From 03c33313ff892e9afa2d8c8334773f6adf0fbefb Mon Sep 17 00:00:00 2001 From: Andreas Gullberg Larsen Date: Sat, 12 Mar 2016 09:25:27 +0100 Subject: [PATCH 01/17] Add UnitsNet.WindowsRuntimeComponent project * Avoid conflict with existing packages.config files --- UnitsNet.sln | 20 +++ UnitsNet/.gitignore | 1 + .../UnitsNet.WindowsRuntimeComponent.csproj | 125 ++++++++++++++++++ ...tsNet.WindowsRuntimeComponent.project.json | 16 +++ 4 files changed, 162 insertions(+) create mode 100644 UnitsNet/.gitignore create mode 100644 UnitsNet/UnitsNet.WindowsRuntimeComponent.csproj create mode 100644 UnitsNet/UnitsNet.WindowsRuntimeComponent.project.json diff --git a/UnitsNet.sln b/UnitsNet.sln index c9de706129..3f10bb910f 100644 --- a/UnitsNet.sln +++ b/UnitsNet.sln @@ -20,6 +20,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{9BEB42C6 Build\UnitsNet.Serialization.JsonNet.nuspec = Build\UnitsNet.Serialization.JsonNet.nuspec EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestApps", "TestApps", "{222FA466-52B9-4C04-916E-6D36B99559B4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitsNet.Uap", "UnitsNet\UnitsNet.Uap.csproj", "{2DA428CA-BFE1-43FA-86D2-7CB42289D596}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -94,6 +98,22 @@ Global {2A76FC53-E331-4CFA-83C0-93A212FD8F6E}.Release|x64.Build.0 = Release|Any CPU {2A76FC53-E331-4CFA-83C0-93A212FD8F6E}.Release|x86.ActiveCfg = Release|Any CPU {2A76FC53-E331-4CFA-83C0-93A212FD8F6E}.Release|x86.Build.0 = Release|Any CPU + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|ARM.ActiveCfg = Debug|ARM + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|ARM.Build.0 = Debug|ARM + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|x64.ActiveCfg = Debug|x64 + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|x64.Build.0 = Debug|x64 + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|x86.ActiveCfg = Debug|x86 + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|x86.Build.0 = Debug|x86 + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|Any CPU.Build.0 = Release|Any CPU + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|ARM.ActiveCfg = Release|ARM + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|ARM.Build.0 = Release|ARM + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|x64.ActiveCfg = Release|x64 + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|x64.Build.0 = Release|x64 + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|x86.ActiveCfg = Release|x86 + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/UnitsNet/.gitignore b/UnitsNet/.gitignore new file mode 100644 index 0000000000..0cae154d35 --- /dev/null +++ b/UnitsNet/.gitignore @@ -0,0 +1 @@ +/*project.lock.json diff --git a/UnitsNet/UnitsNet.WindowsRuntimeComponent.csproj b/UnitsNet/UnitsNet.WindowsRuntimeComponent.csproj new file mode 100644 index 0000000000..eb2aa0cfa3 --- /dev/null +++ b/UnitsNet/UnitsNet.WindowsRuntimeComponent.csproj @@ -0,0 +1,125 @@ + + + + + Debug + AnyCPU + {2DA428CA-BFE1-43FA-86D2-7CB42289D596} + winmdobj + Properties + UnitsNet + UnitsNet + en-US + UAP + 10.0.10586.0 + 10.0.10240.0 + 14 + 512 + {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + false + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + prompt + 4 + + + x86 + true + bin\x86\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + x86 + false + prompt + + + x86 + bin\x86\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + x86 + false + prompt + + + ARM + true + bin\ARM\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + ARM + false + prompt + + + ARM + bin\ARM\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + ARM + false + prompt + + + x64 + true + bin\x64\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + x64 + false + prompt + + + x64 + bin\x64\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + x64 + false + prompt + + + + + + + + + + + 14.0 + + + + \ No newline at end of file diff --git a/UnitsNet/UnitsNet.WindowsRuntimeComponent.project.json b/UnitsNet/UnitsNet.WindowsRuntimeComponent.project.json new file mode 100644 index 0000000000..c594939270 --- /dev/null +++ b/UnitsNet/UnitsNet.WindowsRuntimeComponent.project.json @@ -0,0 +1,16 @@ +{ + "dependencies": { + "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0" + }, + "frameworks": { + "uap10.0": {} + }, + "runtimes": { + "win10-arm": {}, + "win10-arm-aot": {}, + "win10-x86": {}, + "win10-x86-aot": {}, + "win10-x64": {}, + "win10-x64-aot": {} + } +} \ No newline at end of file From 2c5e4614dff3b3fe59950ccd0489d5f46e6e00ef Mon Sep 17 00:00:00 2001 From: Andreas Gullberg Larsen Date: Sun, 13 Mar 2016 20:33:55 +0100 Subject: [PATCH 02/17] uwp: Set output path to Artifacts folder --- UnitsNet/UnitsNet.WindowsRuntimeComponent.csproj | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/UnitsNet/UnitsNet.WindowsRuntimeComponent.csproj b/UnitsNet/UnitsNet.WindowsRuntimeComponent.csproj index eb2aa0cfa3..7d9567e2f0 100644 --- a/UnitsNet/UnitsNet.WindowsRuntimeComponent.csproj +++ b/UnitsNet/UnitsNet.WindowsRuntimeComponent.csproj @@ -17,13 +17,13 @@ 512 {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} false + ..\Artifacts\Bin\Src\$(Platform)_$(Configuration)\uap10.0\ AnyCPU true full false - bin\Debug\ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP prompt 4 @@ -32,15 +32,14 @@ AnyCPU pdbonly true - bin\Release\ TRACE;NETFX_CORE;WINDOWS_UWP prompt 4 + true x86 true - bin\x86\Debug\ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP ;2008 full @@ -50,7 +49,6 @@ x86 - bin\x86\Release\ TRACE;NETFX_CORE;WINDOWS_UWP true ;2008 @@ -62,7 +60,6 @@ ARM true - bin\ARM\Debug\ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP ;2008 full @@ -72,7 +69,6 @@ ARM - bin\ARM\Release\ TRACE;NETFX_CORE;WINDOWS_UWP true ;2008 @@ -84,7 +80,6 @@ x64 true - bin\x64\Debug\ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP ;2008 full @@ -94,7 +89,6 @@ x64 - bin\x64\Release\ TRACE;NETFX_CORE;WINDOWS_UWP true ;2008 From 1130e4761c137312db58499decf92980a659c772 Mon Sep 17 00:00:00 2001 From: Andreas Gullberg Larsen Date: Sat, 12 Mar 2016 13:52:59 +0100 Subject: [PATCH 03/17] uwp: Add dependency JetBrains.Annotations 10.0 --- UnitsNet/UnitsNet.WindowsRuntimeComponent.project.json | 1 + 1 file changed, 1 insertion(+) diff --git a/UnitsNet/UnitsNet.WindowsRuntimeComponent.project.json b/UnitsNet/UnitsNet.WindowsRuntimeComponent.project.json index c594939270..e06088bf84 100644 --- a/UnitsNet/UnitsNet.WindowsRuntimeComponent.project.json +++ b/UnitsNet/UnitsNet.WindowsRuntimeComponent.project.json @@ -1,5 +1,6 @@ { "dependencies": { + "JetBrains.Annotations": "10.0.0", "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0" }, "frameworks": { From 59d340afc15de4d96d21a2c21f636f45e214248e Mon Sep 17 00:00:00 2001 From: Andreas Gullberg Larsen Date: Sat, 12 Mar 2016 09:52:05 +0100 Subject: [PATCH 04/17] uwp: Make exceptions internal and set HRESULT --- UnitsNet/AmbiguousUnitParseException.cs | 9 ++++++++- UnitsNet/UnitsNetException.cs | 10 +++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/UnitsNet/AmbiguousUnitParseException.cs b/UnitsNet/AmbiguousUnitParseException.cs index c9683a780d..ec25ed8387 100644 --- a/UnitsNet/AmbiguousUnitParseException.cs +++ b/UnitsNet/AmbiguousUnitParseException.cs @@ -23,14 +23,21 @@ namespace UnitsNet { - public class AmbiguousUnitParseException : UnitsNetException +#if WINDOWS_UWP + internal +#else + public +#endif + class AmbiguousUnitParseException : UnitsNetException { public AmbiguousUnitParseException(string message) : base(message) { + HResult = 2; } public AmbiguousUnitParseException(string message, Exception innerException) : base(message, innerException) { + HResult = 2; } } } \ No newline at end of file diff --git a/UnitsNet/UnitsNetException.cs b/UnitsNet/UnitsNetException.cs index ec344ee054..0a08b11d94 100644 --- a/UnitsNet/UnitsNetException.cs +++ b/UnitsNet/UnitsNetException.cs @@ -23,18 +23,26 @@ namespace UnitsNet { - public class UnitsNetException : Exception +#if WINDOWS_UWP + internal +#else + public +#endif + class UnitsNetException : Exception { public UnitsNetException() { + HResult = 1; } public UnitsNetException(string message) : base(message) { + HResult = 1; } public UnitsNetException(string message, Exception innerException) : base(message, innerException) { + HResult = 1; } } } \ No newline at end of file From cd763c8757ea8eb8478c6630ec67388f4d47c6d4 Mon Sep 17 00:00:00 2001 From: Andreas Gullberg Larsen Date: Sat, 12 Mar 2016 13:51:24 +0100 Subject: [PATCH 05/17] uwp: Add conditionals for Vector2/3 and Length2d --- UnitsNet/Length2d.cs | 12 ++++++++++++ UnitsNet/Vector2.cs | 12 ++++++++++-- UnitsNet/Vector3.cs | 9 +++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/UnitsNet/Length2d.cs b/UnitsNet/Length2d.cs index 40d12299de..a61907649f 100644 --- a/UnitsNet/Length2d.cs +++ b/UnitsNet/Length2d.cs @@ -19,15 +19,26 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +#if !WINDOWS_UWP using System; using System.Collections.Generic; using UnitsNet.Units; +#endif namespace UnitsNet { /// /// A class for representing position in two dimensions. /// +#if WINDOWS_UWP + public struct Length2d + { + /// + /// Returns a point represented in meters. + /// + public Vector2 Meters; + } +#else public struct Length2d : IEquatable { /// @@ -244,4 +255,5 @@ public int GetHashCode(Length2d obj) #endregion } +#endif } \ No newline at end of file diff --git a/UnitsNet/Vector2.cs b/UnitsNet/Vector2.cs index 40b97519e2..aab5e7cb74 100644 --- a/UnitsNet/Vector2.cs +++ b/UnitsNet/Vector2.cs @@ -24,6 +24,13 @@ namespace UnitsNet { +#if WINDOWS_UWP + public struct Vector2 + { + public double X; + public double Y; + } +#else public struct Vector2 : IEquatable { public readonly double X; @@ -41,7 +48,7 @@ public Vector2(double xy) : this() Y = xy; } - #region Equality +#region Equality private static IEqualityComparer XyComparer { get; } = new XyEqualityComparer(); @@ -90,11 +97,12 @@ public int GetHashCode(Vector2 obj) } } - #endregion +#endregion public override string ToString() { return $"[{X:0.####}, {Y:0.####}]"; } } +#endif } \ No newline at end of file diff --git a/UnitsNet/Vector3.cs b/UnitsNet/Vector3.cs index cbc0250215..276e03b047 100644 --- a/UnitsNet/Vector3.cs +++ b/UnitsNet/Vector3.cs @@ -24,6 +24,14 @@ namespace UnitsNet { +#if WINDOWS_UWP + public struct Vector3 + { + public double X; + public double Y; + public double Z; + } +#else public struct Vector3 : IEquatable { public readonly double X; @@ -96,4 +104,5 @@ public override string ToString() return $"[{X:0.####}, {Y:0.####}, {Z:0.####}]"; } } +#endif } \ No newline at end of file From 325a8d0b8800b1a564c4e0a8830a1d2b3b92762e Mon Sep 17 00:00:00 2001 From: Andreas Gullberg Larsen Date: Sat, 12 Mar 2016 14:57:20 +0100 Subject: [PATCH 06/17] uwp: Add conditionals to UnitSystem + generator --- UnitsNet/CustomCode/UnitSystem.cs | 287 +++++++++++++----- .../GeneratedCode/UnitSystem.Default.g.cs | 2 +- ...de-GenerateUnitSystemDefaultSourceCode.ps1 | 2 +- UnitsNet/UnitFormatter.cs | 2 +- 4 files changed, 217 insertions(+), 76 deletions(-) diff --git a/UnitsNet/CustomCode/UnitSystem.cs b/UnitsNet/CustomCode/UnitSystem.cs index acf625257c..b3002b9f0f 100644 --- a/UnitsNet/CustomCode/UnitSystem.cs +++ b/UnitsNet/CustomCode/UnitSystem.cs @@ -26,17 +26,30 @@ using JetBrains.Annotations; using UnitsNet.I18n; -// ReSharper disable once CheckNamespace - - +#if WINDOWS_UWP +using System.Reflection; +#endif +// ReSharper disable once CheckNamespace namespace UnitsNet { [PublicAPI] - public partial class UnitSystem + public sealed partial class UnitSystem { private static readonly Dictionary CultureToInstance; - private static readonly CultureInfo DefaultCulture = new CultureInfo("en-US"); + + /// + /// Fallback culture used by and + /// + /// if no abbreviations are found with current . + /// + /// + /// User wants to call or with Russian + /// culture, but no translation is defined, so we return the US English definition as a last resort. If it's not + /// defined there either, an exception is thrown. + /// + private static readonly CultureInfo FallbackCulture = new CultureInfo("en-US"); + private static readonly object LockUnitSystemCache = new object(); /// @@ -54,22 +67,43 @@ public partial class UnitSystem /// /// The culture of which this unit system is based on. Either passed in to constructor or the default culture. /// - [NotNull] [PublicAPI] public readonly IFormatProvider Culture; + [NotNull] [PublicAPI] internal readonly IFormatProvider Culture; static UnitSystem() { CultureToInstance = new Dictionary(); } + /// + /// Create unit system for parsing and generating strings with the English US culture. + /// + public UnitSystem() : this(DefaultCulture) + { + } + /// /// Create unit system for parsing and generating strings of the specified culture. /// If null is specified, the default English US culture will be used. /// /// - public UnitSystem([CanBeNull] IFormatProvider cultureInfo = null) + public UnitSystem([CanBeNull] string cultureInfo) : this(cultureInfo != null ? new CultureInfo(cultureInfo) : DefaultCulture) + { + } + + /// + /// Create unit system for parsing and generating strings of the specified culture. + /// If null is specified, the default English US culture will be used. + /// + /// +#if WINDOWS_UWP + internal +#else + public +#endif + UnitSystem([CanBeNull] IFormatProvider cultureInfo) { if (cultureInfo == null) - cultureInfo = new CultureInfo(DefaultCulture.Name); + cultureInfo = DefaultCulture; Culture = cultureInfo; _unitTypeToUnitValueToAbbrevs = new Dictionary>>(); @@ -78,7 +112,13 @@ public UnitSystem([CanBeNull] IFormatProvider cultureInfo = null) LoadDefaultAbbreviatons(cultureInfo); } - public bool IsDefaultCulture => Culture.Equals(DefaultCulture); + /// + /// Default culture if none is specified in constructor or is always + /// . + /// + private static IFormatProvider DefaultCulture => CultureInfo.CurrentUICulture; + + public bool IsFallbackCulture => Culture.Equals(FallbackCulture); [PublicAPI] public static void ClearCache() @@ -94,13 +134,36 @@ public static void ClearCache() /// Creating can be a little expensive, so it will use a static cache. /// To always create, use the constructor. /// - /// Culture to use. If null then will be used. /// [PublicAPI] - public static UnitSystem GetCached(IFormatProvider cultureInfo = null) + public static UnitSystem GetCached() + { + return GetCached((CultureInfo)null); + } + + /// + /// Get or create a unit system for parsing and presenting numbers, units and abbreviations. + /// Creating can be a little expensive, so it will use a static cache. + /// To always create, use the constructor. + /// + /// Culture to use. If null then will be used. + /// + [PublicAPI] + public static UnitSystem GetCached([CanBeNull] string cultureName) + { + var cultureInfo = cultureName == null ? DefaultCulture : new CultureInfo(cultureName); + return GetCached(cultureInfo); + } + +#if WINDOWS_UWP + internal +#else + public +#endif + static UnitSystem GetCached([CanBeNull] IFormatProvider cultureInfo) { if (cultureInfo == null) - cultureInfo = CultureInfo.CurrentUICulture; + cultureInfo = DefaultCulture; lock (LockUnitSystemCache) { @@ -113,62 +176,92 @@ public static UnitSystem GetCached(IFormatProvider cultureInfo = null) } [PublicAPI] - public static TUnit Parse(string unitAbbreviation, CultureInfo culture) +#if WINDOWS_UWP + internal +#else + public +#endif + static TUnit Parse(string unitAbbreviation, CultureInfo culture) where TUnit : /*Enum constraint hack*/ struct, IComparable, IFormattable { return GetCached(culture).Parse(unitAbbreviation); } [PublicAPI] - public TUnit Parse(string unitAbbreviation) +#if WINDOWS_UWP + internal +#else + public +#endif + TUnit Parse(string unitAbbreviation) where TUnit : /*Enum constraint hack*/ struct, IComparable, IFormattable { - Type unitType = typeof (TUnit); + return (TUnit) Parse(unitAbbreviation, typeof (TUnit)); + } + + [PublicAPI] + public object Parse(string unitAbbreviation, Type unitType) + { AbbreviationMap abbrevToUnitValue; if (!_unitTypeToAbbrevToUnitValue.TryGetValue(unitType, out abbrevToUnitValue)) throw new NotImplementedException( $"No abbreviations defined for unit type [{unitType}] for culture [{Culture}]."); - List unitValues; - List units; - - if (abbrevToUnitValue.TryGetValue(unitAbbreviation, out unitValues)) - { - units = unitValues.Cast().Distinct().ToList(); - } - else - { - units = new List(); - } + List unitIntValues; + List unitValues = abbrevToUnitValue.TryGetValue(unitAbbreviation, out unitIntValues) + ? unitIntValues.Distinct().Cast().ToList() + : new List(); - switch (units.Count) + switch (unitValues.Count) { case 1: - return units[0]; + return unitValues[0]; case 0: - return default(TUnit); + return 0; default: - var unitsCsv = String.Join(", ", units.Select(x => x.ToString()).ToArray()); - throw new AmbiguousUnitParseException($"Cannot parse '{unitAbbreviation}' since it could be either of these: {unitsCsv}"); + var unitsCsv = string.Join(", ", unitValues.Select(x => x.ToString()).ToArray()); + throw new AmbiguousUnitParseException( + $"Cannot parse '{unitAbbreviation}' since it could be either of these: {unitsCsv}"); } } [PublicAPI] - public static string GetDefaultAbbreviation(TUnit unit, CultureInfo culture) +#if WINDOWS_UWP + internal +#else + public +#endif + static string GetDefaultAbbreviation(TUnit unit, CultureInfo culture) where TUnit : /*Enum constraint hack*/ struct, IComparable, IFormattable { return GetCached(culture).GetDefaultAbbreviation(unit); } [PublicAPI] - public string GetDefaultAbbreviation(TUnit unit) +#if WINDOWS_UWP + internal +#else + public +#endif + string GetDefaultAbbreviation(TUnit unit) where TUnit : /*Enum constraint hack*/ struct, IComparable, IFormattable { return GetAllAbbreviations(unit).First(); } [PublicAPI] - public void MapUnitToAbbreviation(TUnit unit, params string[] abbreviations) + public string GetDefaultAbbreviation(Type unitType, int unitValue) + { + return GetAllAbbreviations(unitType, unitValue).First(); + } + + [PublicAPI] +#if WINDOWS_UWP + internal +#else + public +#endif + void MapUnitToAbbreviation(TUnit unit, params string[] abbreviations) where TUnit : /*Enum constraint hack*/ struct, IComparable, IFormattable { // Assuming TUnit is an enum, this conversion is safe. Seems not possible to enforce this today. @@ -180,9 +273,18 @@ public void MapUnitToAbbreviation(TUnit unit, params string[] abbreviatio } [PublicAPI] - public void MapUnitToAbbreviation(Type unitType, int unitValue, [NotNull] params string[] abbreviations) +#if WINDOWS_UWP + internal +#else + public +#endif + void MapUnitToAbbreviation(Type unitType, int unitValue, [NotNull] params string[] abbreviations) { +#if WINDOWS_UWP + if (!unitType.GetTypeInfo().IsEnum) +#else if (!unitType.IsEnum) +#endif throw new ArgumentException("Must be an enum type.", nameof(unitType)); if (abbreviations == null) @@ -220,36 +322,38 @@ public void MapUnitToAbbreviation(Type unitType, int unitValue, [NotNull] params } [PublicAPI] - public bool TryParse(string unitAbbreviation, out TUnit unit) +#if WINDOWS_UWP + internal +#else + public +#endif + bool TryParse(string unitAbbreviation, out TUnit unit) where TUnit : /*Enum constraint hack*/ struct, IComparable, IFormattable { - Type unitType = typeof (TUnit); - - AbbreviationMap abbrevToUnitValue; - List unitValues; - - if (!_unitTypeToAbbrevToUnitValue.TryGetValue(unitType, out abbrevToUnitValue) || - !abbrevToUnitValue.TryGetValue(unitAbbreviation, out unitValues)) + try { - if (IsDefaultCulture) - { - unit = default(TUnit); - return false; - } - - // Fall back to default culture - return GetCached(DefaultCulture).TryParse(unitAbbreviation, out unit); + unit = (TUnit)Parse(unitAbbreviation, typeof (TUnit)); + return true; } + catch + { + unit = default(TUnit); + return false; + } + } - var maps = (List) (object) unitValues; - - switch (maps.Count) + [PublicAPI] + public bool TryParse(string unitAbbreviation, Type unitType, out object unit) + { + try { - case 1: unit = maps[0]; - return true; - default: - unit = default(TUnit); - return false; + unit = Parse(unitAbbreviation, unitType); + return true; + } + catch + { + unit = GetDefault(unitType); + return false; } } @@ -260,28 +364,50 @@ public bool TryParse(string unitAbbreviation, out TUnit unit) /// Enum value for unit. /// Unit abbreviations associated with unit. [PublicAPI] - public string[] GetAllAbbreviations(TUnit unit) +#if WINDOWS_UWP + internal +#else + public +#endif + string[] GetAllAbbreviations(TUnit unit) where TUnit : /*Enum constraint hack*/ struct, IComparable, IFormattable { - Type unitType = typeof (TUnit); - int unitValue = Convert.ToInt32(unit); - Dictionary> unitValueToAbbrevs; List abbrevs; - if (!_unitTypeToUnitValueToAbbrevs.TryGetValue(unitType, out unitValueToAbbrevs) || - !unitValueToAbbrevs.TryGetValue(unitValue, out abbrevs)) + if (_unitTypeToUnitValueToAbbrevs.TryGetValue(typeof(TUnit), out unitValueToAbbrevs) && + unitValueToAbbrevs.TryGetValue((int)(object)unit, out abbrevs)) { - if (IsDefaultCulture) - { - return new[] {$"(no abbreviation for {unitType.Name}.{unit})"}; - } + return abbrevs.ToArray(); + } + + return IsFallbackCulture + ? new[] {$"(no abbreviation for {typeof(TUnit).Name}.{unit})"} + : GetCached(FallbackCulture).GetAllAbbreviations(unit); + } + + /// + /// Get all abbreviations for unit. + /// + /// Enum type for unit. + /// Enum value for unit. + /// Unit abbreviations associated with unit. + [PublicAPI] + public string[] GetAllAbbreviations(Type unitType, int unitValue) + { + Dictionary> unitValueToAbbrevs; + List abbrevs; - // Fall back to default culture - return GetCached(DefaultCulture).GetAllAbbreviations(unit); + if (_unitTypeToUnitValueToAbbrevs.TryGetValue(unitType, out unitValueToAbbrevs) && + unitValueToAbbrevs.TryGetValue(unitValue, out abbrevs)) + { + return abbrevs.ToArray(); } - return abbrevs.ToArray(); + // Fall back to default culture + return IsFallbackCulture + ? new[] {$"(no abbreviation for {unitType.Name} with numeric value {unitValue})"} + : GetCached(FallbackCulture).GetAllAbbreviations(unitType, unitValue); } private void LoadDefaultAbbreviatons([NotNull] IFormatProvider culture) @@ -311,9 +437,24 @@ private void LoadDefaultAbbreviatons([NotNull] IFormatProvider culture) /// /// Avoids having too many nested generics for code clarity /// - class AbbreviationMap : Dictionary> + private class AbbreviationMap : Dictionary> { } + + /// + /// Get default(Type) of . + /// Null for reference types, 0 for numeric types and default constructor for the rest. + /// + private static object GetDefault(Type type) + { + return type +#if WINDOWS_UWP + .GetTypeInfo() +#endif + .IsValueType + ? Activator.CreateInstance(type) + : null; + } } } \ No newline at end of file diff --git a/UnitsNet/GeneratedCode/UnitSystem.Default.g.cs b/UnitsNet/GeneratedCode/UnitSystem.Default.g.cs index f4f4e11773..e322d949f5 100644 --- a/UnitsNet/GeneratedCode/UnitSystem.Default.g.cs +++ b/UnitsNet/GeneratedCode/UnitSystem.Default.g.cs @@ -29,7 +29,7 @@ namespace UnitsNet { - public partial class UnitSystem + public sealed partial class UnitSystem { private static readonly ReadOnlyCollection DefaultLocalizations = new ReadOnlyCollection(new List diff --git a/UnitsNet/Scripts/Include-GenerateUnitSystemDefaultSourceCode.ps1 b/UnitsNet/Scripts/Include-GenerateUnitSystemDefaultSourceCode.ps1 index eb8f6fd4a1..04ab5cac84 100644 --- a/UnitsNet/Scripts/Include-GenerateUnitSystemDefaultSourceCode.ps1 +++ b/UnitsNet/Scripts/Include-GenerateUnitSystemDefaultSourceCode.ps1 @@ -32,7 +32,7 @@ using UnitsNet.Units; namespace UnitsNet { - public partial class UnitSystem + public sealed partial class UnitSystem { private static readonly ReadOnlyCollection DefaultLocalizations = new ReadOnlyCollection(new List diff --git a/UnitsNet/UnitFormatter.cs b/UnitsNet/UnitFormatter.cs index f52e9f8301..f0714df0a2 100644 --- a/UnitsNet/UnitFormatter.cs +++ b/UnitsNet/UnitFormatter.cs @@ -93,7 +93,7 @@ private static bool NearlyEqual(double a, double b) public static object[] GetFormatArgs(TUnit unit, double value, [CanBeNull] CultureInfo culture, IEnumerable args) where TUnit : struct, IComparable, IFormattable { - string abbreviation = UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); + string abbreviation = UnitSystem.GetCached(culture).GetDefaultAbbreviation(typeof(TUnit), Convert.ToInt32(unit)); return new object[] { value, abbreviation }.Concat(args).ToArray(); } } From 903563c3c059be1a136d70049ac113b332cfb280 Mon Sep 17 00:00:00 2001 From: Andreas Gullberg Larsen Date: Sat, 12 Mar 2016 16:07:33 +0100 Subject: [PATCH 07/17] uwp: Add conditionals to unit class generator Add long/double/decimal constructors and add conditionals * Convenience constructors for all unit classes * If UWP, only expose constructor with double type * Use type alias Culture to represent IFormatProvider vs string --- .../Include-GenerateLogarithmicCode.ps1 | 2 + .../Include-GenerateUnitClassSourceCode.ps1 | 218 ++++++++++++++++-- UnitsNet/UnitFormatter.cs | 3 +- 3 files changed, 200 insertions(+), 23 deletions(-) diff --git a/UnitsNet/Scripts/Include-GenerateLogarithmicCode.ps1 b/UnitsNet/Scripts/Include-GenerateLogarithmicCode.ps1 index 9cdd8aa74b..af2734cefc 100644 --- a/UnitsNet/Scripts/Include-GenerateLogarithmicCode.ps1 +++ b/UnitsNet/Scripts/Include-GenerateLogarithmicCode.ps1 @@ -24,6 +24,7 @@ function GenerateLogarithmicArithmeticOperators([string]$className, [string]$bas #region Logarithmic Arithmetic Operators +#if !WINDOWS_UWP public static $className operator -($className right) { return new $className(-right.$baseUnitFieldName); @@ -66,6 +67,7 @@ function GenerateLogarithmicArithmeticOperators([string]$className, [string]$bas // Logarithmic division = subtraction return Convert.ToDouble(left.$baseUnitFieldName - right.$baseUnitFieldName); } +#endif #endregion "@; diff --git a/UnitsNet/Scripts/Include-GenerateUnitClassSourceCode.ps1 b/UnitsNet/Scripts/Include-GenerateUnitClassSourceCode.ps1 index c1c1839d77..9597b8a9fa 100644 --- a/UnitsNet/Scripts/Include-GenerateUnitClassSourceCode.ps1 +++ b/UnitsNet/Scripts/Include-GenerateUnitClassSourceCode.ps1 @@ -10,6 +10,23 @@ function GenerateUnitClassSourceCode($unitClass) $unitEnumName = "$className" + "Unit"; $baseUnitFieldName = "_"+[Char]::ToLowerInvariant($baseUnitPluralName[0]) + $baseUnitPluralName.Substring(1); + switch ($baseType) { + long { + $convertToBaseType = "Convert.ToInt64" + break + } + double { + $convertToBaseType = "Convert.ToDouble" + break + } + decimal { + $convertToBaseType = "Convert.ToDecimal" + break + } + default { + throw "Base type not supported: $baseType" + } + } @" // Copyright � 2007 by Initial Force AS. All rights reserved. // https://github.com/anjdreas/UnitsNet @@ -40,6 +57,12 @@ using System.Linq; using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -48,16 +71,49 @@ namespace UnitsNet /// $($unitClass.XmlDoc) /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class $className +#else public partial struct $className : IComparable, IComparable<$className> +#endif { /// /// Base unit of $className. /// private readonly $baseType $baseUnitFieldName; - public $className($baseType $baseUnitPluralNameLower) : this() +#if WINDOWS_UWP + public $className() : this(0) + { + } +#endif + + public $className(double $baseUnitPluralNameLower) + { + $baseUnitFieldName = $convertToBaseType($baseUnitPluralNameLower); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + $className(long $baseUnitPluralNameLower) { - $baseUnitFieldName = $baseUnitPluralNameLower; + $baseUnitFieldName = $convertToBaseType($baseUnitPluralNameLower); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + $className(decimal $baseUnitPluralNameLower) + { + $baseUnitFieldName = $convertToBaseType($baseUnitPluralNameLower); } #region Properties @@ -106,7 +162,7 @@ namespace UnitsNet } "@; }@" - +#if !WINDOWS_UWP "@; foreach ($unit in $units) { $valueParamName = $unit.PluralName.ToLowerInvariant(); $func = $unit.FromUnitToBaseFunc.Replace("x", "$($valueParamName).Value");@" @@ -121,25 +177,26 @@ namespace UnitsNet } else { - return null; + return null; } } "@; }@" +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// $className unit value. - public static $className From(double value, $unitEnumName fromUnit) + public static $className From(double val, $unitEnumName fromUnit) { switch (fromUnit) { "@; foreach ($unit in $units) {@" case $unitEnumName.$($unit.SingularName): - return From$($unit.PluralName)(value); + return From$($unit.PluralName)(val); "@; }@" default: @@ -147,6 +204,7 @@ namespace UnitsNet } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -170,6 +228,18 @@ namespace UnitsNet throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation($unitEnumName unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -178,7 +248,7 @@ namespace UnitsNet /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation($unitEnumName unit, CultureInfo culture = null) + public static string GetAbbreviation($unitEnumName unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -192,6 +262,7 @@ namespace UnitsNet #region Arithmetic Operators +#if !WINDOWS_UWP public static $className operator -($className right) { return new $className(-right.$baseUnitFieldName); @@ -226,6 +297,7 @@ namespace UnitsNet { return Convert.ToDouble(left.$baseUnitFieldName/right.$baseUnitFieldName); } +#endif #endregion "@; }@" @@ -239,11 +311,17 @@ namespace UnitsNet return CompareTo(($className) obj); } - public int CompareTo($className other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo($className other) { return $baseUnitFieldName.CompareTo(other.$baseUnitFieldName); } +#if !WINDOWS_UWP public static bool operator <=($className left, $className right) { return left.$baseUnitFieldName <= right.$baseUnitFieldName; @@ -275,6 +353,7 @@ namespace UnitsNet // ReSharper disable once CompareOfFloatsByEqualityOperator return left.$baseUnitFieldName != right.$baseUnitFieldName; } +#endif public override bool Equals(object obj) { @@ -322,7 +401,6 @@ namespace UnitsNet /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -341,10 +419,43 @@ namespace UnitsNet /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static $className Parse(string str, IFormatProvider formatProvider = null) + public static $className Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static $className Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -368,7 +479,7 @@ namespace UnitsNet "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => $className.From$baseUnitPluralName(x.$baseUnitPluralName + y.$baseUnitPluralName)); } /// @@ -405,7 +516,7 @@ namespace UnitsNet converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -430,18 +541,49 @@ namespace UnitsNet /// /// The value of 'str' cannot be null. /// Error parsing string. - public static $unitEnumName ParseUnit(string str, IFormatProvider formatProvider = null) + public static $unitEnumName ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static $unitEnumName ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static $unitEnumName ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse<$unitEnumName>(str.Trim()); if (unit == $unitEnumName.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized $unitEnumName."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -464,6 +606,27 @@ namespace UnitsNet return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString($unitEnumName unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString($unitEnumName unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -472,9 +635,11 @@ namespace UnitsNet /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString($unitEnumName unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString($unitEnumName unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -486,9 +651,20 @@ namespace UnitsNet /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString($unitEnumName unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString($unitEnumName unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/UnitFormatter.cs b/UnitsNet/UnitFormatter.cs index f0714df0a2..3fd1a7a223 100644 --- a/UnitsNet/UnitFormatter.cs +++ b/UnitsNet/UnitFormatter.cs @@ -21,7 +21,6 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using JetBrains.Annotations; @@ -90,7 +89,7 @@ private static bool NearlyEqual(double a, double b) /// The current culture. /// The list of format arguments. /// An array of ToString format arguments. - public static object[] GetFormatArgs(TUnit unit, double value, [CanBeNull] CultureInfo culture, IEnumerable args) + public static object[] GetFormatArgs(TUnit unit, double value, [CanBeNull] IFormatProvider culture, IEnumerable args) where TUnit : struct, IComparable, IFormattable { string abbreviation = UnitSystem.GetCached(culture).GetDefaultAbbreviation(typeof(TUnit), Convert.ToInt32(unit)); From 702117cda5615130633b0f9d7f9474f16584f81e Mon Sep 17 00:00:00 2001 From: Andreas Gullberg Larsen Date: Sun, 13 Mar 2016 21:59:09 +0100 Subject: [PATCH 08/17] uwp: Add conditionals to CustomCode Exclude operator overloads Use sealed class instead of struct Extract extensions code to separate files --- .../CustomCode/AmplitudeRatioTests.cs | 1 + UnitsNet.Tests/CustomCode/PowerRatioTests.cs | 1 + .../Extensions/AmplitudeRatioExtensions.cs | 34 ++++++++++ .../Extensions/ElectricPotentialExtensions.cs | 23 +++++++ .../CustomCode/Extensions/PowerExtensions.cs | 22 ++++++ .../Extensions/PowerRatioExtensions.cs | 32 +++++++++ .../UnitClasses/AmplitudeRatio.extra.cs | 67 ++++--------------- .../CustomCode/UnitClasses/Angle.extra.cs | 5 +- UnitsNet/CustomCode/UnitClasses/Area.extra.cs | 5 +- .../BrakeSpecificFuelConsumption.extra.cs | 5 +- .../CustomCode/UnitClasses/Density.extra.cs | 5 +- .../CustomCode/UnitClasses/Duration.extra.cs | 27 +++++--- .../UnitClasses/DynamicViscosity.extra.cs | 5 +- .../CustomCode/UnitClasses/Force.extra.cs | 10 +++ .../UnitClasses/KinematicViscosity.extra.cs | 5 +- .../CustomCode/UnitClasses/Length.extra.cs | 43 ++++++++---- .../CustomCode/UnitClasses/Level.extra.cs | 4 ++ UnitsNet/CustomCode/UnitClasses/Mass.extra.cs | 24 ++++++- .../CustomCode/UnitClasses/MassFlow.extra.cs | 5 +- .../CustomCode/UnitClasses/Power.extra.cs | 5 +- .../UnitClasses/PowerRatio.extra.cs | 63 +++-------------- .../CustomCode/UnitClasses/Pressure.extra.cs | 5 +- .../UnitClasses/RotationalSpeed.extra.cs | 5 +- .../UnitClasses/SpecificEnergy.extra.cs | 5 +- .../CustomCode/UnitClasses/Speed.extra.cs | 3 + .../CustomCode/UnitClasses/Torque.extra.cs | 5 +- .../CustomCode/UnitClasses/Volume.extra.cs | 5 +- 27 files changed, 272 insertions(+), 147 deletions(-) create mode 100644 UnitsNet/CustomCode/Extensions/AmplitudeRatioExtensions.cs create mode 100644 UnitsNet/CustomCode/Extensions/ElectricPotentialExtensions.cs create mode 100644 UnitsNet/CustomCode/Extensions/PowerExtensions.cs create mode 100644 UnitsNet/CustomCode/Extensions/PowerRatioExtensions.cs diff --git a/UnitsNet.Tests/CustomCode/AmplitudeRatioTests.cs b/UnitsNet.Tests/CustomCode/AmplitudeRatioTests.cs index 279b578247..5222c464ce 100644 --- a/UnitsNet.Tests/CustomCode/AmplitudeRatioTests.cs +++ b/UnitsNet.Tests/CustomCode/AmplitudeRatioTests.cs @@ -21,6 +21,7 @@ using System; using NUnit.Framework; +using UnitsNet.CustomCode.Extensions; namespace UnitsNet.Tests.CustomCode { diff --git a/UnitsNet.Tests/CustomCode/PowerRatioTests.cs b/UnitsNet.Tests/CustomCode/PowerRatioTests.cs index 5ab98971ae..a2bcebfcff 100644 --- a/UnitsNet.Tests/CustomCode/PowerRatioTests.cs +++ b/UnitsNet.Tests/CustomCode/PowerRatioTests.cs @@ -21,6 +21,7 @@ using System; using NUnit.Framework; +using UnitsNet.CustomCode.Extensions; namespace UnitsNet.Tests.CustomCode { diff --git a/UnitsNet/CustomCode/Extensions/AmplitudeRatioExtensions.cs b/UnitsNet/CustomCode/Extensions/AmplitudeRatioExtensions.cs new file mode 100644 index 0000000000..cec7679b5e --- /dev/null +++ b/UnitsNet/CustomCode/Extensions/AmplitudeRatioExtensions.cs @@ -0,0 +1,34 @@ +namespace UnitsNet.CustomCode.Extensions +{ + /// + /// Extension methods for . + /// + public static class AmplitudeRatioExtensions + { + /// + /// Gets an from . + /// + /// The amplitude ratio to convert. + /// + /// Provides a nicer syntax for converting an amplitude ratio back to a voltage. + /// + /// var voltage = voltageRatio.ToElectricPotential(); + /// + /// + public static ElectricPotential ToElectricPotential(this AmplitudeRatio amplitudeRatio) + { + return AmplitudeRatio.ToElectricPotential(amplitudeRatio); + } + + /// + /// Converts a to a . + /// + /// The amplitude ratio to convert. + /// The input impedance of the load. This is usually 50, 75 or 600 ohms. + /// http://www.maximintegrated.com/en/app-notes/index.mvp/id/808 + public static PowerRatio ToPowerRatio(this AmplitudeRatio amplitudeRatio, ElectricResistance impedance) + { + return AmplitudeRatio.ToPowerRatio(amplitudeRatio, impedance); + } + } +} \ No newline at end of file diff --git a/UnitsNet/CustomCode/Extensions/ElectricPotentialExtensions.cs b/UnitsNet/CustomCode/Extensions/ElectricPotentialExtensions.cs new file mode 100644 index 0000000000..b068c32782 --- /dev/null +++ b/UnitsNet/CustomCode/Extensions/ElectricPotentialExtensions.cs @@ -0,0 +1,23 @@ +namespace UnitsNet.CustomCode.Extensions +{ + /// + /// Extension methods for . + /// + public static class ElectricPotentialExtensions + { + /// + /// Gets an in decibels (dB) relative to 1 volt RMS from an + /// . + /// + /// + /// Provides a nicer syntax for converting a voltage to an amplitude ratio (relative to 1 volt RMS). + /// + /// var voltageRatio = voltage.ToAmplitudeRatio(); + /// + /// + public static AmplitudeRatio ToAmplitudeRatio(this ElectricPotential voltage) + { + return AmplitudeRatio.FromElectricPotential(voltage); + } + } +} \ No newline at end of file diff --git a/UnitsNet/CustomCode/Extensions/PowerExtensions.cs b/UnitsNet/CustomCode/Extensions/PowerExtensions.cs new file mode 100644 index 0000000000..c7f107ebac --- /dev/null +++ b/UnitsNet/CustomCode/Extensions/PowerExtensions.cs @@ -0,0 +1,22 @@ +namespace UnitsNet.CustomCode.Extensions +{ + /// + /// Extension methods for . + /// + public static class PowerExtensions + { + /// + /// Gets a from a relative to one watt. + /// + /// + /// Provides a nicer syntax for converting a power to a power ratio (relative to 1 watt). + /// + /// var powerRatio = power.ToPowerRatio(); + /// + /// + public static PowerRatio ToPowerRatio(this Power power) + { + return PowerRatio.FromPower(power); + } + } +} \ No newline at end of file diff --git a/UnitsNet/CustomCode/Extensions/PowerRatioExtensions.cs b/UnitsNet/CustomCode/Extensions/PowerRatioExtensions.cs new file mode 100644 index 0000000000..4c1ed13541 --- /dev/null +++ b/UnitsNet/CustomCode/Extensions/PowerRatioExtensions.cs @@ -0,0 +1,32 @@ +namespace UnitsNet.CustomCode.Extensions +{ + /// + /// Extension methods for . + /// + public static class PowerRatioExtensions + { + /// + /// Gets a from a . + /// + /// + /// Provides a nicer syntax for converting a power ratio back to a power. + /// + /// var power = powerRatio.ToPower(); + /// + /// + public static Power ToPower(this PowerRatio powerRatio) + { + return PowerRatio.ToPower(powerRatio); + } + + /// + /// Gets a from a . + /// + /// The power ratio. + /// The input impedance of the load. This is usually 50, 75 or 600 ohms. + public static AmplitudeRatio ToAmplitudeRatio(this PowerRatio powerRatio, ElectricResistance impedance) + { + return PowerRatio.ToAmplitudeRatio(powerRatio, impedance); + } + } +} \ No newline at end of file diff --git a/UnitsNet/CustomCode/UnitClasses/AmplitudeRatio.extra.cs b/UnitsNet/CustomCode/UnitClasses/AmplitudeRatio.extra.cs index fc71fc2ecf..839c7fa9c2 100644 --- a/UnitsNet/CustomCode/UnitClasses/AmplitudeRatio.extra.cs +++ b/UnitsNet/CustomCode/UnitClasses/AmplitudeRatio.extra.cs @@ -23,60 +23,11 @@ namespace UnitsNet { - /// - /// Extension methods for . - /// - public static class AmplitudeRatioExtensions - { - /// - /// Gets an from . - /// - /// The amplitude ratio to convert. - /// - /// Provides a nicer syntax for converting an amplitude ratio back to a voltage. - /// - /// var voltage = voltageRatio.ToElectricPotential(); - /// - /// - public static ElectricPotential ToElectricPotential(this AmplitudeRatio amplitudeRatio) - { - return AmplitudeRatio.ToElectricPotential(amplitudeRatio); - } - - /// - /// Converts a to a . - /// - /// The amplitude ratio to convert. - /// The input impedance of the load. This is usually 50, 75 or 600 ohms. - /// http://www.maximintegrated.com/en/app-notes/index.mvp/id/808 - public static PowerRatio ToPowerRatio(this AmplitudeRatio amplitudeRatio, ElectricResistance impedance) - { - return AmplitudeRatio.ToPowerRatio(amplitudeRatio, impedance); - } - } - - /// - /// Extension methods for . - /// - public static class ElectricPotentialExtensions - { - /// - /// Gets an in decibels (dB) relative to 1 volt RMS from an - /// . - /// - /// - /// Provides a nicer syntax for converting a voltage to an amplitude ratio (relative to 1 volt RMS). - /// - /// var voltageRatio = voltage.ToAmplitudeRatio(); - /// - /// - public static AmplitudeRatio ToAmplitudeRatio(this ElectricPotential voltage) - { - return AmplitudeRatio.FromElectricPotential(voltage); - } - } - +#if WINDOWS_UWP + public sealed partial class AmplitudeRatio +#else public partial struct AmplitudeRatio +#endif { /// /// Initializes a new instance of the struct from the specified electric potential @@ -85,7 +36,13 @@ public partial struct AmplitudeRatio /// resistance. /// /// The electric potential referenced to one volt. - public AmplitudeRatio(ElectricPotential voltage) + // Operator overloads not supported in Universal Windows Platform (WinRT Components) +#if WINDOWS_UWP + internal +#else + public +#endif + AmplitudeRatio(ElectricPotential voltage) : this() { if (voltage.Volts <= 0) @@ -94,7 +51,7 @@ public AmplitudeRatio(ElectricPotential voltage) "The base-10 logarithm of a number ≤ 0 is undefined. Voltage must be greater than 0 V."); // E(dBV) = 20*log10(value(V)/reference(V)) - _decibelVolts = 20*Math.Log10(voltage/ElectricPotential.FromVolts(1)); + _decibelVolts = 20*Math.Log10(voltage.Volts/1); } /// diff --git a/UnitsNet/CustomCode/UnitClasses/Angle.extra.cs b/UnitsNet/CustomCode/UnitClasses/Angle.extra.cs index 4dd592d71a..ab19a88caf 100644 --- a/UnitsNet/CustomCode/UnitClasses/Angle.extra.cs +++ b/UnitsNet/CustomCode/UnitClasses/Angle.extra.cs @@ -19,6 +19,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +// Operator overloads not supported in Universal Windows Platform (WinRT Components) +#if !WINDOWS_UWP using System; namespace UnitsNet @@ -35,4 +37,5 @@ public partial struct Angle return RotationalSpeed.FromRadiansPerSecond(angle.Radians/duration.Seconds); } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/UnitsNet/CustomCode/UnitClasses/Area.extra.cs b/UnitsNet/CustomCode/UnitClasses/Area.extra.cs index 19e0ad3e96..01caf93696 100644 --- a/UnitsNet/CustomCode/UnitClasses/Area.extra.cs +++ b/UnitsNet/CustomCode/UnitClasses/Area.extra.cs @@ -19,6 +19,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +// Operator overloads not supported in Universal Windows Platform (WinRT Components) +#if !WINDOWS_UWP namespace UnitsNet { public partial struct Area @@ -28,4 +30,5 @@ public partial struct Area return Length.FromMeters(area.SquareMeters/length.Meters); } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/UnitsNet/CustomCode/UnitClasses/BrakeSpecificFuelConsumption.extra.cs b/UnitsNet/CustomCode/UnitClasses/BrakeSpecificFuelConsumption.extra.cs index 20d51850eb..2d42320de0 100644 --- a/UnitsNet/CustomCode/UnitClasses/BrakeSpecificFuelConsumption.extra.cs +++ b/UnitsNet/CustomCode/UnitClasses/BrakeSpecificFuelConsumption.extra.cs @@ -19,6 +19,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +// Operator overloads not supported in Universal Windows Platform (WinRT Components) +#if !WINDOWS_UWP namespace UnitsNet { public partial struct BrakeSpecificFuelConsumption @@ -38,4 +40,5 @@ public partial struct BrakeSpecificFuelConsumption return specificEnergy.JoulesPerKilogram * bsfc.KilogramsPerJoule; } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/UnitsNet/CustomCode/UnitClasses/Density.extra.cs b/UnitsNet/CustomCode/UnitClasses/Density.extra.cs index e3ba47f495..b19c16ed42 100644 --- a/UnitsNet/CustomCode/UnitClasses/Density.extra.cs +++ b/UnitsNet/CustomCode/UnitClasses/Density.extra.cs @@ -19,6 +19,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +// Operator overloads not supported in Universal Windows Platform (WinRT Components) +#if !WINDOWS_UWP namespace UnitsNet { public partial struct Density @@ -38,4 +40,5 @@ public partial struct Density return DynamicViscosity.FromNewtonSecondsPerMeterSquared(kinematicViscosity.SquareMetersPerSecond * density.KilogramsPerCubicMeter); } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/UnitsNet/CustomCode/UnitClasses/Duration.extra.cs b/UnitsNet/CustomCode/UnitClasses/Duration.extra.cs index 922408e25e..f52b655759 100644 --- a/UnitsNet/CustomCode/UnitClasses/Duration.extra.cs +++ b/UnitsNet/CustomCode/UnitClasses/Duration.extra.cs @@ -23,8 +23,14 @@ namespace UnitsNet { +#if WINDOWS_UWP + public sealed partial class Duration +#else public partial struct Duration +#endif { + // Operator overloads not supported in Universal Windows Platform (WinRT Components) +#if !WINDOWS_UWP public static DateTime operator +(DateTime time, Duration duration) { return time.AddSeconds(duration.Seconds); @@ -35,6 +41,17 @@ public partial struct Duration return time.AddSeconds(-duration.Seconds); } + public static explicit operator TimeSpan(Duration duration) + { + return duration.ToTimeSpan(); + } + + public static explicit operator Duration(TimeSpan duration) + { + return FromSeconds(duration.TotalSeconds); + } +#endif + /// /// Convert a Duration to a TimeSpan. /// @@ -49,15 +66,5 @@ public TimeSpan ToTimeSpan() } return TimeSpan.FromSeconds(Seconds); } - - public static explicit operator TimeSpan(Duration duration) - { - return duration.ToTimeSpan(); - } - - public static explicit operator Duration(TimeSpan duration) - { - return FromSeconds(duration.TotalSeconds); - } } } \ No newline at end of file diff --git a/UnitsNet/CustomCode/UnitClasses/DynamicViscosity.extra.cs b/UnitsNet/CustomCode/UnitClasses/DynamicViscosity.extra.cs index d00d20bb7d..c06ea56bf6 100644 --- a/UnitsNet/CustomCode/UnitClasses/DynamicViscosity.extra.cs +++ b/UnitsNet/CustomCode/UnitClasses/DynamicViscosity.extra.cs @@ -19,6 +19,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +// Operator overloads not supported in Universal Windows Platform (WinRT Components) +#if !WINDOWS_UWP using System; namespace UnitsNet @@ -30,4 +32,5 @@ public partial struct DynamicViscosity return KinematicViscosity.FromSquareMetersPerSecond(dynamicViscosity.NewtonSecondsPerMeterSquared / density.KilogramsPerCubicMeter); } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/UnitsNet/CustomCode/UnitClasses/Force.extra.cs b/UnitsNet/CustomCode/UnitClasses/Force.extra.cs index 216db53983..e56948542f 100644 --- a/UnitsNet/CustomCode/UnitClasses/Force.extra.cs +++ b/UnitsNet/CustomCode/UnitClasses/Force.extra.cs @@ -21,8 +21,14 @@ namespace UnitsNet { +#if WINDOWS_UWP + public sealed partial class Force +#else public partial struct Force +#endif { + // Operator overloads not supported in Universal Windows Platform (WinRT Components) +#if !WINDOWS_UWP public static Power operator *(Force force, Speed speed) { return Power.FromWatts(force.Newtons*speed.MetersPerSecond); @@ -42,13 +48,17 @@ public partial struct Force { return Pressure.FromPascals(force.Newtons/area.SquareMeters); } +#endif + // Method overloads with same number of argumnets not supported in Universal Windows Platform (WinRT Components) +#if !WINDOWS_UWP public static Force FromPressureByArea(Pressure p, Length2d area) { double metersSquared = area.Meters.X*area.Meters.Y; double newtons = p.Pascals*metersSquared; return new Force(newtons); } +#endif public static Force FromPressureByArea(Pressure p, Area area) { diff --git a/UnitsNet/CustomCode/UnitClasses/KinematicViscosity.extra.cs b/UnitsNet/CustomCode/UnitClasses/KinematicViscosity.extra.cs index 807a890312..bd8dc65f25 100644 --- a/UnitsNet/CustomCode/UnitClasses/KinematicViscosity.extra.cs +++ b/UnitsNet/CustomCode/UnitClasses/KinematicViscosity.extra.cs @@ -19,6 +19,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +// Operator overloads not supported in Universal Windows Platform (WinRT Components) +#if !WINDOWS_UWP using System; namespace UnitsNet @@ -55,4 +57,5 @@ public partial struct KinematicViscosity return DynamicViscosity.FromNewtonSecondsPerMeterSquared(kinematicViscosity.SquareMetersPerSecond * density.KilogramsPerCubicMeter); } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/UnitsNet/CustomCode/UnitClasses/Length.extra.cs b/UnitsNet/CustomCode/UnitClasses/Length.extra.cs index cd26771a4e..aa2c45cf52 100644 --- a/UnitsNet/CustomCode/UnitClasses/Length.extra.cs +++ b/UnitsNet/CustomCode/UnitClasses/Length.extra.cs @@ -20,8 +20,7 @@ // THE SOFTWARE. using System; -using System.Diagnostics; -using System.Globalization; +using JetBrains.Annotations; using UnitsNet.Units; namespace UnitsNet @@ -31,7 +30,11 @@ namespace UnitsNet /// Makes it easier to work with Feet/Inches combinations, which are customarily used in the US and UK /// to express body height. For example, someone is 5 feet 3 inches tall. /// +#if WINDOWS_UWP + public sealed partial class Length +#else public partial struct Length +#endif { private const double FeetToInches = 12; @@ -58,6 +61,8 @@ public static Length FromFeetInches(double feet, double inches) return FromInches(FeetToInches*feet + inches); } + // Operator overloads not supported in Universal Windows Platform (WinRT Components) +#if !WINDOWS_UWP public static Speed operator /(Length length, TimeSpan timeSpan) { return Speed.FromMetersPerSecond(length.Meters/timeSpan.TotalSeconds); @@ -102,9 +107,10 @@ public static Length FromFeetInches(double feet, double inches) { return KinematicViscosity.FromSquareMetersPerSecond(length.Meters * speed.MetersPerSecond); } +#endif } - public class FeetInches + public sealed class FeetInches { public FeetInches(double feet, double inches) { @@ -115,17 +121,26 @@ public FeetInches(double feet, double inches) public double Feet { get; } public double Inches { get; } - public string ToString(IFormatProvider cultureInfo = null) + public override string ToString() { - // Note that it isn't customary to use fractions - one wouldn't say "I am 5 feet and 4.5 inches". - // So inches are rounded when converting from base units to feet/inches. - - UnitSystem unitSystem = UnitSystem.GetCached(cultureInfo); - string footUnit = unitSystem.GetDefaultAbbreviation(LengthUnit.Foot); - string inchUnit = unitSystem.GetDefaultAbbreviation(LengthUnit.Inch); - - return string.Format(cultureInfo == null ? CultureInfo.CurrentCulture : cultureInfo, "{0:n0} {1} {2:n0} {3}", - Feet, footUnit, Math.Round(Inches), inchUnit); + return ToString(null); } + + #if WINDOWS_UWP + internal + #else + public + #endif + string ToString([CanBeNull] IFormatProvider cultureInfo) + { + // Note that it isn't customary to use fractions - one wouldn't say "I am 5 feet and 4.5 inches". + // So inches are rounded when converting from base units to feet/inches. + UnitSystem unitSystem = UnitSystem.GetCached(cultureInfo); + string footUnit = unitSystem.GetDefaultAbbreviation(LengthUnit.Foot); + string inchUnit = unitSystem.GetDefaultAbbreviation(LengthUnit.Inch); + + return string.Format(unitSystem.Culture, "{0:n0} {1} {2:n0} {3}", Feet, footUnit, Math.Round(Inches), + inchUnit); + } } -} \ No newline at end of file +} diff --git a/UnitsNet/CustomCode/UnitClasses/Level.extra.cs b/UnitsNet/CustomCode/UnitClasses/Level.extra.cs index 6f0ac139b5..6601c3d3ee 100644 --- a/UnitsNet/CustomCode/UnitClasses/Level.extra.cs +++ b/UnitsNet/CustomCode/UnitClasses/Level.extra.cs @@ -23,7 +23,11 @@ namespace UnitsNet { +#if WINDOWS_UWP + public sealed partial class Level +#else public partial struct Level +#endif { /// /// Initializes a new instance of the logarithmic struct which is the ratio of a quantity Q to a diff --git a/UnitsNet/CustomCode/UnitClasses/Mass.extra.cs b/UnitsNet/CustomCode/UnitClasses/Mass.extra.cs index 1c814bef04..0da3b39368 100644 --- a/UnitsNet/CustomCode/UnitClasses/Mass.extra.cs +++ b/UnitsNet/CustomCode/UnitClasses/Mass.extra.cs @@ -21,11 +21,16 @@ using System; using System.Globalization; +using JetBrains.Annotations; using UnitsNet.Units; namespace UnitsNet { +#if WINDOWS_UWP + public sealed partial class Mass +#else public partial struct Mass +#endif { public static Mass FromGravitationalForce(Force f) { @@ -61,6 +66,8 @@ public static Mass FromStonePounds(double stone, double pounds) return FromPounds(StoneToPounds*stone + pounds); } + // Operator overloads not supported in Universal Windows Platform (WinRT Components) +#if !WINDOWS_UWP public static MassFlow operator /(Mass mass, TimeSpan timeSpan) { return MassFlow.FromKilogramsPerSecond(mass.Kilograms/timeSpan.TotalSeconds); @@ -85,9 +92,10 @@ public static Mass FromStonePounds(double stone, double pounds) { return Force.FromNewtons(mass.Kilograms*acceleration.MeterPerSecondSquared); } +#endif } - public class StonePounds + public sealed class StonePounds { public StonePounds(double stone, double pounds) { @@ -98,7 +106,17 @@ public StonePounds(double stone, double pounds) public double Stone { get; } public double Pounds { get; } - public string ToString(IFormatProvider cultureInfo = null) + public override string ToString() + { + return ToString(null); + } + +#if WINDOWS_UWP + internal +#else + public +#endif + string ToString([CanBeNull] IFormatProvider cultureInfo) { // Note that it isn't customary to use fractions - one wouldn't say "I am 11 stone and 4.5 pounds". // So pounds are rounded here. @@ -107,7 +125,7 @@ public string ToString(IFormatProvider cultureInfo = null) string stoneUnit = unitSystem.GetDefaultAbbreviation(MassUnit.Stone); string poundUnit = unitSystem.GetDefaultAbbreviation(MassUnit.Pound); - return string.Format(cultureInfo == null ? CultureInfo.CurrentCulture : cultureInfo, "{0:n0} {1} {2:n0} {3}", + return string.Format(unitSystem.Culture, "{0:n0} {1} {2:n0} {3}", Stone, stoneUnit, Math.Round(Pounds), poundUnit); } } diff --git a/UnitsNet/CustomCode/UnitClasses/MassFlow.extra.cs b/UnitsNet/CustomCode/UnitClasses/MassFlow.extra.cs index 14df0b7818..0bd46bdfb1 100644 --- a/UnitsNet/CustomCode/UnitClasses/MassFlow.extra.cs +++ b/UnitsNet/CustomCode/UnitClasses/MassFlow.extra.cs @@ -19,6 +19,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +// Operator overloads not supported in Universal Windows Platform (WinRT Components) +#if !WINDOWS_UWP using System; namespace UnitsNet @@ -60,4 +62,5 @@ public partial struct MassFlow return Power.FromWatts(massFlow.KilogramsPerSecond * specificEnergy.JoulesPerKilogram); } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/UnitsNet/CustomCode/UnitClasses/Power.extra.cs b/UnitsNet/CustomCode/UnitClasses/Power.extra.cs index cfff49b446..c391d1fdd8 100644 --- a/UnitsNet/CustomCode/UnitClasses/Power.extra.cs +++ b/UnitsNet/CustomCode/UnitClasses/Power.extra.cs @@ -19,6 +19,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +// Operator overloads not supported in Universal Windows Platform (WinRT Components) +#if !WINDOWS_UWP using System; namespace UnitsNet @@ -80,4 +82,5 @@ public partial struct Power return MassFlow.FromKilogramsPerSecond(power.Watts / specificEnergy.JoulesPerKilogram); } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/UnitsNet/CustomCode/UnitClasses/PowerRatio.extra.cs b/UnitsNet/CustomCode/UnitClasses/PowerRatio.extra.cs index 810a222b7f..726e2c3055 100644 --- a/UnitsNet/CustomCode/UnitClasses/PowerRatio.extra.cs +++ b/UnitsNet/CustomCode/UnitClasses/PowerRatio.extra.cs @@ -23,63 +23,22 @@ namespace UnitsNet { - /// - /// Extension methods for . - /// - public static class PowerRatioExtensions - { - /// - /// Gets a from a . - /// - /// - /// Provides a nicer syntax for converting a power ratio back to a power. - /// - /// var power = powerRatio.ToPower(); - /// - /// - public static Power ToPower(this PowerRatio powerRatio) - { - return PowerRatio.ToPower(powerRatio); - } - - /// - /// Gets a from a . - /// - /// The power ratio. - /// The input impedance of the load. This is usually 50, 75 or 600 ohms. - public static AmplitudeRatio ToAmplitudeRatio(this PowerRatio powerRatio, ElectricResistance impedance) - { - return PowerRatio.ToAmplitudeRatio(powerRatio, impedance); - } - } - - /// - /// Extension methods for . - /// - public static class PowerExtensions - { - /// - /// Gets a from a relative to one watt. - /// - /// - /// Provides a nicer syntax for converting a power to a power ratio (relative to 1 watt). - /// - /// var powerRatio = power.ToPowerRatio(); - /// - /// - public static PowerRatio ToPowerRatio(this Power power) - { - return PowerRatio.FromPower(power); - } - } - +#if WINDOWS_UWP + public sealed partial class PowerRatio +#else public partial struct PowerRatio +#endif { /// /// Initializes a new instance of the struct from the specified power referenced to one watt. /// /// The power relative to one watt. - public PowerRatio(Power power) +#if WINDOWS_UWP + internal +#else + public +#endif + PowerRatio(Power power) : this() { if (power.Watts <= 0) @@ -87,7 +46,7 @@ public PowerRatio(Power power) nameof(power), "The base-10 logarithm of a number ≤ 0 is undefined. Power must be greater than 0 W."); // P(dBW) = 10*log10(value(W)/reference(W)) - _decibelWatts = 10*Math.Log10(power/Power.FromWatts(1)); + _decibelWatts = 10*Math.Log10(power.Watts/1); } /// diff --git a/UnitsNet/CustomCode/UnitClasses/Pressure.extra.cs b/UnitsNet/CustomCode/UnitClasses/Pressure.extra.cs index 59e1df6b57..12548a988c 100644 --- a/UnitsNet/CustomCode/UnitClasses/Pressure.extra.cs +++ b/UnitsNet/CustomCode/UnitClasses/Pressure.extra.cs @@ -19,6 +19,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +// Operator overloads not supported in Universal Windows Platform (WinRT Components) +#if !WINDOWS_UWP namespace UnitsNet { public partial struct Pressure @@ -33,4 +35,5 @@ public partial struct Pressure return Force.FromNewtons(pressure.Pascals*area.SquareMeters); } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/UnitsNet/CustomCode/UnitClasses/RotationalSpeed.extra.cs b/UnitsNet/CustomCode/UnitClasses/RotationalSpeed.extra.cs index d342f57514..51371642be 100644 --- a/UnitsNet/CustomCode/UnitClasses/RotationalSpeed.extra.cs +++ b/UnitsNet/CustomCode/UnitClasses/RotationalSpeed.extra.cs @@ -19,6 +19,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +// Operator overloads not supported in Universal Windows Platform (WinRT Components) +#if !WINDOWS_UWP using System; namespace UnitsNet @@ -45,4 +47,5 @@ public partial struct RotationalSpeed return Angle.FromRadians(rotationalSpeed.RadiansPerSecond*duration.Seconds); } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/UnitsNet/CustomCode/UnitClasses/SpecificEnergy.extra.cs b/UnitsNet/CustomCode/UnitClasses/SpecificEnergy.extra.cs index 59ac8d504c..7eb9671d2e 100644 --- a/UnitsNet/CustomCode/UnitClasses/SpecificEnergy.extra.cs +++ b/UnitsNet/CustomCode/UnitClasses/SpecificEnergy.extra.cs @@ -19,6 +19,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +// Operator overloads not supported in Universal Windows Platform (WinRT Components) +#if !WINDOWS_UWP namespace UnitsNet { public partial struct SpecificEnergy @@ -48,4 +50,5 @@ public partial struct SpecificEnergy return Power.FromWatts(massFlow.KilogramsPerSecond * specificEnergy.JoulesPerKilogram); } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/UnitsNet/CustomCode/UnitClasses/Speed.extra.cs b/UnitsNet/CustomCode/UnitClasses/Speed.extra.cs index cdfcce9bfb..b04e415e1c 100644 --- a/UnitsNet/CustomCode/UnitClasses/Speed.extra.cs +++ b/UnitsNet/CustomCode/UnitClasses/Speed.extra.cs @@ -19,6 +19,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +// Operator overloads not supported in Universal Windows Platform (WinRT Components) +#if !WINDOWS_UWP using System; namespace UnitsNet @@ -66,3 +68,4 @@ public partial struct Speed } } } +#endif diff --git a/UnitsNet/CustomCode/UnitClasses/Torque.extra.cs b/UnitsNet/CustomCode/UnitClasses/Torque.extra.cs index 99d6605344..ad2a6a409b 100644 --- a/UnitsNet/CustomCode/UnitClasses/Torque.extra.cs +++ b/UnitsNet/CustomCode/UnitClasses/Torque.extra.cs @@ -19,6 +19,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +// Operator overloads not supported in Universal Windows Platform (WinRT Components) +#if !WINDOWS_UWP namespace UnitsNet { public partial struct Torque @@ -33,4 +35,5 @@ public partial struct Torque return Length.FromMeters(torque.NewtonMeters/force.Newtons); } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/UnitsNet/CustomCode/UnitClasses/Volume.extra.cs b/UnitsNet/CustomCode/UnitClasses/Volume.extra.cs index fe2815f658..b35619bc11 100644 --- a/UnitsNet/CustomCode/UnitClasses/Volume.extra.cs +++ b/UnitsNet/CustomCode/UnitClasses/Volume.extra.cs @@ -19,6 +19,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +// Operator overloads not supported in Universal Windows Platform (WinRT Components) +#if !WINDOWS_UWP namespace UnitsNet { public partial struct Volume @@ -33,4 +35,5 @@ public partial struct Volume return Length.FromMeters(volume.CubicMeters/area.SquareMeters); } } -} \ No newline at end of file +} +#endif \ No newline at end of file From a12b2fd8304c8f5b72416a750e938858da1ffc5a Mon Sep 17 00:00:00 2001 From: Andreas Gullberg Larsen Date: Sun, 13 Mar 2016 11:44:04 +0100 Subject: [PATCH 09/17] Regenerate code --- .../UnitClasses/Acceleration.g.cs | 225 ++++++++++-- .../UnitClasses/AmplitudeRatio.g.cs | 209 +++++++++-- UnitsNet/GeneratedCode/UnitClasses/Angle.g.cs | 249 ++++++++++--- UnitsNet/GeneratedCode/UnitClasses/Area.g.cs | 237 ++++++++++--- .../BrakeSpecificFuelConsumption.g.cs | 209 +++++++++-- .../GeneratedCode/UnitClasses/Density.g.cs | 237 ++++++++++--- .../GeneratedCode/UnitClasses/Duration.g.cs | 237 ++++++++++--- .../UnitClasses/DynamicViscosity.g.cs | 217 ++++++++++-- .../UnitClasses/ElectricCurrent.g.cs | 221 ++++++++++-- .../UnitClasses/ElectricPotential.g.cs | 217 ++++++++++-- .../UnitClasses/ElectricResistance.g.cs | 209 +++++++++-- .../GeneratedCode/UnitClasses/Energy.g.cs | 249 ++++++++++--- UnitsNet/GeneratedCode/UnitClasses/Flow.g.cs | 245 ++++++++++--- UnitsNet/GeneratedCode/UnitClasses/Force.g.cs | 229 ++++++++++-- .../UnitClasses/ForceChangeRate.g.cs | 225 ++++++++++-- .../GeneratedCode/UnitClasses/Frequency.g.cs | 229 ++++++++++-- .../UnitClasses/Information.g.cs | 301 ++++++++++++---- .../UnitClasses/KinematicViscosity.g.cs | 229 ++++++++++-- .../GeneratedCode/UnitClasses/Length.g.cs | 253 +++++++++++--- UnitsNet/GeneratedCode/UnitClasses/Level.g.cs | 205 +++++++++-- UnitsNet/GeneratedCode/UnitClasses/Mass.g.cs | 265 +++++++++++--- .../GeneratedCode/UnitClasses/MassFlow.g.cs | 237 ++++++++++--- UnitsNet/GeneratedCode/UnitClasses/Power.g.cs | 261 +++++++++++--- .../GeneratedCode/UnitClasses/PowerRatio.g.cs | 205 +++++++++-- .../GeneratedCode/UnitClasses/Pressure.g.cs | 329 +++++++++++++----- .../UnitClasses/PressureChangeRate.g.cs | 213 ++++++++++-- UnitsNet/GeneratedCode/UnitClasses/Ratio.g.cs | 221 ++++++++++-- .../UnitClasses/RotationalSpeed.g.cs | 249 ++++++++++--- .../UnitClasses/SpecificEnergy.g.cs | 229 ++++++++++-- .../UnitClasses/SpecificWeight.g.cs | 261 +++++++++++--- UnitsNet/GeneratedCode/UnitClasses/Speed.g.cs | 273 ++++++++++++--- .../UnitClasses/Temperature.g.cs | 229 ++++++++++-- .../UnitClasses/TemperatureChangeRate.g.cs | 233 +++++++++++-- .../GeneratedCode/UnitClasses/Torque.g.cs | 261 +++++++++++--- .../GeneratedCode/UnitClasses/VitaminA.g.cs | 201 +++++++++-- .../GeneratedCode/UnitClasses/Volume.g.cs | 317 ++++++++++++----- 36 files changed, 7170 insertions(+), 1446 deletions(-) diff --git a/UnitsNet/GeneratedCode/UnitClasses/Acceleration.g.cs b/UnitsNet/GeneratedCode/UnitClasses/Acceleration.g.cs index 09c937a26a..5bfb9fc0e2 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/Acceleration.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/Acceleration.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// Acceleration, in physics, is the rate at which the velocity of an object changes over time. An object's acceleration is the net result of any and all forces acting on the object, as described by Newton's Second Law. The SI unit for acceleration is the Meter per second squared (m/s2). Accelerations are vector quantities (they have magnitude and direction) and add according to the parallelogram law. As a vector, the calculated net force is equal to the product of the object's mass (a scalar quantity) and the acceleration. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class Acceleration +#else public partial struct Acceleration : IComparable, IComparable +#endif { /// /// Base unit of Acceleration. /// private readonly double _meterPerSecondSquared; - public Acceleration(double meterpersecondsquared) : this() +#if WINDOWS_UWP + public Acceleration() : this(0) + { + } +#endif + + public Acceleration(double meterpersecondsquared) + { + _meterPerSecondSquared = Convert.ToDouble(meterpersecondsquared); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Acceleration(long meterpersecondsquared) + { + _meterPerSecondSquared = Convert.ToDouble(meterpersecondsquared); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Acceleration(decimal meterpersecondsquared) { - _meterPerSecondSquared = meterpersecondsquared; + _meterPerSecondSquared = Convert.ToDouble(meterpersecondsquared); } #region Properties @@ -175,7 +214,7 @@ public static Acceleration FromNanometerPerSecondSquared(double nanometerperseco return new Acceleration((nanometerpersecondsquared) * 1e-9d); } - +#if !WINDOWS_UWP /// /// Get nullable Acceleration from nullable CentimeterPerSecondSquared. /// @@ -187,7 +226,7 @@ public static Acceleration FromNanometerPerSecondSquared(double nanometerperseco } else { - return null; + return null; } } @@ -202,7 +241,7 @@ public static Acceleration FromNanometerPerSecondSquared(double nanometerperseco } else { - return null; + return null; } } @@ -217,7 +256,7 @@ public static Acceleration FromNanometerPerSecondSquared(double nanometerperseco } else { - return null; + return null; } } @@ -232,7 +271,7 @@ public static Acceleration FromNanometerPerSecondSquared(double nanometerperseco } else { - return null; + return null; } } @@ -247,7 +286,7 @@ public static Acceleration FromNanometerPerSecondSquared(double nanometerperseco } else { - return null; + return null; } } @@ -262,7 +301,7 @@ public static Acceleration FromNanometerPerSecondSquared(double nanometerperseco } else { - return null; + return null; } } @@ -277,41 +316,43 @@ public static Acceleration FromNanometerPerSecondSquared(double nanometerperseco } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// Acceleration unit value. - public static Acceleration From(double value, AccelerationUnit fromUnit) + public static Acceleration From(double val, AccelerationUnit fromUnit) { switch (fromUnit) { case AccelerationUnit.CentimeterPerSecondSquared: - return FromCentimeterPerSecondSquared(value); + return FromCentimeterPerSecondSquared(val); case AccelerationUnit.DecimeterPerSecondSquared: - return FromDecimeterPerSecondSquared(value); + return FromDecimeterPerSecondSquared(val); case AccelerationUnit.KilometerPerSecondSquared: - return FromKilometerPerSecondSquared(value); + return FromKilometerPerSecondSquared(val); case AccelerationUnit.MeterPerSecondSquared: - return FromMeterPerSecondSquared(value); + return FromMeterPerSecondSquared(val); case AccelerationUnit.MicrometerPerSecondSquared: - return FromMicrometerPerSecondSquared(value); + return FromMicrometerPerSecondSquared(val); case AccelerationUnit.MillimeterPerSecondSquared: - return FromMillimeterPerSecondSquared(value); + return FromMillimeterPerSecondSquared(val); case AccelerationUnit.NanometerPerSecondSquared: - return FromNanometerPerSecondSquared(value); + return FromNanometerPerSecondSquared(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -345,6 +386,18 @@ public static Acceleration From(double value, AccelerationUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(AccelerationUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -353,7 +406,7 @@ public static Acceleration From(double value, AccelerationUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(AccelerationUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(AccelerationUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -362,6 +415,7 @@ public static string GetAbbreviation(AccelerationUnit unit, CultureInfo culture #region Arithmetic Operators +#if !WINDOWS_UWP public static Acceleration operator -(Acceleration right) { return new Acceleration(-right._meterPerSecondSquared); @@ -396,6 +450,7 @@ public static string GetAbbreviation(AccelerationUnit unit, CultureInfo culture { return Convert.ToDouble(left._meterPerSecondSquared/right._meterPerSecondSquared); } +#endif #endregion @@ -408,11 +463,17 @@ public int CompareTo(object obj) return CompareTo((Acceleration) obj); } - public int CompareTo(Acceleration other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(Acceleration other) { return _meterPerSecondSquared.CompareTo(other._meterPerSecondSquared); } +#if !WINDOWS_UWP public static bool operator <=(Acceleration left, Acceleration right) { return left._meterPerSecondSquared <= right._meterPerSecondSquared; @@ -444,6 +505,7 @@ public int CompareTo(Acceleration other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._meterPerSecondSquared != right._meterPerSecondSquared; } +#endif public override bool Equals(object obj) { @@ -501,7 +563,6 @@ public double As(AccelerationUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -520,10 +581,43 @@ public double As(AccelerationUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static Acceleration Parse(string str, IFormatProvider formatProvider = null) + public static Acceleration Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static Acceleration Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -547,7 +641,7 @@ public static Acceleration Parse(string str, IFormatProvider formatProvider = nu "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => Acceleration.FromMeterPerSecondSquared(x.MeterPerSecondSquared + y.MeterPerSecondSquared)); } /// @@ -584,7 +678,7 @@ private static List ParseWithRegex(string regexString, string str, converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -609,18 +703,49 @@ private static List ParseWithRegex(string regexString, string str, /// /// The value of 'str' cannot be null. /// Error parsing string. - public static AccelerationUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static AccelerationUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static AccelerationUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static AccelerationUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == AccelerationUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized AccelerationUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -643,6 +768,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(AccelerationUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(AccelerationUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -651,9 +797,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(AccelerationUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(AccelerationUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -665,9 +813,20 @@ public string ToString(AccelerationUnit unit, CultureInfo culture = null, int si /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(AccelerationUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(AccelerationUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/AmplitudeRatio.g.cs b/UnitsNet/GeneratedCode/UnitClasses/AmplitudeRatio.g.cs index a2843f3a06..6c2fd53bbf 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/AmplitudeRatio.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/AmplitudeRatio.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// The strength of a signal expressed in decibels (dB) relative to one volt RMS. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class AmplitudeRatio +#else public partial struct AmplitudeRatio : IComparable, IComparable +#endif { /// /// Base unit of AmplitudeRatio. /// private readonly double _decibelVolts; - public AmplitudeRatio(double decibelvolts) : this() +#if WINDOWS_UWP + public AmplitudeRatio() : this(0) + { + } +#endif + + public AmplitudeRatio(double decibelvolts) + { + _decibelVolts = Convert.ToDouble(decibelvolts); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + AmplitudeRatio(long decibelvolts) + { + _decibelVolts = Convert.ToDouble(decibelvolts); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + AmplitudeRatio(decimal decibelvolts) { - _decibelVolts = decibelvolts; + _decibelVolts = Convert.ToDouble(decibelvolts); } #region Properties @@ -111,7 +150,7 @@ public static AmplitudeRatio FromDecibelVolts(double decibelvolts) return new AmplitudeRatio(decibelvolts); } - +#if !WINDOWS_UWP /// /// Get nullable AmplitudeRatio from nullable DecibelMicrovolts. /// @@ -123,7 +162,7 @@ public static AmplitudeRatio FromDecibelVolts(double decibelvolts) } else { - return null; + return null; } } @@ -138,7 +177,7 @@ public static AmplitudeRatio FromDecibelVolts(double decibelvolts) } else { - return null; + return null; } } @@ -153,33 +192,35 @@ public static AmplitudeRatio FromDecibelVolts(double decibelvolts) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// AmplitudeRatio unit value. - public static AmplitudeRatio From(double value, AmplitudeRatioUnit fromUnit) + public static AmplitudeRatio From(double val, AmplitudeRatioUnit fromUnit) { switch (fromUnit) { case AmplitudeRatioUnit.DecibelMicrovolt: - return FromDecibelMicrovolts(value); + return FromDecibelMicrovolts(val); case AmplitudeRatioUnit.DecibelMillivolt: - return FromDecibelMillivolts(value); + return FromDecibelMillivolts(val); case AmplitudeRatioUnit.DecibelVolt: - return FromDecibelVolts(value); + return FromDecibelVolts(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -205,6 +246,18 @@ public static AmplitudeRatio From(double value, AmplitudeRatioUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(AmplitudeRatioUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -213,7 +266,7 @@ public static AmplitudeRatio From(double value, AmplitudeRatioUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(AmplitudeRatioUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(AmplitudeRatioUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -222,6 +275,7 @@ public static string GetAbbreviation(AmplitudeRatioUnit unit, CultureInfo cultur #region Logarithmic Arithmetic Operators +#if !WINDOWS_UWP public static AmplitudeRatio operator -(AmplitudeRatio right) { return new AmplitudeRatio(-right._decibelVolts); @@ -264,6 +318,7 @@ public static string GetAbbreviation(AmplitudeRatioUnit unit, CultureInfo cultur // Logarithmic division = subtraction return Convert.ToDouble(left._decibelVolts - right._decibelVolts); } +#endif #endregion @@ -276,11 +331,17 @@ public int CompareTo(object obj) return CompareTo((AmplitudeRatio) obj); } - public int CompareTo(AmplitudeRatio other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(AmplitudeRatio other) { return _decibelVolts.CompareTo(other._decibelVolts); } +#if !WINDOWS_UWP public static bool operator <=(AmplitudeRatio left, AmplitudeRatio right) { return left._decibelVolts <= right._decibelVolts; @@ -312,6 +373,7 @@ public int CompareTo(AmplitudeRatio other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._decibelVolts != right._decibelVolts; } +#endif public override bool Equals(object obj) { @@ -361,7 +423,6 @@ public double As(AmplitudeRatioUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -380,10 +441,43 @@ public double As(AmplitudeRatioUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static AmplitudeRatio Parse(string str, IFormatProvider formatProvider = null) + public static AmplitudeRatio Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static AmplitudeRatio Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -407,7 +501,7 @@ public static AmplitudeRatio Parse(string str, IFormatProvider formatProvider = "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => AmplitudeRatio.FromDecibelVolts(x.DecibelVolts + y.DecibelVolts)); } /// @@ -444,7 +538,7 @@ private static List ParseWithRegex(string regexString, string st converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -469,18 +563,49 @@ private static List ParseWithRegex(string regexString, string st /// /// The value of 'str' cannot be null. /// Error parsing string. - public static AmplitudeRatioUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static AmplitudeRatioUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static AmplitudeRatioUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static AmplitudeRatioUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == AmplitudeRatioUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized AmplitudeRatioUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -503,6 +628,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(AmplitudeRatioUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(AmplitudeRatioUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -511,9 +657,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(AmplitudeRatioUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(AmplitudeRatioUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -525,9 +673,20 @@ public string ToString(AmplitudeRatioUnit unit, CultureInfo culture = null, int /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(AmplitudeRatioUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(AmplitudeRatioUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/Angle.g.cs b/UnitsNet/GeneratedCode/UnitClasses/Angle.g.cs index d4e84942bf..fc40c65f91 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/Angle.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/Angle.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// In geometry, an angle is the figure formed by two rays, called the sides of the angle, sharing a common endpoint, called the vertex of the angle. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class Angle +#else public partial struct Angle : IComparable, IComparable +#endif { /// /// Base unit of Angle. /// private readonly double _degrees; - public Angle(double degrees) : this() +#if WINDOWS_UWP + public Angle() : this(0) + { + } +#endif + + public Angle(double degrees) + { + _degrees = Convert.ToDouble(degrees); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Angle(long degrees) { - _degrees = degrees; + _degrees = Convert.ToDouble(degrees); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Angle(decimal degrees) + { + _degrees = Convert.ToDouble(degrees); } #region Properties @@ -271,7 +310,7 @@ public static Angle FromRadians(double radians) return new Angle(radians*180/Math.PI); } - +#if !WINDOWS_UWP /// /// Get nullable Angle from nullable Arcminutes. /// @@ -283,7 +322,7 @@ public static Angle FromRadians(double radians) } else { - return null; + return null; } } @@ -298,7 +337,7 @@ public static Angle FromRadians(double radians) } else { - return null; + return null; } } @@ -313,7 +352,7 @@ public static Angle FromRadians(double radians) } else { - return null; + return null; } } @@ -328,7 +367,7 @@ public static Angle FromRadians(double radians) } else { - return null; + return null; } } @@ -343,7 +382,7 @@ public static Angle FromRadians(double radians) } else { - return null; + return null; } } @@ -358,7 +397,7 @@ public static Angle FromRadians(double radians) } else { - return null; + return null; } } @@ -373,7 +412,7 @@ public static Angle FromRadians(double radians) } else { - return null; + return null; } } @@ -388,7 +427,7 @@ public static Angle FromRadians(double radians) } else { - return null; + return null; } } @@ -403,7 +442,7 @@ public static Angle FromRadians(double radians) } else { - return null; + return null; } } @@ -418,7 +457,7 @@ public static Angle FromRadians(double radians) } else { - return null; + return null; } } @@ -433,7 +472,7 @@ public static Angle FromRadians(double radians) } else { - return null; + return null; } } @@ -448,7 +487,7 @@ public static Angle FromRadians(double radians) } else { - return null; + return null; } } @@ -463,53 +502,55 @@ public static Angle FromRadians(double radians) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// Angle unit value. - public static Angle From(double value, AngleUnit fromUnit) + public static Angle From(double val, AngleUnit fromUnit) { switch (fromUnit) { case AngleUnit.Arcminute: - return FromArcminutes(value); + return FromArcminutes(val); case AngleUnit.Arcsecond: - return FromArcseconds(value); + return FromArcseconds(val); case AngleUnit.Centiradian: - return FromCentiradians(value); + return FromCentiradians(val); case AngleUnit.Deciradian: - return FromDeciradians(value); + return FromDeciradians(val); case AngleUnit.Degree: - return FromDegrees(value); + return FromDegrees(val); case AngleUnit.Gradian: - return FromGradians(value); + return FromGradians(val); case AngleUnit.Microdegree: - return FromMicrodegrees(value); + return FromMicrodegrees(val); case AngleUnit.Microradian: - return FromMicroradians(value); + return FromMicroradians(val); case AngleUnit.Millidegree: - return FromMillidegrees(value); + return FromMillidegrees(val); case AngleUnit.Milliradian: - return FromMilliradians(value); + return FromMilliradians(val); case AngleUnit.Nanodegree: - return FromNanodegrees(value); + return FromNanodegrees(val); case AngleUnit.Nanoradian: - return FromNanoradians(value); + return FromNanoradians(val); case AngleUnit.Radian: - return FromRadians(value); + return FromRadians(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -555,6 +596,18 @@ public static Angle From(double value, AngleUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(AngleUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -563,7 +616,7 @@ public static Angle From(double value, AngleUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(AngleUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(AngleUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -572,6 +625,7 @@ public static string GetAbbreviation(AngleUnit unit, CultureInfo culture = null) #region Arithmetic Operators +#if !WINDOWS_UWP public static Angle operator -(Angle right) { return new Angle(-right._degrees); @@ -606,6 +660,7 @@ public static string GetAbbreviation(AngleUnit unit, CultureInfo culture = null) { return Convert.ToDouble(left._degrees/right._degrees); } +#endif #endregion @@ -618,11 +673,17 @@ public int CompareTo(object obj) return CompareTo((Angle) obj); } - public int CompareTo(Angle other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(Angle other) { return _degrees.CompareTo(other._degrees); } +#if !WINDOWS_UWP public static bool operator <=(Angle left, Angle right) { return left._degrees <= right._degrees; @@ -654,6 +715,7 @@ public int CompareTo(Angle other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._degrees != right._degrees; } +#endif public override bool Equals(object obj) { @@ -723,7 +785,6 @@ public double As(AngleUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -742,10 +803,43 @@ public double As(AngleUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static Angle Parse(string str, IFormatProvider formatProvider = null) + public static Angle Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static Angle Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -769,7 +863,7 @@ public static Angle Parse(string str, IFormatProvider formatProvider = null) "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => Angle.FromDegrees(x.Degrees + y.Degrees)); } /// @@ -806,7 +900,7 @@ private static List ParseWithRegex(string regexString, string str, IForma converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -831,18 +925,49 @@ private static List ParseWithRegex(string regexString, string str, IForma /// /// The value of 'str' cannot be null. /// Error parsing string. - public static AngleUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static AngleUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static AngleUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static AngleUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == AngleUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized AngleUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -865,6 +990,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(AngleUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(AngleUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -873,9 +1019,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(AngleUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(AngleUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -887,9 +1035,20 @@ public string ToString(AngleUnit unit, CultureInfo culture = null, int significa /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(AngleUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(AngleUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/Area.g.cs b/UnitsNet/GeneratedCode/UnitClasses/Area.g.cs index b1fd8a61ed..f60a5d5ed8 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/Area.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/Area.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// Area is a quantity that expresses the extent of a two-dimensional surface or shape, or planar lamina, in the plane. Area can be understood as the amount of material with a given thickness that would be necessary to fashion a model of the shape, or the amount of paint necessary to cover the surface with a single coat.[1] It is the two-dimensional analog of the length of a curve (a one-dimensional concept) or the volume of a solid (a three-dimensional concept). /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class Area +#else public partial struct Area : IComparable, IComparable +#endif { /// /// Base unit of Area. /// private readonly double _squareMeters; - public Area(double squaremeters) : this() +#if WINDOWS_UWP + public Area() : this(0) + { + } +#endif + + public Area(double squaremeters) + { + _squareMeters = Convert.ToDouble(squaremeters); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Area(long squaremeters) + { + _squareMeters = Convert.ToDouble(squaremeters); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Area(decimal squaremeters) { - _squareMeters = squaremeters; + _squareMeters = Convert.ToDouble(squaremeters); } #region Properties @@ -223,7 +262,7 @@ public static Area FromSquareYards(double squareyards) return new Area(squareyards*0.836127); } - +#if !WINDOWS_UWP /// /// Get nullable Area from nullable SquareCentimeters. /// @@ -235,7 +274,7 @@ public static Area FromSquareYards(double squareyards) } else { - return null; + return null; } } @@ -250,7 +289,7 @@ public static Area FromSquareYards(double squareyards) } else { - return null; + return null; } } @@ -265,7 +304,7 @@ public static Area FromSquareYards(double squareyards) } else { - return null; + return null; } } @@ -280,7 +319,7 @@ public static Area FromSquareYards(double squareyards) } else { - return null; + return null; } } @@ -295,7 +334,7 @@ public static Area FromSquareYards(double squareyards) } else { - return null; + return null; } } @@ -310,7 +349,7 @@ public static Area FromSquareYards(double squareyards) } else { - return null; + return null; } } @@ -325,7 +364,7 @@ public static Area FromSquareYards(double squareyards) } else { - return null; + return null; } } @@ -340,7 +379,7 @@ public static Area FromSquareYards(double squareyards) } else { - return null; + return null; } } @@ -355,7 +394,7 @@ public static Area FromSquareYards(double squareyards) } else { - return null; + return null; } } @@ -370,47 +409,49 @@ public static Area FromSquareYards(double squareyards) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// Area unit value. - public static Area From(double value, AreaUnit fromUnit) + public static Area From(double val, AreaUnit fromUnit) { switch (fromUnit) { case AreaUnit.SquareCentimeter: - return FromSquareCentimeters(value); + return FromSquareCentimeters(val); case AreaUnit.SquareDecimeter: - return FromSquareDecimeters(value); + return FromSquareDecimeters(val); case AreaUnit.SquareFoot: - return FromSquareFeet(value); + return FromSquareFeet(val); case AreaUnit.SquareInch: - return FromSquareInches(value); + return FromSquareInches(val); case AreaUnit.SquareKilometer: - return FromSquareKilometers(value); + return FromSquareKilometers(val); case AreaUnit.SquareMeter: - return FromSquareMeters(value); + return FromSquareMeters(val); case AreaUnit.SquareMicrometer: - return FromSquareMicrometers(value); + return FromSquareMicrometers(val); case AreaUnit.SquareMile: - return FromSquareMiles(value); + return FromSquareMiles(val); case AreaUnit.SquareMillimeter: - return FromSquareMillimeters(value); + return FromSquareMillimeters(val); case AreaUnit.SquareYard: - return FromSquareYards(value); + return FromSquareYards(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -450,6 +491,18 @@ public static Area From(double value, AreaUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(AreaUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -458,7 +511,7 @@ public static Area From(double value, AreaUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(AreaUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(AreaUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -467,6 +520,7 @@ public static string GetAbbreviation(AreaUnit unit, CultureInfo culture = null) #region Arithmetic Operators +#if !WINDOWS_UWP public static Area operator -(Area right) { return new Area(-right._squareMeters); @@ -501,6 +555,7 @@ public static string GetAbbreviation(AreaUnit unit, CultureInfo culture = null) { return Convert.ToDouble(left._squareMeters/right._squareMeters); } +#endif #endregion @@ -513,11 +568,17 @@ public int CompareTo(object obj) return CompareTo((Area) obj); } - public int CompareTo(Area other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(Area other) { return _squareMeters.CompareTo(other._squareMeters); } +#if !WINDOWS_UWP public static bool operator <=(Area left, Area right) { return left._squareMeters <= right._squareMeters; @@ -549,6 +610,7 @@ public int CompareTo(Area other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._squareMeters != right._squareMeters; } +#endif public override bool Equals(object obj) { @@ -612,7 +674,6 @@ public double As(AreaUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -631,10 +692,43 @@ public double As(AreaUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static Area Parse(string str, IFormatProvider formatProvider = null) + public static Area Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static Area Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -658,7 +752,7 @@ public static Area Parse(string str, IFormatProvider formatProvider = null) "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => Area.FromSquareMeters(x.SquareMeters + y.SquareMeters)); } /// @@ -695,7 +789,7 @@ private static List ParseWithRegex(string regexString, string str, IFormat converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -720,18 +814,49 @@ private static List ParseWithRegex(string regexString, string str, IFormat /// /// The value of 'str' cannot be null. /// Error parsing string. - public static AreaUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static AreaUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static AreaUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static AreaUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == AreaUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized AreaUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -754,6 +879,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(AreaUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(AreaUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -762,9 +908,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(AreaUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(AreaUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -776,9 +924,20 @@ public string ToString(AreaUnit unit, CultureInfo culture = null, int significan /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(AreaUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(AreaUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/BrakeSpecificFuelConsumption.g.cs b/UnitsNet/GeneratedCode/UnitClasses/BrakeSpecificFuelConsumption.g.cs index 7258e5bbfb..8216315575 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/BrakeSpecificFuelConsumption.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/BrakeSpecificFuelConsumption.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// Brake specific fuel consumption (BSFC) is a measure of the fuel efficiency of any prime mover that burns fuel and produces rotational, or shaft, power. It is typically used for comparing the efficiency of internal combustion engines with a shaft output. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class BrakeSpecificFuelConsumption +#else public partial struct BrakeSpecificFuelConsumption : IComparable, IComparable +#endif { /// /// Base unit of BrakeSpecificFuelConsumption. /// private readonly double _kilogramsPerJoule; - public BrakeSpecificFuelConsumption(double kilogramsperjoule) : this() +#if WINDOWS_UWP + public BrakeSpecificFuelConsumption() : this(0) + { + } +#endif + + public BrakeSpecificFuelConsumption(double kilogramsperjoule) + { + _kilogramsPerJoule = Convert.ToDouble(kilogramsperjoule); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + BrakeSpecificFuelConsumption(long kilogramsperjoule) + { + _kilogramsPerJoule = Convert.ToDouble(kilogramsperjoule); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + BrakeSpecificFuelConsumption(decimal kilogramsperjoule) { - _kilogramsPerJoule = kilogramsperjoule; + _kilogramsPerJoule = Convert.ToDouble(kilogramsperjoule); } #region Properties @@ -111,7 +150,7 @@ public static BrakeSpecificFuelConsumption FromPoundsPerMechanicalHorsepowerHour return new BrakeSpecificFuelConsumption(poundspermechanicalhorsepowerhour*1.689659410672e-7); } - +#if !WINDOWS_UWP /// /// Get nullable BrakeSpecificFuelConsumption from nullable GramsPerKiloWattHour. /// @@ -123,7 +162,7 @@ public static BrakeSpecificFuelConsumption FromPoundsPerMechanicalHorsepowerHour } else { - return null; + return null; } } @@ -138,7 +177,7 @@ public static BrakeSpecificFuelConsumption FromPoundsPerMechanicalHorsepowerHour } else { - return null; + return null; } } @@ -153,33 +192,35 @@ public static BrakeSpecificFuelConsumption FromPoundsPerMechanicalHorsepowerHour } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// BrakeSpecificFuelConsumption unit value. - public static BrakeSpecificFuelConsumption From(double value, BrakeSpecificFuelConsumptionUnit fromUnit) + public static BrakeSpecificFuelConsumption From(double val, BrakeSpecificFuelConsumptionUnit fromUnit) { switch (fromUnit) { case BrakeSpecificFuelConsumptionUnit.GramPerKiloWattHour: - return FromGramsPerKiloWattHour(value); + return FromGramsPerKiloWattHour(val); case BrakeSpecificFuelConsumptionUnit.KilogramPerJoule: - return FromKilogramsPerJoule(value); + return FromKilogramsPerJoule(val); case BrakeSpecificFuelConsumptionUnit.PoundPerMechanicalHorsepowerHour: - return FromPoundsPerMechanicalHorsepowerHour(value); + return FromPoundsPerMechanicalHorsepowerHour(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -205,6 +246,18 @@ public static BrakeSpecificFuelConsumption From(double value, BrakeSpecificFuelC throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(BrakeSpecificFuelConsumptionUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -213,7 +266,7 @@ public static BrakeSpecificFuelConsumption From(double value, BrakeSpecificFuelC /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(BrakeSpecificFuelConsumptionUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(BrakeSpecificFuelConsumptionUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -222,6 +275,7 @@ public static string GetAbbreviation(BrakeSpecificFuelConsumptionUnit unit, Cult #region Arithmetic Operators +#if !WINDOWS_UWP public static BrakeSpecificFuelConsumption operator -(BrakeSpecificFuelConsumption right) { return new BrakeSpecificFuelConsumption(-right._kilogramsPerJoule); @@ -256,6 +310,7 @@ public static string GetAbbreviation(BrakeSpecificFuelConsumptionUnit unit, Cult { return Convert.ToDouble(left._kilogramsPerJoule/right._kilogramsPerJoule); } +#endif #endregion @@ -268,11 +323,17 @@ public int CompareTo(object obj) return CompareTo((BrakeSpecificFuelConsumption) obj); } - public int CompareTo(BrakeSpecificFuelConsumption other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(BrakeSpecificFuelConsumption other) { return _kilogramsPerJoule.CompareTo(other._kilogramsPerJoule); } +#if !WINDOWS_UWP public static bool operator <=(BrakeSpecificFuelConsumption left, BrakeSpecificFuelConsumption right) { return left._kilogramsPerJoule <= right._kilogramsPerJoule; @@ -304,6 +365,7 @@ public int CompareTo(BrakeSpecificFuelConsumption other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._kilogramsPerJoule != right._kilogramsPerJoule; } +#endif public override bool Equals(object obj) { @@ -353,7 +415,6 @@ public double As(BrakeSpecificFuelConsumptionUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -372,10 +433,43 @@ public double As(BrakeSpecificFuelConsumptionUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static BrakeSpecificFuelConsumption Parse(string str, IFormatProvider formatProvider = null) + public static BrakeSpecificFuelConsumption Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static BrakeSpecificFuelConsumption Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -399,7 +493,7 @@ public static BrakeSpecificFuelConsumption Parse(string str, IFormatProvider for "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => BrakeSpecificFuelConsumption.FromKilogramsPerJoule(x.KilogramsPerJoule + y.KilogramsPerJoule)); } /// @@ -436,7 +530,7 @@ private static List ParseWithRegex(string regexStr converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -461,18 +555,49 @@ private static List ParseWithRegex(string regexStr /// /// The value of 'str' cannot be null. /// Error parsing string. - public static BrakeSpecificFuelConsumptionUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static BrakeSpecificFuelConsumptionUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static BrakeSpecificFuelConsumptionUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static BrakeSpecificFuelConsumptionUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == BrakeSpecificFuelConsumptionUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized BrakeSpecificFuelConsumptionUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -495,6 +620,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(BrakeSpecificFuelConsumptionUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(BrakeSpecificFuelConsumptionUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -503,9 +649,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(BrakeSpecificFuelConsumptionUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(BrakeSpecificFuelConsumptionUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -517,9 +665,20 @@ public string ToString(BrakeSpecificFuelConsumptionUnit unit, CultureInfo cultur /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(BrakeSpecificFuelConsumptionUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(BrakeSpecificFuelConsumptionUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/Density.g.cs b/UnitsNet/GeneratedCode/UnitClasses/Density.g.cs index 4d44b42ec1..902f5e43d5 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/Density.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/Density.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// The density, or more precisely, the volumetric mass density, of a substance is its mass per unit volume. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class Density +#else public partial struct Density : IComparable, IComparable +#endif { /// /// Base unit of Density. /// private readonly double _kilogramsPerCubicMeter; - public Density(double kilogramspercubicmeter) : this() +#if WINDOWS_UWP + public Density() : this(0) + { + } +#endif + + public Density(double kilogramspercubicmeter) + { + _kilogramsPerCubicMeter = Convert.ToDouble(kilogramspercubicmeter); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Density(long kilogramspercubicmeter) + { + _kilogramsPerCubicMeter = Convert.ToDouble(kilogramspercubicmeter); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Density(decimal kilogramspercubicmeter) { - _kilogramsPerCubicMeter = kilogramspercubicmeter; + _kilogramsPerCubicMeter = Convert.ToDouble(kilogramspercubicmeter); } #region Properties @@ -223,7 +262,7 @@ public static Density FromTonnesPerCubicMillimeter(double tonnespercubicmillimet return new Density(tonnespercubicmillimeter*1000000000000000); } - +#if !WINDOWS_UWP /// /// Get nullable Density from nullable KilogramsPerCubicCentimeter. /// @@ -235,7 +274,7 @@ public static Density FromTonnesPerCubicMillimeter(double tonnespercubicmillimet } else { - return null; + return null; } } @@ -250,7 +289,7 @@ public static Density FromTonnesPerCubicMillimeter(double tonnespercubicmillimet } else { - return null; + return null; } } @@ -265,7 +304,7 @@ public static Density FromTonnesPerCubicMillimeter(double tonnespercubicmillimet } else { - return null; + return null; } } @@ -280,7 +319,7 @@ public static Density FromTonnesPerCubicMillimeter(double tonnespercubicmillimet } else { - return null; + return null; } } @@ -295,7 +334,7 @@ public static Density FromTonnesPerCubicMillimeter(double tonnespercubicmillimet } else { - return null; + return null; } } @@ -310,7 +349,7 @@ public static Density FromTonnesPerCubicMillimeter(double tonnespercubicmillimet } else { - return null; + return null; } } @@ -325,7 +364,7 @@ public static Density FromTonnesPerCubicMillimeter(double tonnespercubicmillimet } else { - return null; + return null; } } @@ -340,7 +379,7 @@ public static Density FromTonnesPerCubicMillimeter(double tonnespercubicmillimet } else { - return null; + return null; } } @@ -355,7 +394,7 @@ public static Density FromTonnesPerCubicMillimeter(double tonnespercubicmillimet } else { - return null; + return null; } } @@ -370,47 +409,49 @@ public static Density FromTonnesPerCubicMillimeter(double tonnespercubicmillimet } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// Density unit value. - public static Density From(double value, DensityUnit fromUnit) + public static Density From(double val, DensityUnit fromUnit) { switch (fromUnit) { case DensityUnit.KilogramPerCubicCentimeter: - return FromKilogramsPerCubicCentimeter(value); + return FromKilogramsPerCubicCentimeter(val); case DensityUnit.KilogramPerCubicMeter: - return FromKilogramsPerCubicMeter(value); + return FromKilogramsPerCubicMeter(val); case DensityUnit.KilogramPerCubicMillimeter: - return FromKilogramsPerCubicMillimeter(value); + return FromKilogramsPerCubicMillimeter(val); case DensityUnit.KilopoundPerCubicFoot: - return FromKilopoundsPerCubicFoot(value); + return FromKilopoundsPerCubicFoot(val); case DensityUnit.KilopoundPerCubicInch: - return FromKilopoundsPerCubicInch(value); + return FromKilopoundsPerCubicInch(val); case DensityUnit.PoundPerCubicFoot: - return FromPoundsPerCubicFoot(value); + return FromPoundsPerCubicFoot(val); case DensityUnit.PoundPerCubicInch: - return FromPoundsPerCubicInch(value); + return FromPoundsPerCubicInch(val); case DensityUnit.TonnePerCubicCentimeter: - return FromTonnesPerCubicCentimeter(value); + return FromTonnesPerCubicCentimeter(val); case DensityUnit.TonnePerCubicMeter: - return FromTonnesPerCubicMeter(value); + return FromTonnesPerCubicMeter(val); case DensityUnit.TonnePerCubicMillimeter: - return FromTonnesPerCubicMillimeter(value); + return FromTonnesPerCubicMillimeter(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -450,6 +491,18 @@ public static Density From(double value, DensityUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(DensityUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -458,7 +511,7 @@ public static Density From(double value, DensityUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(DensityUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(DensityUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -467,6 +520,7 @@ public static string GetAbbreviation(DensityUnit unit, CultureInfo culture = nul #region Arithmetic Operators +#if !WINDOWS_UWP public static Density operator -(Density right) { return new Density(-right._kilogramsPerCubicMeter); @@ -501,6 +555,7 @@ public static string GetAbbreviation(DensityUnit unit, CultureInfo culture = nul { return Convert.ToDouble(left._kilogramsPerCubicMeter/right._kilogramsPerCubicMeter); } +#endif #endregion @@ -513,11 +568,17 @@ public int CompareTo(object obj) return CompareTo((Density) obj); } - public int CompareTo(Density other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(Density other) { return _kilogramsPerCubicMeter.CompareTo(other._kilogramsPerCubicMeter); } +#if !WINDOWS_UWP public static bool operator <=(Density left, Density right) { return left._kilogramsPerCubicMeter <= right._kilogramsPerCubicMeter; @@ -549,6 +610,7 @@ public int CompareTo(Density other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._kilogramsPerCubicMeter != right._kilogramsPerCubicMeter; } +#endif public override bool Equals(object obj) { @@ -612,7 +674,6 @@ public double As(DensityUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -631,10 +692,43 @@ public double As(DensityUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static Density Parse(string str, IFormatProvider formatProvider = null) + public static Density Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static Density Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -658,7 +752,7 @@ public static Density Parse(string str, IFormatProvider formatProvider = null) "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => Density.FromKilogramsPerCubicMeter(x.KilogramsPerCubicMeter + y.KilogramsPerCubicMeter)); } /// @@ -695,7 +789,7 @@ private static List ParseWithRegex(string regexString, string str, IFor converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -720,18 +814,49 @@ private static List ParseWithRegex(string regexString, string str, IFor /// /// The value of 'str' cannot be null. /// Error parsing string. - public static DensityUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static DensityUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static DensityUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static DensityUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == DensityUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized DensityUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -754,6 +879,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(DensityUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(DensityUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -762,9 +908,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(DensityUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(DensityUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -776,9 +924,20 @@ public string ToString(DensityUnit unit, CultureInfo culture = null, int signifi /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(DensityUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(DensityUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/Duration.g.cs b/UnitsNet/GeneratedCode/UnitClasses/Duration.g.cs index 42e2c7288a..ec1b4bdcb3 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/Duration.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/Duration.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// Time is a dimension in which events can be ordered from the past through the present into the future, and also the measure of durations of events and the intervals between them. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class Duration +#else public partial struct Duration : IComparable, IComparable +#endif { /// /// Base unit of Duration. /// private readonly double _seconds; - public Duration(double seconds) : this() +#if WINDOWS_UWP + public Duration() : this(0) + { + } +#endif + + public Duration(double seconds) + { + _seconds = Convert.ToDouble(seconds); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Duration(long seconds) + { + _seconds = Convert.ToDouble(seconds); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Duration(decimal seconds) { - _seconds = seconds; + _seconds = Convert.ToDouble(seconds); } #region Properties @@ -223,7 +262,7 @@ public static Duration FromYears(double years) return new Duration(years*365*24*3600); } - +#if !WINDOWS_UWP /// /// Get nullable Duration from nullable Days. /// @@ -235,7 +274,7 @@ public static Duration FromYears(double years) } else { - return null; + return null; } } @@ -250,7 +289,7 @@ public static Duration FromYears(double years) } else { - return null; + return null; } } @@ -265,7 +304,7 @@ public static Duration FromYears(double years) } else { - return null; + return null; } } @@ -280,7 +319,7 @@ public static Duration FromYears(double years) } else { - return null; + return null; } } @@ -295,7 +334,7 @@ public static Duration FromYears(double years) } else { - return null; + return null; } } @@ -310,7 +349,7 @@ public static Duration FromYears(double years) } else { - return null; + return null; } } @@ -325,7 +364,7 @@ public static Duration FromYears(double years) } else { - return null; + return null; } } @@ -340,7 +379,7 @@ public static Duration FromYears(double years) } else { - return null; + return null; } } @@ -355,7 +394,7 @@ public static Duration FromYears(double years) } else { - return null; + return null; } } @@ -370,47 +409,49 @@ public static Duration FromYears(double years) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// Duration unit value. - public static Duration From(double value, DurationUnit fromUnit) + public static Duration From(double val, DurationUnit fromUnit) { switch (fromUnit) { case DurationUnit.Day: - return FromDays(value); + return FromDays(val); case DurationUnit.Hour: - return FromHours(value); + return FromHours(val); case DurationUnit.Microsecond: - return FromMicroseconds(value); + return FromMicroseconds(val); case DurationUnit.Millisecond: - return FromMilliseconds(value); + return FromMilliseconds(val); case DurationUnit.Minute: - return FromMinutes(value); + return FromMinutes(val); case DurationUnit.Month: - return FromMonths(value); + return FromMonths(val); case DurationUnit.Nanosecond: - return FromNanoseconds(value); + return FromNanoseconds(val); case DurationUnit.Second: - return FromSeconds(value); + return FromSeconds(val); case DurationUnit.Week: - return FromWeeks(value); + return FromWeeks(val); case DurationUnit.Year: - return FromYears(value); + return FromYears(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -450,6 +491,18 @@ public static Duration From(double value, DurationUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(DurationUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -458,7 +511,7 @@ public static Duration From(double value, DurationUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(DurationUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(DurationUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -467,6 +520,7 @@ public static string GetAbbreviation(DurationUnit unit, CultureInfo culture = nu #region Arithmetic Operators +#if !WINDOWS_UWP public static Duration operator -(Duration right) { return new Duration(-right._seconds); @@ -501,6 +555,7 @@ public static string GetAbbreviation(DurationUnit unit, CultureInfo culture = nu { return Convert.ToDouble(left._seconds/right._seconds); } +#endif #endregion @@ -513,11 +568,17 @@ public int CompareTo(object obj) return CompareTo((Duration) obj); } - public int CompareTo(Duration other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(Duration other) { return _seconds.CompareTo(other._seconds); } +#if !WINDOWS_UWP public static bool operator <=(Duration left, Duration right) { return left._seconds <= right._seconds; @@ -549,6 +610,7 @@ public int CompareTo(Duration other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._seconds != right._seconds; } +#endif public override bool Equals(object obj) { @@ -612,7 +674,6 @@ public double As(DurationUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -631,10 +692,43 @@ public double As(DurationUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static Duration Parse(string str, IFormatProvider formatProvider = null) + public static Duration Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static Duration Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -658,7 +752,7 @@ public static Duration Parse(string str, IFormatProvider formatProvider = null) "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => Duration.FromSeconds(x.Seconds + y.Seconds)); } /// @@ -695,7 +789,7 @@ private static List ParseWithRegex(string regexString, string str, IFo converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -720,18 +814,49 @@ private static List ParseWithRegex(string regexString, string str, IFo /// /// The value of 'str' cannot be null. /// Error parsing string. - public static DurationUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static DurationUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static DurationUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static DurationUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == DurationUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized DurationUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -754,6 +879,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(DurationUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(DurationUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -762,9 +908,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(DurationUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(DurationUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -776,9 +924,20 @@ public string ToString(DurationUnit unit, CultureInfo culture = null, int signif /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(DurationUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(DurationUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/DynamicViscosity.g.cs b/UnitsNet/GeneratedCode/UnitClasses/DynamicViscosity.g.cs index ec83929e52..2bf17cba1c 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/DynamicViscosity.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/DynamicViscosity.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// The dynamic (shear) viscosity of a fluid expresses its resistance to shearing flows, where adjacent layers move parallel to each other with different speeds /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class DynamicViscosity +#else public partial struct DynamicViscosity : IComparable, IComparable +#endif { /// /// Base unit of DynamicViscosity. /// private readonly double _newtonSecondsPerMeterSquared; - public DynamicViscosity(double newtonsecondspermetersquared) : this() +#if WINDOWS_UWP + public DynamicViscosity() : this(0) + { + } +#endif + + public DynamicViscosity(double newtonsecondspermetersquared) + { + _newtonSecondsPerMeterSquared = Convert.ToDouble(newtonsecondspermetersquared); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + DynamicViscosity(long newtonsecondspermetersquared) + { + _newtonSecondsPerMeterSquared = Convert.ToDouble(newtonsecondspermetersquared); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + DynamicViscosity(decimal newtonsecondspermetersquared) { - _newtonSecondsPerMeterSquared = newtonsecondspermetersquared; + _newtonSecondsPerMeterSquared = Convert.ToDouble(newtonsecondspermetersquared); } #region Properties @@ -143,7 +182,7 @@ public static DynamicViscosity FromPoise(double poise) return new DynamicViscosity(poise/10); } - +#if !WINDOWS_UWP /// /// Get nullable DynamicViscosity from nullable Centipoise. /// @@ -155,7 +194,7 @@ public static DynamicViscosity FromPoise(double poise) } else { - return null; + return null; } } @@ -170,7 +209,7 @@ public static DynamicViscosity FromPoise(double poise) } else { - return null; + return null; } } @@ -185,7 +224,7 @@ public static DynamicViscosity FromPoise(double poise) } else { - return null; + return null; } } @@ -200,7 +239,7 @@ public static DynamicViscosity FromPoise(double poise) } else { - return null; + return null; } } @@ -215,37 +254,39 @@ public static DynamicViscosity FromPoise(double poise) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// DynamicViscosity unit value. - public static DynamicViscosity From(double value, DynamicViscosityUnit fromUnit) + public static DynamicViscosity From(double val, DynamicViscosityUnit fromUnit) { switch (fromUnit) { case DynamicViscosityUnit.Centipoise: - return FromCentipoise(value); + return FromCentipoise(val); case DynamicViscosityUnit.MillipascalSecond: - return FromMillipascalSeconds(value); + return FromMillipascalSeconds(val); case DynamicViscosityUnit.NewtonSecondPerMeterSquared: - return FromNewtonSecondsPerMeterSquared(value); + return FromNewtonSecondsPerMeterSquared(val); case DynamicViscosityUnit.PascalSecond: - return FromPascalSeconds(value); + return FromPascalSeconds(val); case DynamicViscosityUnit.Poise: - return FromPoise(value); + return FromPoise(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -275,6 +316,18 @@ public static DynamicViscosity From(double value, DynamicViscosityUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(DynamicViscosityUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -283,7 +336,7 @@ public static DynamicViscosity From(double value, DynamicViscosityUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(DynamicViscosityUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(DynamicViscosityUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -292,6 +345,7 @@ public static string GetAbbreviation(DynamicViscosityUnit unit, CultureInfo cult #region Arithmetic Operators +#if !WINDOWS_UWP public static DynamicViscosity operator -(DynamicViscosity right) { return new DynamicViscosity(-right._newtonSecondsPerMeterSquared); @@ -326,6 +380,7 @@ public static string GetAbbreviation(DynamicViscosityUnit unit, CultureInfo cult { return Convert.ToDouble(left._newtonSecondsPerMeterSquared/right._newtonSecondsPerMeterSquared); } +#endif #endregion @@ -338,11 +393,17 @@ public int CompareTo(object obj) return CompareTo((DynamicViscosity) obj); } - public int CompareTo(DynamicViscosity other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(DynamicViscosity other) { return _newtonSecondsPerMeterSquared.CompareTo(other._newtonSecondsPerMeterSquared); } +#if !WINDOWS_UWP public static bool operator <=(DynamicViscosity left, DynamicViscosity right) { return left._newtonSecondsPerMeterSquared <= right._newtonSecondsPerMeterSquared; @@ -374,6 +435,7 @@ public int CompareTo(DynamicViscosity other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._newtonSecondsPerMeterSquared != right._newtonSecondsPerMeterSquared; } +#endif public override bool Equals(object obj) { @@ -427,7 +489,6 @@ public double As(DynamicViscosityUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -446,10 +507,43 @@ public double As(DynamicViscosityUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static DynamicViscosity Parse(string str, IFormatProvider formatProvider = null) + public static DynamicViscosity Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static DynamicViscosity Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -473,7 +567,7 @@ public static DynamicViscosity Parse(string str, IFormatProvider formatProvider "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => DynamicViscosity.FromNewtonSecondsPerMeterSquared(x.NewtonSecondsPerMeterSquared + y.NewtonSecondsPerMeterSquared)); } /// @@ -510,7 +604,7 @@ private static List ParseWithRegex(string regexString, string converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -535,18 +629,49 @@ private static List ParseWithRegex(string regexString, string /// /// The value of 'str' cannot be null. /// Error parsing string. - public static DynamicViscosityUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static DynamicViscosityUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static DynamicViscosityUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static DynamicViscosityUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == DynamicViscosityUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized DynamicViscosityUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -569,6 +694,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(DynamicViscosityUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(DynamicViscosityUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -577,9 +723,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(DynamicViscosityUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(DynamicViscosityUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -591,9 +739,20 @@ public string ToString(DynamicViscosityUnit unit, CultureInfo culture = null, in /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(DynamicViscosityUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(DynamicViscosityUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/ElectricCurrent.g.cs b/UnitsNet/GeneratedCode/UnitClasses/ElectricCurrent.g.cs index a500d23eed..a96ce6af6c 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/ElectricCurrent.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/ElectricCurrent.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// An electric current is a flow of electric charge. In electric circuits this charge is often carried by moving electrons in a wire. It can also be carried by ions in an electrolyte, or by both ions and electrons such as in a plasma. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class ElectricCurrent +#else public partial struct ElectricCurrent : IComparable, IComparable +#endif { /// /// Base unit of ElectricCurrent. /// private readonly double _amperes; - public ElectricCurrent(double amperes) : this() +#if WINDOWS_UWP + public ElectricCurrent() : this(0) + { + } +#endif + + public ElectricCurrent(double amperes) + { + _amperes = Convert.ToDouble(amperes); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + ElectricCurrent(long amperes) + { + _amperes = Convert.ToDouble(amperes); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + ElectricCurrent(decimal amperes) { - _amperes = amperes; + _amperes = Convert.ToDouble(amperes); } #region Properties @@ -159,7 +198,7 @@ public static ElectricCurrent FromNanoamperes(double nanoamperes) return new ElectricCurrent((nanoamperes) * 1e-9d); } - +#if !WINDOWS_UWP /// /// Get nullable ElectricCurrent from nullable Amperes. /// @@ -171,7 +210,7 @@ public static ElectricCurrent FromNanoamperes(double nanoamperes) } else { - return null; + return null; } } @@ -186,7 +225,7 @@ public static ElectricCurrent FromNanoamperes(double nanoamperes) } else { - return null; + return null; } } @@ -201,7 +240,7 @@ public static ElectricCurrent FromNanoamperes(double nanoamperes) } else { - return null; + return null; } } @@ -216,7 +255,7 @@ public static ElectricCurrent FromNanoamperes(double nanoamperes) } else { - return null; + return null; } } @@ -231,7 +270,7 @@ public static ElectricCurrent FromNanoamperes(double nanoamperes) } else { - return null; + return null; } } @@ -246,39 +285,41 @@ public static ElectricCurrent FromNanoamperes(double nanoamperes) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// ElectricCurrent unit value. - public static ElectricCurrent From(double value, ElectricCurrentUnit fromUnit) + public static ElectricCurrent From(double val, ElectricCurrentUnit fromUnit) { switch (fromUnit) { case ElectricCurrentUnit.Ampere: - return FromAmperes(value); + return FromAmperes(val); case ElectricCurrentUnit.Kiloampere: - return FromKiloamperes(value); + return FromKiloamperes(val); case ElectricCurrentUnit.Megaampere: - return FromMegaamperes(value); + return FromMegaamperes(val); case ElectricCurrentUnit.Microampere: - return FromMicroamperes(value); + return FromMicroamperes(val); case ElectricCurrentUnit.Milliampere: - return FromMilliamperes(value); + return FromMilliamperes(val); case ElectricCurrentUnit.Nanoampere: - return FromNanoamperes(value); + return FromNanoamperes(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -310,6 +351,18 @@ public static ElectricCurrent From(double value, ElectricCurrentUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(ElectricCurrentUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -318,7 +371,7 @@ public static ElectricCurrent From(double value, ElectricCurrentUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(ElectricCurrentUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(ElectricCurrentUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -327,6 +380,7 @@ public static string GetAbbreviation(ElectricCurrentUnit unit, CultureInfo cultu #region Arithmetic Operators +#if !WINDOWS_UWP public static ElectricCurrent operator -(ElectricCurrent right) { return new ElectricCurrent(-right._amperes); @@ -361,6 +415,7 @@ public static string GetAbbreviation(ElectricCurrentUnit unit, CultureInfo cultu { return Convert.ToDouble(left._amperes/right._amperes); } +#endif #endregion @@ -373,11 +428,17 @@ public int CompareTo(object obj) return CompareTo((ElectricCurrent) obj); } - public int CompareTo(ElectricCurrent other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(ElectricCurrent other) { return _amperes.CompareTo(other._amperes); } +#if !WINDOWS_UWP public static bool operator <=(ElectricCurrent left, ElectricCurrent right) { return left._amperes <= right._amperes; @@ -409,6 +470,7 @@ public int CompareTo(ElectricCurrent other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._amperes != right._amperes; } +#endif public override bool Equals(object obj) { @@ -464,7 +526,6 @@ public double As(ElectricCurrentUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -483,10 +544,43 @@ public double As(ElectricCurrentUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static ElectricCurrent Parse(string str, IFormatProvider formatProvider = null) + public static ElectricCurrent Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static ElectricCurrent Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -510,7 +604,7 @@ public static ElectricCurrent Parse(string str, IFormatProvider formatProvider = "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => ElectricCurrent.FromAmperes(x.Amperes + y.Amperes)); } /// @@ -547,7 +641,7 @@ private static List ParseWithRegex(string regexString, string s converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -572,18 +666,49 @@ private static List ParseWithRegex(string regexString, string s /// /// The value of 'str' cannot be null. /// Error parsing string. - public static ElectricCurrentUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static ElectricCurrentUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static ElectricCurrentUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static ElectricCurrentUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == ElectricCurrentUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized ElectricCurrentUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -606,6 +731,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(ElectricCurrentUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(ElectricCurrentUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -614,9 +760,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(ElectricCurrentUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(ElectricCurrentUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -628,9 +776,20 @@ public string ToString(ElectricCurrentUnit unit, CultureInfo culture = null, int /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(ElectricCurrentUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(ElectricCurrentUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/ElectricPotential.g.cs b/UnitsNet/GeneratedCode/UnitClasses/ElectricPotential.g.cs index bab5c52aa4..4a9bf7fbf1 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/ElectricPotential.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/ElectricPotential.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// In classical electromagnetism, the electric potential (a scalar quantity denoted by Φ, ΦE or V and also called the electric field potential or the electrostatic potential) at a point is the amount of electric potential energy that a unitary point charge would have when located at that point. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class ElectricPotential +#else public partial struct ElectricPotential : IComparable, IComparable +#endif { /// /// Base unit of ElectricPotential. /// private readonly double _volts; - public ElectricPotential(double volts) : this() +#if WINDOWS_UWP + public ElectricPotential() : this(0) + { + } +#endif + + public ElectricPotential(double volts) + { + _volts = Convert.ToDouble(volts); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + ElectricPotential(long volts) + { + _volts = Convert.ToDouble(volts); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + ElectricPotential(decimal volts) { - _volts = volts; + _volts = Convert.ToDouble(volts); } #region Properties @@ -143,7 +182,7 @@ public static ElectricPotential FromVolts(double volts) return new ElectricPotential(volts); } - +#if !WINDOWS_UWP /// /// Get nullable ElectricPotential from nullable Kilovolts. /// @@ -155,7 +194,7 @@ public static ElectricPotential FromVolts(double volts) } else { - return null; + return null; } } @@ -170,7 +209,7 @@ public static ElectricPotential FromVolts(double volts) } else { - return null; + return null; } } @@ -185,7 +224,7 @@ public static ElectricPotential FromVolts(double volts) } else { - return null; + return null; } } @@ -200,7 +239,7 @@ public static ElectricPotential FromVolts(double volts) } else { - return null; + return null; } } @@ -215,37 +254,39 @@ public static ElectricPotential FromVolts(double volts) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// ElectricPotential unit value. - public static ElectricPotential From(double value, ElectricPotentialUnit fromUnit) + public static ElectricPotential From(double val, ElectricPotentialUnit fromUnit) { switch (fromUnit) { case ElectricPotentialUnit.Kilovolt: - return FromKilovolts(value); + return FromKilovolts(val); case ElectricPotentialUnit.Megavolt: - return FromMegavolts(value); + return FromMegavolts(val); case ElectricPotentialUnit.Microvolt: - return FromMicrovolts(value); + return FromMicrovolts(val); case ElectricPotentialUnit.Millivolt: - return FromMillivolts(value); + return FromMillivolts(val); case ElectricPotentialUnit.Volt: - return FromVolts(value); + return FromVolts(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -275,6 +316,18 @@ public static ElectricPotential From(double value, ElectricPotentialUnit fromUni throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(ElectricPotentialUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -283,7 +336,7 @@ public static ElectricPotential From(double value, ElectricPotentialUnit fromUni /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(ElectricPotentialUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(ElectricPotentialUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -292,6 +345,7 @@ public static string GetAbbreviation(ElectricPotentialUnit unit, CultureInfo cul #region Arithmetic Operators +#if !WINDOWS_UWP public static ElectricPotential operator -(ElectricPotential right) { return new ElectricPotential(-right._volts); @@ -326,6 +380,7 @@ public static string GetAbbreviation(ElectricPotentialUnit unit, CultureInfo cul { return Convert.ToDouble(left._volts/right._volts); } +#endif #endregion @@ -338,11 +393,17 @@ public int CompareTo(object obj) return CompareTo((ElectricPotential) obj); } - public int CompareTo(ElectricPotential other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(ElectricPotential other) { return _volts.CompareTo(other._volts); } +#if !WINDOWS_UWP public static bool operator <=(ElectricPotential left, ElectricPotential right) { return left._volts <= right._volts; @@ -374,6 +435,7 @@ public int CompareTo(ElectricPotential other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._volts != right._volts; } +#endif public override bool Equals(object obj) { @@ -427,7 +489,6 @@ public double As(ElectricPotentialUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -446,10 +507,43 @@ public double As(ElectricPotentialUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static ElectricPotential Parse(string str, IFormatProvider formatProvider = null) + public static ElectricPotential Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static ElectricPotential Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -473,7 +567,7 @@ public static ElectricPotential Parse(string str, IFormatProvider formatProvider "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => ElectricPotential.FromVolts(x.Volts + y.Volts)); } /// @@ -510,7 +604,7 @@ private static List ParseWithRegex(string regexString, string converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -535,18 +629,49 @@ private static List ParseWithRegex(string regexString, string /// /// The value of 'str' cannot be null. /// Error parsing string. - public static ElectricPotentialUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static ElectricPotentialUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static ElectricPotentialUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static ElectricPotentialUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == ElectricPotentialUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized ElectricPotentialUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -569,6 +694,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(ElectricPotentialUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(ElectricPotentialUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -577,9 +723,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(ElectricPotentialUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(ElectricPotentialUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -591,9 +739,20 @@ public string ToString(ElectricPotentialUnit unit, CultureInfo culture = null, i /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(ElectricPotentialUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(ElectricPotentialUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/ElectricResistance.g.cs b/UnitsNet/GeneratedCode/UnitClasses/ElectricResistance.g.cs index 82778c0778..a9a8a3ac28 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/ElectricResistance.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/ElectricResistance.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// The electrical resistance of an electrical conductor is the opposition to the passage of an electric current through that conductor. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class ElectricResistance +#else public partial struct ElectricResistance : IComparable, IComparable +#endif { /// /// Base unit of ElectricResistance. /// private readonly double _ohms; - public ElectricResistance(double ohms) : this() +#if WINDOWS_UWP + public ElectricResistance() : this(0) + { + } +#endif + + public ElectricResistance(double ohms) + { + _ohms = Convert.ToDouble(ohms); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + ElectricResistance(long ohms) + { + _ohms = Convert.ToDouble(ohms); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + ElectricResistance(decimal ohms) { - _ohms = ohms; + _ohms = Convert.ToDouble(ohms); } #region Properties @@ -111,7 +150,7 @@ public static ElectricResistance FromOhms(double ohms) return new ElectricResistance(ohms); } - +#if !WINDOWS_UWP /// /// Get nullable ElectricResistance from nullable Kiloohms. /// @@ -123,7 +162,7 @@ public static ElectricResistance FromOhms(double ohms) } else { - return null; + return null; } } @@ -138,7 +177,7 @@ public static ElectricResistance FromOhms(double ohms) } else { - return null; + return null; } } @@ -153,33 +192,35 @@ public static ElectricResistance FromOhms(double ohms) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// ElectricResistance unit value. - public static ElectricResistance From(double value, ElectricResistanceUnit fromUnit) + public static ElectricResistance From(double val, ElectricResistanceUnit fromUnit) { switch (fromUnit) { case ElectricResistanceUnit.Kiloohm: - return FromKiloohms(value); + return FromKiloohms(val); case ElectricResistanceUnit.Megaohm: - return FromMegaohms(value); + return FromMegaohms(val); case ElectricResistanceUnit.Ohm: - return FromOhms(value); + return FromOhms(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -205,6 +246,18 @@ public static ElectricResistance From(double value, ElectricResistanceUnit fromU throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(ElectricResistanceUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -213,7 +266,7 @@ public static ElectricResistance From(double value, ElectricResistanceUnit fromU /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(ElectricResistanceUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(ElectricResistanceUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -222,6 +275,7 @@ public static string GetAbbreviation(ElectricResistanceUnit unit, CultureInfo cu #region Arithmetic Operators +#if !WINDOWS_UWP public static ElectricResistance operator -(ElectricResistance right) { return new ElectricResistance(-right._ohms); @@ -256,6 +310,7 @@ public static string GetAbbreviation(ElectricResistanceUnit unit, CultureInfo cu { return Convert.ToDouble(left._ohms/right._ohms); } +#endif #endregion @@ -268,11 +323,17 @@ public int CompareTo(object obj) return CompareTo((ElectricResistance) obj); } - public int CompareTo(ElectricResistance other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(ElectricResistance other) { return _ohms.CompareTo(other._ohms); } +#if !WINDOWS_UWP public static bool operator <=(ElectricResistance left, ElectricResistance right) { return left._ohms <= right._ohms; @@ -304,6 +365,7 @@ public int CompareTo(ElectricResistance other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._ohms != right._ohms; } +#endif public override bool Equals(object obj) { @@ -353,7 +415,6 @@ public double As(ElectricResistanceUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -372,10 +433,43 @@ public double As(ElectricResistanceUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static ElectricResistance Parse(string str, IFormatProvider formatProvider = null) + public static ElectricResistance Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static ElectricResistance Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -399,7 +493,7 @@ public static ElectricResistance Parse(string str, IFormatProvider formatProvide "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => ElectricResistance.FromOhms(x.Ohms + y.Ohms)); } /// @@ -436,7 +530,7 @@ private static List ParseWithRegex(string regexString, strin converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -461,18 +555,49 @@ private static List ParseWithRegex(string regexString, strin /// /// The value of 'str' cannot be null. /// Error parsing string. - public static ElectricResistanceUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static ElectricResistanceUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static ElectricResistanceUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static ElectricResistanceUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == ElectricResistanceUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized ElectricResistanceUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -495,6 +620,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(ElectricResistanceUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(ElectricResistanceUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -503,9 +649,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(ElectricResistanceUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(ElectricResistanceUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -517,9 +665,20 @@ public string ToString(ElectricResistanceUnit unit, CultureInfo culture = null, /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(ElectricResistanceUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(ElectricResistanceUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/Energy.g.cs b/UnitsNet/GeneratedCode/UnitClasses/Energy.g.cs index b3f389c137..79ec46159c 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/Energy.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/Energy.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// The joule, symbol J, is a derived unit of energy, work, or amount of heat in the International System of Units. It is equal to the energy transferred (or work done) when applying a force of one newton through a distance of one metre (1 newton metre or N·m), or in passing an electric current of one ampere through a resistance of one ohm for one second. Many other units of energy are included. Please do not confuse this definition of the calorie with the one colloquially used by the food industry, the large calorie, which is equivalent to 1 kcal. Thermochemical definition of the calorie is used. For BTU, the IT definition is used. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class Energy +#else public partial struct Energy : IComparable, IComparable +#endif { /// /// Base unit of Energy. /// private readonly double _joules; - public Energy(double joules) : this() +#if WINDOWS_UWP + public Energy() : this(0) + { + } +#endif + + public Energy(double joules) + { + _joules = Convert.ToDouble(joules); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Energy(long joules) { - _joules = joules; + _joules = Convert.ToDouble(joules); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Energy(decimal joules) + { + _joules = Convert.ToDouble(joules); } #region Properties @@ -271,7 +310,7 @@ public static Energy FromWattHours(double watthours) return new Energy(watthours*3600d); } - +#if !WINDOWS_UWP /// /// Get nullable Energy from nullable BritishThermalUnits. /// @@ -283,7 +322,7 @@ public static Energy FromWattHours(double watthours) } else { - return null; + return null; } } @@ -298,7 +337,7 @@ public static Energy FromWattHours(double watthours) } else { - return null; + return null; } } @@ -313,7 +352,7 @@ public static Energy FromWattHours(double watthours) } else { - return null; + return null; } } @@ -328,7 +367,7 @@ public static Energy FromWattHours(double watthours) } else { - return null; + return null; } } @@ -343,7 +382,7 @@ public static Energy FromWattHours(double watthours) } else { - return null; + return null; } } @@ -358,7 +397,7 @@ public static Energy FromWattHours(double watthours) } else { - return null; + return null; } } @@ -373,7 +412,7 @@ public static Energy FromWattHours(double watthours) } else { - return null; + return null; } } @@ -388,7 +427,7 @@ public static Energy FromWattHours(double watthours) } else { - return null; + return null; } } @@ -403,7 +442,7 @@ public static Energy FromWattHours(double watthours) } else { - return null; + return null; } } @@ -418,7 +457,7 @@ public static Energy FromWattHours(double watthours) } else { - return null; + return null; } } @@ -433,7 +472,7 @@ public static Energy FromWattHours(double watthours) } else { - return null; + return null; } } @@ -448,7 +487,7 @@ public static Energy FromWattHours(double watthours) } else { - return null; + return null; } } @@ -463,53 +502,55 @@ public static Energy FromWattHours(double watthours) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// Energy unit value. - public static Energy From(double value, EnergyUnit fromUnit) + public static Energy From(double val, EnergyUnit fromUnit) { switch (fromUnit) { case EnergyUnit.BritishThermalUnit: - return FromBritishThermalUnits(value); + return FromBritishThermalUnits(val); case EnergyUnit.Calorie: - return FromCalories(value); + return FromCalories(val); case EnergyUnit.ElectronVolt: - return FromElectronVolts(value); + return FromElectronVolts(val); case EnergyUnit.Erg: - return FromErgs(value); + return FromErgs(val); case EnergyUnit.FootPound: - return FromFootPounds(value); + return FromFootPounds(val); case EnergyUnit.GigawattHour: - return FromGigawattHours(value); + return FromGigawattHours(val); case EnergyUnit.Joule: - return FromJoules(value); + return FromJoules(val); case EnergyUnit.Kilocalorie: - return FromKilocalories(value); + return FromKilocalories(val); case EnergyUnit.Kilojoule: - return FromKilojoules(value); + return FromKilojoules(val); case EnergyUnit.KilowattHour: - return FromKilowattHours(value); + return FromKilowattHours(val); case EnergyUnit.Megajoule: - return FromMegajoules(value); + return FromMegajoules(val); case EnergyUnit.MegawattHour: - return FromMegawattHours(value); + return FromMegawattHours(val); case EnergyUnit.WattHour: - return FromWattHours(value); + return FromWattHours(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -555,6 +596,18 @@ public static Energy From(double value, EnergyUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(EnergyUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -563,7 +616,7 @@ public static Energy From(double value, EnergyUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(EnergyUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(EnergyUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -572,6 +625,7 @@ public static string GetAbbreviation(EnergyUnit unit, CultureInfo culture = null #region Arithmetic Operators +#if !WINDOWS_UWP public static Energy operator -(Energy right) { return new Energy(-right._joules); @@ -606,6 +660,7 @@ public static string GetAbbreviation(EnergyUnit unit, CultureInfo culture = null { return Convert.ToDouble(left._joules/right._joules); } +#endif #endregion @@ -618,11 +673,17 @@ public int CompareTo(object obj) return CompareTo((Energy) obj); } - public int CompareTo(Energy other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(Energy other) { return _joules.CompareTo(other._joules); } +#if !WINDOWS_UWP public static bool operator <=(Energy left, Energy right) { return left._joules <= right._joules; @@ -654,6 +715,7 @@ public int CompareTo(Energy other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._joules != right._joules; } +#endif public override bool Equals(object obj) { @@ -723,7 +785,6 @@ public double As(EnergyUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -742,10 +803,43 @@ public double As(EnergyUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static Energy Parse(string str, IFormatProvider formatProvider = null) + public static Energy Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static Energy Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -769,7 +863,7 @@ public static Energy Parse(string str, IFormatProvider formatProvider = null) "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => Energy.FromJoules(x.Joules + y.Joules)); } /// @@ -806,7 +900,7 @@ private static List ParseWithRegex(string regexString, string str, IForm converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -831,18 +925,49 @@ private static List ParseWithRegex(string regexString, string str, IForm /// /// The value of 'str' cannot be null. /// Error parsing string. - public static EnergyUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static EnergyUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static EnergyUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static EnergyUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == EnergyUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized EnergyUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -865,6 +990,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(EnergyUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(EnergyUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -873,9 +1019,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(EnergyUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(EnergyUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -887,9 +1035,20 @@ public string ToString(EnergyUnit unit, CultureInfo culture = null, int signific /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(EnergyUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(EnergyUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/Flow.g.cs b/UnitsNet/GeneratedCode/UnitClasses/Flow.g.cs index 92056ea040..2770814587 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/Flow.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/Flow.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// In physics and engineering, in particular fluid dynamics and hydrometry, the volumetric flow rate, (also known as volume flow rate, rate of fluid flow or volume velocity) is the volume of fluid which passes through a given surface per unit time. The SI unit is m3·s−1 (cubic meters per second). In US Customary Units and British Imperial Units, volumetric flow rate is often expressed as ft3/s (cubic feet per second). It is usually represented by the symbol Q. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class Flow +#else public partial struct Flow : IComparable, IComparable +#endif { /// /// Base unit of Flow. /// private readonly double _cubicMetersPerSecond; - public Flow(double cubicmeterspersecond) : this() +#if WINDOWS_UWP + public Flow() : this(0) + { + } +#endif + + public Flow(double cubicmeterspersecond) + { + _cubicMetersPerSecond = Convert.ToDouble(cubicmeterspersecond); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Flow(long cubicmeterspersecond) { - _cubicMetersPerSecond = cubicmeterspersecond; + _cubicMetersPerSecond = Convert.ToDouble(cubicmeterspersecond); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Flow(decimal cubicmeterspersecond) + { + _cubicMetersPerSecond = Convert.ToDouble(cubicmeterspersecond); } #region Properties @@ -255,7 +294,7 @@ public static Flow FromUsGallonsPerMinute(double usgallonsperminute) return new Flow(usgallonsperminute/15850.323141489); } - +#if !WINDOWS_UWP /// /// Get nullable Flow from nullable CentilitersPerMinute. /// @@ -267,7 +306,7 @@ public static Flow FromUsGallonsPerMinute(double usgallonsperminute) } else { - return null; + return null; } } @@ -282,7 +321,7 @@ public static Flow FromUsGallonsPerMinute(double usgallonsperminute) } else { - return null; + return null; } } @@ -297,7 +336,7 @@ public static Flow FromUsGallonsPerMinute(double usgallonsperminute) } else { - return null; + return null; } } @@ -312,7 +351,7 @@ public static Flow FromUsGallonsPerMinute(double usgallonsperminute) } else { - return null; + return null; } } @@ -327,7 +366,7 @@ public static Flow FromUsGallonsPerMinute(double usgallonsperminute) } else { - return null; + return null; } } @@ -342,7 +381,7 @@ public static Flow FromUsGallonsPerMinute(double usgallonsperminute) } else { - return null; + return null; } } @@ -357,7 +396,7 @@ public static Flow FromUsGallonsPerMinute(double usgallonsperminute) } else { - return null; + return null; } } @@ -372,7 +411,7 @@ public static Flow FromUsGallonsPerMinute(double usgallonsperminute) } else { - return null; + return null; } } @@ -387,7 +426,7 @@ public static Flow FromUsGallonsPerMinute(double usgallonsperminute) } else { - return null; + return null; } } @@ -402,7 +441,7 @@ public static Flow FromUsGallonsPerMinute(double usgallonsperminute) } else { - return null; + return null; } } @@ -417,7 +456,7 @@ public static Flow FromUsGallonsPerMinute(double usgallonsperminute) } else { - return null; + return null; } } @@ -432,51 +471,53 @@ public static Flow FromUsGallonsPerMinute(double usgallonsperminute) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// Flow unit value. - public static Flow From(double value, FlowUnit fromUnit) + public static Flow From(double val, FlowUnit fromUnit) { switch (fromUnit) { case FlowUnit.CentilitersPerMinute: - return FromCentilitersPerMinute(value); + return FromCentilitersPerMinute(val); case FlowUnit.CubicFootPerSecond: - return FromCubicFeetPerSecond(value); + return FromCubicFeetPerSecond(val); case FlowUnit.CubicMeterPerHour: - return FromCubicMetersPerHour(value); + return FromCubicMetersPerHour(val); case FlowUnit.CubicMeterPerSecond: - return FromCubicMetersPerSecond(value); + return FromCubicMetersPerSecond(val); case FlowUnit.DecilitersPerMinute: - return FromDecilitersPerMinute(value); + return FromDecilitersPerMinute(val); case FlowUnit.KilolitersPerMinute: - return FromKilolitersPerMinute(value); + return FromKilolitersPerMinute(val); case FlowUnit.LitersPerMinute: - return FromLitersPerMinute(value); + return FromLitersPerMinute(val); case FlowUnit.MicrolitersPerMinute: - return FromMicrolitersPerMinute(value); + return FromMicrolitersPerMinute(val); case FlowUnit.MillilitersPerMinute: - return FromMillilitersPerMinute(value); + return FromMillilitersPerMinute(val); case FlowUnit.MillionUsGallonsPerDay: - return FromMillionUsGallonsPerDay(value); + return FromMillionUsGallonsPerDay(val); case FlowUnit.NanolitersPerMinute: - return FromNanolitersPerMinute(value); + return FromNanolitersPerMinute(val); case FlowUnit.UsGallonsPerMinute: - return FromUsGallonsPerMinute(value); + return FromUsGallonsPerMinute(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -520,6 +561,18 @@ public static Flow From(double value, FlowUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(FlowUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -528,7 +581,7 @@ public static Flow From(double value, FlowUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(FlowUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(FlowUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -537,6 +590,7 @@ public static string GetAbbreviation(FlowUnit unit, CultureInfo culture = null) #region Arithmetic Operators +#if !WINDOWS_UWP public static Flow operator -(Flow right) { return new Flow(-right._cubicMetersPerSecond); @@ -571,6 +625,7 @@ public static string GetAbbreviation(FlowUnit unit, CultureInfo culture = null) { return Convert.ToDouble(left._cubicMetersPerSecond/right._cubicMetersPerSecond); } +#endif #endregion @@ -583,11 +638,17 @@ public int CompareTo(object obj) return CompareTo((Flow) obj); } - public int CompareTo(Flow other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(Flow other) { return _cubicMetersPerSecond.CompareTo(other._cubicMetersPerSecond); } +#if !WINDOWS_UWP public static bool operator <=(Flow left, Flow right) { return left._cubicMetersPerSecond <= right._cubicMetersPerSecond; @@ -619,6 +680,7 @@ public int CompareTo(Flow other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._cubicMetersPerSecond != right._cubicMetersPerSecond; } +#endif public override bool Equals(object obj) { @@ -686,7 +748,6 @@ public double As(FlowUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -705,10 +766,43 @@ public double As(FlowUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static Flow Parse(string str, IFormatProvider formatProvider = null) + public static Flow Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static Flow Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -732,7 +826,7 @@ public static Flow Parse(string str, IFormatProvider formatProvider = null) "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => Flow.FromCubicMetersPerSecond(x.CubicMetersPerSecond + y.CubicMetersPerSecond)); } /// @@ -769,7 +863,7 @@ private static List ParseWithRegex(string regexString, string str, IFormat converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -794,18 +888,49 @@ private static List ParseWithRegex(string regexString, string str, IFormat /// /// The value of 'str' cannot be null. /// Error parsing string. - public static FlowUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static FlowUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static FlowUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static FlowUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == FlowUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized FlowUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -828,6 +953,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(FlowUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(FlowUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -836,9 +982,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(FlowUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(FlowUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -850,9 +998,20 @@ public string ToString(FlowUnit unit, CultureInfo culture = null, int significan /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(FlowUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(FlowUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/Force.g.cs b/UnitsNet/GeneratedCode/UnitClasses/Force.g.cs index 6fb0ffb548..7c95bf0766 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/Force.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/Force.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// In physics, a force is any influence that causes an object to undergo a certain change, either concerning its movement, direction, or geometrical construction. In other words, a force can cause an object with mass to change its velocity (which includes to begin moving from a state of rest), i.e., to accelerate, or a flexible object to deform, or both. Force can also be described by intuitive concepts such as a push or a pull. A force has both magnitude and direction, making it a vector quantity. It is measured in the SI unit of newtons and represented by the symbol F. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class Force +#else public partial struct Force : IComparable, IComparable +#endif { /// /// Base unit of Force. /// private readonly double _newtons; - public Force(double newtons) : this() +#if WINDOWS_UWP + public Force() : this(0) + { + } +#endif + + public Force(double newtons) + { + _newtons = Convert.ToDouble(newtons); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Force(long newtons) + { + _newtons = Convert.ToDouble(newtons); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Force(decimal newtons) { - _newtons = newtons; + _newtons = Convert.ToDouble(newtons); } #region Properties @@ -191,7 +230,7 @@ public static Force FromTonnesForce(double tonnesforce) return new Force(tonnesforce*Constants.Gravity*1000); } - +#if !WINDOWS_UWP /// /// Get nullable Force from nullable Dyne. /// @@ -203,7 +242,7 @@ public static Force FromTonnesForce(double tonnesforce) } else { - return null; + return null; } } @@ -218,7 +257,7 @@ public static Force FromTonnesForce(double tonnesforce) } else { - return null; + return null; } } @@ -233,7 +272,7 @@ public static Force FromTonnesForce(double tonnesforce) } else { - return null; + return null; } } @@ -248,7 +287,7 @@ public static Force FromTonnesForce(double tonnesforce) } else { - return null; + return null; } } @@ -263,7 +302,7 @@ public static Force FromTonnesForce(double tonnesforce) } else { - return null; + return null; } } @@ -278,7 +317,7 @@ public static Force FromTonnesForce(double tonnesforce) } else { - return null; + return null; } } @@ -293,7 +332,7 @@ public static Force FromTonnesForce(double tonnesforce) } else { - return null; + return null; } } @@ -308,43 +347,45 @@ public static Force FromTonnesForce(double tonnesforce) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// Force unit value. - public static Force From(double value, ForceUnit fromUnit) + public static Force From(double val, ForceUnit fromUnit) { switch (fromUnit) { case ForceUnit.Dyn: - return FromDyne(value); + return FromDyne(val); case ForceUnit.KilogramForce: - return FromKilogramsForce(value); + return FromKilogramsForce(val); case ForceUnit.Kilonewton: - return FromKilonewtons(value); + return FromKilonewtons(val); case ForceUnit.KiloPond: - return FromKiloPonds(value); + return FromKiloPonds(val); case ForceUnit.Newton: - return FromNewtons(value); + return FromNewtons(val); case ForceUnit.Poundal: - return FromPoundals(value); + return FromPoundals(val); case ForceUnit.PoundForce: - return FromPoundsForce(value); + return FromPoundsForce(val); case ForceUnit.TonneForce: - return FromTonnesForce(value); + return FromTonnesForce(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -380,6 +421,18 @@ public static Force From(double value, ForceUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(ForceUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -388,7 +441,7 @@ public static Force From(double value, ForceUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(ForceUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(ForceUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -397,6 +450,7 @@ public static string GetAbbreviation(ForceUnit unit, CultureInfo culture = null) #region Arithmetic Operators +#if !WINDOWS_UWP public static Force operator -(Force right) { return new Force(-right._newtons); @@ -431,6 +485,7 @@ public static string GetAbbreviation(ForceUnit unit, CultureInfo culture = null) { return Convert.ToDouble(left._newtons/right._newtons); } +#endif #endregion @@ -443,11 +498,17 @@ public int CompareTo(object obj) return CompareTo((Force) obj); } - public int CompareTo(Force other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(Force other) { return _newtons.CompareTo(other._newtons); } +#if !WINDOWS_UWP public static bool operator <=(Force left, Force right) { return left._newtons <= right._newtons; @@ -479,6 +540,7 @@ public int CompareTo(Force other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._newtons != right._newtons; } +#endif public override bool Equals(object obj) { @@ -538,7 +600,6 @@ public double As(ForceUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -557,10 +618,43 @@ public double As(ForceUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static Force Parse(string str, IFormatProvider formatProvider = null) + public static Force Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static Force Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -584,7 +678,7 @@ public static Force Parse(string str, IFormatProvider formatProvider = null) "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => Force.FromNewtons(x.Newtons + y.Newtons)); } /// @@ -621,7 +715,7 @@ private static List ParseWithRegex(string regexString, string str, IForma converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -646,18 +740,49 @@ private static List ParseWithRegex(string regexString, string str, IForma /// /// The value of 'str' cannot be null. /// Error parsing string. - public static ForceUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static ForceUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static ForceUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static ForceUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == ForceUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized ForceUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -680,6 +805,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(ForceUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(ForceUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -688,9 +834,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(ForceUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(ForceUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -702,9 +850,20 @@ public string ToString(ForceUnit unit, CultureInfo culture = null, int significa /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(ForceUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(ForceUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/ForceChangeRate.g.cs b/UnitsNet/GeneratedCode/UnitClasses/ForceChangeRate.g.cs index 0870989f65..91878c066a 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/ForceChangeRate.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/ForceChangeRate.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// Force change rate is the ratio of the force change to the time during which the change occurred (value of force changes per unit time). /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class ForceChangeRate +#else public partial struct ForceChangeRate : IComparable, IComparable +#endif { /// /// Base unit of ForceChangeRate. /// private readonly double _newtonsPerSecond; - public ForceChangeRate(double newtonspersecond) : this() +#if WINDOWS_UWP + public ForceChangeRate() : this(0) + { + } +#endif + + public ForceChangeRate(double newtonspersecond) + { + _newtonsPerSecond = Convert.ToDouble(newtonspersecond); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + ForceChangeRate(long newtonspersecond) + { + _newtonsPerSecond = Convert.ToDouble(newtonspersecond); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + ForceChangeRate(decimal newtonspersecond) { - _newtonsPerSecond = newtonspersecond; + _newtonsPerSecond = Convert.ToDouble(newtonspersecond); } #region Properties @@ -175,7 +214,7 @@ public static ForceChangeRate FromNewtonsPerSecond(double newtonspersecond) return new ForceChangeRate(newtonspersecond); } - +#if !WINDOWS_UWP /// /// Get nullable ForceChangeRate from nullable CentinewtonsPerSecond. /// @@ -187,7 +226,7 @@ public static ForceChangeRate FromNewtonsPerSecond(double newtonspersecond) } else { - return null; + return null; } } @@ -202,7 +241,7 @@ public static ForceChangeRate FromNewtonsPerSecond(double newtonspersecond) } else { - return null; + return null; } } @@ -217,7 +256,7 @@ public static ForceChangeRate FromNewtonsPerSecond(double newtonspersecond) } else { - return null; + return null; } } @@ -232,7 +271,7 @@ public static ForceChangeRate FromNewtonsPerSecond(double newtonspersecond) } else { - return null; + return null; } } @@ -247,7 +286,7 @@ public static ForceChangeRate FromNewtonsPerSecond(double newtonspersecond) } else { - return null; + return null; } } @@ -262,7 +301,7 @@ public static ForceChangeRate FromNewtonsPerSecond(double newtonspersecond) } else { - return null; + return null; } } @@ -277,41 +316,43 @@ public static ForceChangeRate FromNewtonsPerSecond(double newtonspersecond) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// ForceChangeRate unit value. - public static ForceChangeRate From(double value, ForceChangeRateUnit fromUnit) + public static ForceChangeRate From(double val, ForceChangeRateUnit fromUnit) { switch (fromUnit) { case ForceChangeRateUnit.CentinewtonPerSecond: - return FromCentinewtonsPerSecond(value); + return FromCentinewtonsPerSecond(val); case ForceChangeRateUnit.DecinewtonPerSecond: - return FromDecinewtonsPerSecond(value); + return FromDecinewtonsPerSecond(val); case ForceChangeRateUnit.KilonewtonPerSecond: - return FromKilonewtonsPerSecond(value); + return FromKilonewtonsPerSecond(val); case ForceChangeRateUnit.MicronewtonPerSecond: - return FromMicronewtonsPerSecond(value); + return FromMicronewtonsPerSecond(val); case ForceChangeRateUnit.MillinewtonPerSecond: - return FromMillinewtonsPerSecond(value); + return FromMillinewtonsPerSecond(val); case ForceChangeRateUnit.NanonewtonPerSecond: - return FromNanonewtonsPerSecond(value); + return FromNanonewtonsPerSecond(val); case ForceChangeRateUnit.NewtonPerSecond: - return FromNewtonsPerSecond(value); + return FromNewtonsPerSecond(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -345,6 +386,18 @@ public static ForceChangeRate From(double value, ForceChangeRateUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(ForceChangeRateUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -353,7 +406,7 @@ public static ForceChangeRate From(double value, ForceChangeRateUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(ForceChangeRateUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(ForceChangeRateUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -362,6 +415,7 @@ public static string GetAbbreviation(ForceChangeRateUnit unit, CultureInfo cultu #region Arithmetic Operators +#if !WINDOWS_UWP public static ForceChangeRate operator -(ForceChangeRate right) { return new ForceChangeRate(-right._newtonsPerSecond); @@ -396,6 +450,7 @@ public static string GetAbbreviation(ForceChangeRateUnit unit, CultureInfo cultu { return Convert.ToDouble(left._newtonsPerSecond/right._newtonsPerSecond); } +#endif #endregion @@ -408,11 +463,17 @@ public int CompareTo(object obj) return CompareTo((ForceChangeRate) obj); } - public int CompareTo(ForceChangeRate other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(ForceChangeRate other) { return _newtonsPerSecond.CompareTo(other._newtonsPerSecond); } +#if !WINDOWS_UWP public static bool operator <=(ForceChangeRate left, ForceChangeRate right) { return left._newtonsPerSecond <= right._newtonsPerSecond; @@ -444,6 +505,7 @@ public int CompareTo(ForceChangeRate other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._newtonsPerSecond != right._newtonsPerSecond; } +#endif public override bool Equals(object obj) { @@ -501,7 +563,6 @@ public double As(ForceChangeRateUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -520,10 +581,43 @@ public double As(ForceChangeRateUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static ForceChangeRate Parse(string str, IFormatProvider formatProvider = null) + public static ForceChangeRate Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static ForceChangeRate Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -547,7 +641,7 @@ public static ForceChangeRate Parse(string str, IFormatProvider formatProvider = "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => ForceChangeRate.FromNewtonsPerSecond(x.NewtonsPerSecond + y.NewtonsPerSecond)); } /// @@ -584,7 +678,7 @@ private static List ParseWithRegex(string regexString, string s converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -609,18 +703,49 @@ private static List ParseWithRegex(string regexString, string s /// /// The value of 'str' cannot be null. /// Error parsing string. - public static ForceChangeRateUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static ForceChangeRateUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static ForceChangeRateUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static ForceChangeRateUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == ForceChangeRateUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized ForceChangeRateUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -643,6 +768,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(ForceChangeRateUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(ForceChangeRateUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -651,9 +797,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(ForceChangeRateUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(ForceChangeRateUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -665,9 +813,20 @@ public string ToString(ForceChangeRateUnit unit, CultureInfo culture = null, int /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(ForceChangeRateUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(ForceChangeRateUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/Frequency.g.cs b/UnitsNet/GeneratedCode/UnitClasses/Frequency.g.cs index 8562a63e78..baf2dfd550 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/Frequency.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/Frequency.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// The number of occurrences of a repeating event per unit time. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class Frequency +#else public partial struct Frequency : IComparable, IComparable +#endif { /// /// Base unit of Frequency. /// private readonly double _hertz; - public Frequency(double hertz) : this() +#if WINDOWS_UWP + public Frequency() : this(0) + { + } +#endif + + public Frequency(double hertz) + { + _hertz = Convert.ToDouble(hertz); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Frequency(long hertz) + { + _hertz = Convert.ToDouble(hertz); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Frequency(decimal hertz) { - _hertz = hertz; + _hertz = Convert.ToDouble(hertz); } #region Properties @@ -191,7 +230,7 @@ public static Frequency FromTerahertz(double terahertz) return new Frequency((terahertz) * 1e12d); } - +#if !WINDOWS_UWP /// /// Get nullable Frequency from nullable CyclesPerHour. /// @@ -203,7 +242,7 @@ public static Frequency FromTerahertz(double terahertz) } else { - return null; + return null; } } @@ -218,7 +257,7 @@ public static Frequency FromTerahertz(double terahertz) } else { - return null; + return null; } } @@ -233,7 +272,7 @@ public static Frequency FromTerahertz(double terahertz) } else { - return null; + return null; } } @@ -248,7 +287,7 @@ public static Frequency FromTerahertz(double terahertz) } else { - return null; + return null; } } @@ -263,7 +302,7 @@ public static Frequency FromTerahertz(double terahertz) } else { - return null; + return null; } } @@ -278,7 +317,7 @@ public static Frequency FromTerahertz(double terahertz) } else { - return null; + return null; } } @@ -293,7 +332,7 @@ public static Frequency FromTerahertz(double terahertz) } else { - return null; + return null; } } @@ -308,43 +347,45 @@ public static Frequency FromTerahertz(double terahertz) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// Frequency unit value. - public static Frequency From(double value, FrequencyUnit fromUnit) + public static Frequency From(double val, FrequencyUnit fromUnit) { switch (fromUnit) { case FrequencyUnit.CyclePerHour: - return FromCyclesPerHour(value); + return FromCyclesPerHour(val); case FrequencyUnit.CyclePerMinute: - return FromCyclesPerMinute(value); + return FromCyclesPerMinute(val); case FrequencyUnit.Gigahertz: - return FromGigahertz(value); + return FromGigahertz(val); case FrequencyUnit.Hertz: - return FromHertz(value); + return FromHertz(val); case FrequencyUnit.Kilohertz: - return FromKilohertz(value); + return FromKilohertz(val); case FrequencyUnit.Megahertz: - return FromMegahertz(value); + return FromMegahertz(val); case FrequencyUnit.RadianPerSecond: - return FromRadiansPerSecond(value); + return FromRadiansPerSecond(val); case FrequencyUnit.Terahertz: - return FromTerahertz(value); + return FromTerahertz(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -380,6 +421,18 @@ public static Frequency From(double value, FrequencyUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(FrequencyUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -388,7 +441,7 @@ public static Frequency From(double value, FrequencyUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(FrequencyUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(FrequencyUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -397,6 +450,7 @@ public static string GetAbbreviation(FrequencyUnit unit, CultureInfo culture = n #region Arithmetic Operators +#if !WINDOWS_UWP public static Frequency operator -(Frequency right) { return new Frequency(-right._hertz); @@ -431,6 +485,7 @@ public static string GetAbbreviation(FrequencyUnit unit, CultureInfo culture = n { return Convert.ToDouble(left._hertz/right._hertz); } +#endif #endregion @@ -443,11 +498,17 @@ public int CompareTo(object obj) return CompareTo((Frequency) obj); } - public int CompareTo(Frequency other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(Frequency other) { return _hertz.CompareTo(other._hertz); } +#if !WINDOWS_UWP public static bool operator <=(Frequency left, Frequency right) { return left._hertz <= right._hertz; @@ -479,6 +540,7 @@ public int CompareTo(Frequency other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._hertz != right._hertz; } +#endif public override bool Equals(object obj) { @@ -538,7 +600,6 @@ public double As(FrequencyUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -557,10 +618,43 @@ public double As(FrequencyUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static Frequency Parse(string str, IFormatProvider formatProvider = null) + public static Frequency Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static Frequency Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -584,7 +678,7 @@ public static Frequency Parse(string str, IFormatProvider formatProvider = null) "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => Frequency.FromHertz(x.Hertz + y.Hertz)); } /// @@ -621,7 +715,7 @@ private static List ParseWithRegex(string regexString, string str, IF converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -646,18 +740,49 @@ private static List ParseWithRegex(string regexString, string str, IF /// /// The value of 'str' cannot be null. /// Error parsing string. - public static FrequencyUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static FrequencyUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static FrequencyUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static FrequencyUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == FrequencyUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized FrequencyUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -680,6 +805,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(FrequencyUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(FrequencyUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -688,9 +834,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(FrequencyUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(FrequencyUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -702,9 +850,20 @@ public string ToString(FrequencyUnit unit, CultureInfo culture = null, int signi /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(FrequencyUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(FrequencyUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/Information.g.cs b/UnitsNet/GeneratedCode/UnitClasses/Information.g.cs index 8526a589f9..404c16af1c 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/Information.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/Information.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// In computing and telecommunications, a unit of information is the capacity of some standard data storage system or communication channel, used to measure the capacities of other systems and channels. In information theory, units of information are also used to measure the information contents or entropy of random variables. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class Information +#else public partial struct Information : IComparable, IComparable +#endif { /// /// Base unit of Information. /// private readonly decimal _bits; - public Information(decimal bits) : this() +#if WINDOWS_UWP + public Information() : this(0) + { + } +#endif + + public Information(double bits) + { + _bits = Convert.ToDecimal(bits); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Information(long bits) { - _bits = bits; + _bits = Convert.ToDecimal(bits); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Information(decimal bits) + { + _bits = Convert.ToDecimal(bits); } #region Properties @@ -479,7 +518,7 @@ public static Information FromTerabytes(double terabytes) return new Information(Convert.ToDecimal((terabytes*8d) * 1e12d)); } - +#if !WINDOWS_UWP /// /// Get nullable Information from nullable Bits. /// @@ -491,7 +530,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -506,7 +545,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -521,7 +560,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -536,7 +575,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -551,7 +590,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -566,7 +605,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -581,7 +620,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -596,7 +635,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -611,7 +650,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -626,7 +665,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -641,7 +680,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -656,7 +695,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -671,7 +710,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -686,7 +725,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -701,7 +740,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -716,7 +755,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -731,7 +770,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -746,7 +785,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -761,7 +800,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -776,7 +815,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -791,7 +830,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -806,7 +845,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -821,7 +860,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -836,7 +875,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -851,7 +890,7 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } @@ -866,79 +905,81 @@ public static Information FromTerabytes(double terabytes) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// Information unit value. - public static Information From(double value, InformationUnit fromUnit) + public static Information From(double val, InformationUnit fromUnit) { switch (fromUnit) { case InformationUnit.Bit: - return FromBits(value); + return FromBits(val); case InformationUnit.Byte: - return FromBytes(value); + return FromBytes(val); case InformationUnit.Exabit: - return FromExabits(value); + return FromExabits(val); case InformationUnit.Exabyte: - return FromExabytes(value); + return FromExabytes(val); case InformationUnit.Exbibit: - return FromExbibits(value); + return FromExbibits(val); case InformationUnit.Exbibyte: - return FromExbibytes(value); + return FromExbibytes(val); case InformationUnit.Gibibit: - return FromGibibits(value); + return FromGibibits(val); case InformationUnit.Gibibyte: - return FromGibibytes(value); + return FromGibibytes(val); case InformationUnit.Gigabit: - return FromGigabits(value); + return FromGigabits(val); case InformationUnit.Gigabyte: - return FromGigabytes(value); + return FromGigabytes(val); case InformationUnit.Kibibit: - return FromKibibits(value); + return FromKibibits(val); case InformationUnit.Kibibyte: - return FromKibibytes(value); + return FromKibibytes(val); case InformationUnit.Kilobit: - return FromKilobits(value); + return FromKilobits(val); case InformationUnit.Kilobyte: - return FromKilobytes(value); + return FromKilobytes(val); case InformationUnit.Mebibit: - return FromMebibits(value); + return FromMebibits(val); case InformationUnit.Mebibyte: - return FromMebibytes(value); + return FromMebibytes(val); case InformationUnit.Megabit: - return FromMegabits(value); + return FromMegabits(val); case InformationUnit.Megabyte: - return FromMegabytes(value); + return FromMegabytes(val); case InformationUnit.Pebibit: - return FromPebibits(value); + return FromPebibits(val); case InformationUnit.Pebibyte: - return FromPebibytes(value); + return FromPebibytes(val); case InformationUnit.Petabit: - return FromPetabits(value); + return FromPetabits(val); case InformationUnit.Petabyte: - return FromPetabytes(value); + return FromPetabytes(val); case InformationUnit.Tebibit: - return FromTebibits(value); + return FromTebibits(val); case InformationUnit.Tebibyte: - return FromTebibytes(value); + return FromTebibytes(val); case InformationUnit.Terabit: - return FromTerabits(value); + return FromTerabits(val); case InformationUnit.Terabyte: - return FromTerabytes(value); + return FromTerabytes(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -1010,6 +1051,18 @@ public static Information From(double value, InformationUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(InformationUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -1018,7 +1071,7 @@ public static Information From(double value, InformationUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(InformationUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(InformationUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -1027,6 +1080,7 @@ public static string GetAbbreviation(InformationUnit unit, CultureInfo culture = #region Arithmetic Operators +#if !WINDOWS_UWP public static Information operator -(Information right) { return new Information(-right._bits); @@ -1061,6 +1115,7 @@ public static string GetAbbreviation(InformationUnit unit, CultureInfo culture = { return Convert.ToDouble(left._bits/right._bits); } +#endif #endregion @@ -1073,11 +1128,17 @@ public int CompareTo(object obj) return CompareTo((Information) obj); } - public int CompareTo(Information other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(Information other) { return _bits.CompareTo(other._bits); } +#if !WINDOWS_UWP public static bool operator <=(Information left, Information right) { return left._bits <= right._bits; @@ -1109,6 +1170,7 @@ public int CompareTo(Information other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._bits != right._bits; } +#endif public override bool Equals(object obj) { @@ -1204,7 +1266,6 @@ public double As(InformationUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -1223,10 +1284,43 @@ public double As(InformationUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static Information Parse(string str, IFormatProvider formatProvider = null) + public static Information Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static Information Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -1250,7 +1344,7 @@ public static Information Parse(string str, IFormatProvider formatProvider = nul "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => Information.FromBits(x.Bits + y.Bits)); } /// @@ -1287,7 +1381,7 @@ private static List ParseWithRegex(string regexString, string str, converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -1312,18 +1406,49 @@ private static List ParseWithRegex(string regexString, string str, /// /// The value of 'str' cannot be null. /// Error parsing string. - public static InformationUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static InformationUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static InformationUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static InformationUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == InformationUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized InformationUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -1346,6 +1471,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(InformationUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(InformationUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -1354,9 +1500,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(InformationUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(InformationUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -1368,9 +1516,20 @@ public string ToString(InformationUnit unit, CultureInfo culture = null, int sig /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(InformationUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(InformationUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/KinematicViscosity.g.cs b/UnitsNet/GeneratedCode/UnitClasses/KinematicViscosity.g.cs index b239ee2410..92597ce394 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/KinematicViscosity.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/KinematicViscosity.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// The viscosity of a fluid is a measure of its resistance to gradual deformation by shear stress or tensile stress. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class KinematicViscosity +#else public partial struct KinematicViscosity : IComparable, IComparable +#endif { /// /// Base unit of KinematicViscosity. /// private readonly double _squareMetersPerSecond; - public KinematicViscosity(double squaremeterspersecond) : this() +#if WINDOWS_UWP + public KinematicViscosity() : this(0) + { + } +#endif + + public KinematicViscosity(double squaremeterspersecond) + { + _squareMetersPerSecond = Convert.ToDouble(squaremeterspersecond); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + KinematicViscosity(long squaremeterspersecond) + { + _squareMetersPerSecond = Convert.ToDouble(squaremeterspersecond); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + KinematicViscosity(decimal squaremeterspersecond) { - _squareMetersPerSecond = squaremeterspersecond; + _squareMetersPerSecond = Convert.ToDouble(squaremeterspersecond); } #region Properties @@ -191,7 +230,7 @@ public static KinematicViscosity FromStokes(double stokes) return new KinematicViscosity(stokes/1e4); } - +#if !WINDOWS_UWP /// /// Get nullable KinematicViscosity from nullable Centistokes. /// @@ -203,7 +242,7 @@ public static KinematicViscosity FromStokes(double stokes) } else { - return null; + return null; } } @@ -218,7 +257,7 @@ public static KinematicViscosity FromStokes(double stokes) } else { - return null; + return null; } } @@ -233,7 +272,7 @@ public static KinematicViscosity FromStokes(double stokes) } else { - return null; + return null; } } @@ -248,7 +287,7 @@ public static KinematicViscosity FromStokes(double stokes) } else { - return null; + return null; } } @@ -263,7 +302,7 @@ public static KinematicViscosity FromStokes(double stokes) } else { - return null; + return null; } } @@ -278,7 +317,7 @@ public static KinematicViscosity FromStokes(double stokes) } else { - return null; + return null; } } @@ -293,7 +332,7 @@ public static KinematicViscosity FromStokes(double stokes) } else { - return null; + return null; } } @@ -308,43 +347,45 @@ public static KinematicViscosity FromStokes(double stokes) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// KinematicViscosity unit value. - public static KinematicViscosity From(double value, KinematicViscosityUnit fromUnit) + public static KinematicViscosity From(double val, KinematicViscosityUnit fromUnit) { switch (fromUnit) { case KinematicViscosityUnit.Centistokes: - return FromCentistokes(value); + return FromCentistokes(val); case KinematicViscosityUnit.Decistokes: - return FromDecistokes(value); + return FromDecistokes(val); case KinematicViscosityUnit.Kilostokes: - return FromKilostokes(value); + return FromKilostokes(val); case KinematicViscosityUnit.Microstokes: - return FromMicrostokes(value); + return FromMicrostokes(val); case KinematicViscosityUnit.Millistokes: - return FromMillistokes(value); + return FromMillistokes(val); case KinematicViscosityUnit.Nanostokes: - return FromNanostokes(value); + return FromNanostokes(val); case KinematicViscosityUnit.SquareMeterPerSecond: - return FromSquareMetersPerSecond(value); + return FromSquareMetersPerSecond(val); case KinematicViscosityUnit.Stokes: - return FromStokes(value); + return FromStokes(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -380,6 +421,18 @@ public static KinematicViscosity From(double value, KinematicViscosityUnit fromU throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(KinematicViscosityUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -388,7 +441,7 @@ public static KinematicViscosity From(double value, KinematicViscosityUnit fromU /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(KinematicViscosityUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(KinematicViscosityUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -397,6 +450,7 @@ public static string GetAbbreviation(KinematicViscosityUnit unit, CultureInfo cu #region Arithmetic Operators +#if !WINDOWS_UWP public static KinematicViscosity operator -(KinematicViscosity right) { return new KinematicViscosity(-right._squareMetersPerSecond); @@ -431,6 +485,7 @@ public static string GetAbbreviation(KinematicViscosityUnit unit, CultureInfo cu { return Convert.ToDouble(left._squareMetersPerSecond/right._squareMetersPerSecond); } +#endif #endregion @@ -443,11 +498,17 @@ public int CompareTo(object obj) return CompareTo((KinematicViscosity) obj); } - public int CompareTo(KinematicViscosity other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(KinematicViscosity other) { return _squareMetersPerSecond.CompareTo(other._squareMetersPerSecond); } +#if !WINDOWS_UWP public static bool operator <=(KinematicViscosity left, KinematicViscosity right) { return left._squareMetersPerSecond <= right._squareMetersPerSecond; @@ -479,6 +540,7 @@ public int CompareTo(KinematicViscosity other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._squareMetersPerSecond != right._squareMetersPerSecond; } +#endif public override bool Equals(object obj) { @@ -538,7 +600,6 @@ public double As(KinematicViscosityUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -557,10 +618,43 @@ public double As(KinematicViscosityUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static KinematicViscosity Parse(string str, IFormatProvider formatProvider = null) + public static KinematicViscosity Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static KinematicViscosity Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -584,7 +678,7 @@ public static KinematicViscosity Parse(string str, IFormatProvider formatProvide "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => KinematicViscosity.FromSquareMetersPerSecond(x.SquareMetersPerSecond + y.SquareMetersPerSecond)); } /// @@ -621,7 +715,7 @@ private static List ParseWithRegex(string regexString, strin converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -646,18 +740,49 @@ private static List ParseWithRegex(string regexString, strin /// /// The value of 'str' cannot be null. /// Error parsing string. - public static KinematicViscosityUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static KinematicViscosityUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static KinematicViscosityUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static KinematicViscosityUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == KinematicViscosityUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized KinematicViscosityUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -680,6 +805,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(KinematicViscosityUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(KinematicViscosityUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -688,9 +834,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(KinematicViscosityUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(KinematicViscosityUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -702,9 +850,20 @@ public string ToString(KinematicViscosityUnit unit, CultureInfo culture = null, /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(KinematicViscosityUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(KinematicViscosityUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/Length.g.cs b/UnitsNet/GeneratedCode/UnitClasses/Length.g.cs index 6924be21d9..9d9f04e890 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/Length.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/Length.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// Many different units of length have been used around the world. The main units in modern use are U.S. customary units in the United States and the Metric system elsewhere. British Imperial units are still used for some purposes in the United Kingdom and some other countries. The metric system is sub-divided into SI and non-SI units. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class Length +#else public partial struct Length : IComparable, IComparable +#endif { /// /// Base unit of Length. /// private readonly double _meters; - public Length(double meters) : this() +#if WINDOWS_UWP + public Length() : this(0) + { + } +#endif + + public Length(double meters) + { + _meters = Convert.ToDouble(meters); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Length(long meters) { - _meters = meters; + _meters = Convert.ToDouble(meters); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Length(decimal meters) + { + _meters = Convert.ToDouble(meters); } #region Properties @@ -287,7 +326,7 @@ public static Length FromYards(double yards) return new Length(yards*0.9144); } - +#if !WINDOWS_UWP /// /// Get nullable Length from nullable Centimeters. /// @@ -299,7 +338,7 @@ public static Length FromYards(double yards) } else { - return null; + return null; } } @@ -314,7 +353,7 @@ public static Length FromYards(double yards) } else { - return null; + return null; } } @@ -329,7 +368,7 @@ public static Length FromYards(double yards) } else { - return null; + return null; } } @@ -344,7 +383,7 @@ public static Length FromYards(double yards) } else { - return null; + return null; } } @@ -359,7 +398,7 @@ public static Length FromYards(double yards) } else { - return null; + return null; } } @@ -374,7 +413,7 @@ public static Length FromYards(double yards) } else { - return null; + return null; } } @@ -389,7 +428,7 @@ public static Length FromYards(double yards) } else { - return null; + return null; } } @@ -404,7 +443,7 @@ public static Length FromYards(double yards) } else { - return null; + return null; } } @@ -419,7 +458,7 @@ public static Length FromYards(double yards) } else { - return null; + return null; } } @@ -434,7 +473,7 @@ public static Length FromYards(double yards) } else { - return null; + return null; } } @@ -449,7 +488,7 @@ public static Length FromYards(double yards) } else { - return null; + return null; } } @@ -464,7 +503,7 @@ public static Length FromYards(double yards) } else { - return null; + return null; } } @@ -479,7 +518,7 @@ public static Length FromYards(double yards) } else { - return null; + return null; } } @@ -494,55 +533,57 @@ public static Length FromYards(double yards) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// Length unit value. - public static Length From(double value, LengthUnit fromUnit) + public static Length From(double val, LengthUnit fromUnit) { switch (fromUnit) { case LengthUnit.Centimeter: - return FromCentimeters(value); + return FromCentimeters(val); case LengthUnit.Decimeter: - return FromDecimeters(value); + return FromDecimeters(val); case LengthUnit.Foot: - return FromFeet(value); + return FromFeet(val); case LengthUnit.Inch: - return FromInches(value); + return FromInches(val); case LengthUnit.Kilometer: - return FromKilometers(value); + return FromKilometers(val); case LengthUnit.Meter: - return FromMeters(value); + return FromMeters(val); case LengthUnit.Microinch: - return FromMicroinches(value); + return FromMicroinches(val); case LengthUnit.Micrometer: - return FromMicrometers(value); + return FromMicrometers(val); case LengthUnit.Mil: - return FromMils(value); + return FromMils(val); case LengthUnit.Mile: - return FromMiles(value); + return FromMiles(val); case LengthUnit.Millimeter: - return FromMillimeters(value); + return FromMillimeters(val); case LengthUnit.Nanometer: - return FromNanometers(value); + return FromNanometers(val); case LengthUnit.NauticalMile: - return FromNauticalMiles(value); + return FromNauticalMiles(val); case LengthUnit.Yard: - return FromYards(value); + return FromYards(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -590,6 +631,18 @@ public static Length From(double value, LengthUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(LengthUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -598,7 +651,7 @@ public static Length From(double value, LengthUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(LengthUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(LengthUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -607,6 +660,7 @@ public static string GetAbbreviation(LengthUnit unit, CultureInfo culture = null #region Arithmetic Operators +#if !WINDOWS_UWP public static Length operator -(Length right) { return new Length(-right._meters); @@ -641,6 +695,7 @@ public static string GetAbbreviation(LengthUnit unit, CultureInfo culture = null { return Convert.ToDouble(left._meters/right._meters); } +#endif #endregion @@ -653,11 +708,17 @@ public int CompareTo(object obj) return CompareTo((Length) obj); } - public int CompareTo(Length other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(Length other) { return _meters.CompareTo(other._meters); } +#if !WINDOWS_UWP public static bool operator <=(Length left, Length right) { return left._meters <= right._meters; @@ -689,6 +750,7 @@ public int CompareTo(Length other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._meters != right._meters; } +#endif public override bool Equals(object obj) { @@ -760,7 +822,6 @@ public double As(LengthUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -779,10 +840,43 @@ public double As(LengthUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static Length Parse(string str, IFormatProvider formatProvider = null) + public static Length Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static Length Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -806,7 +900,7 @@ public static Length Parse(string str, IFormatProvider formatProvider = null) "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => Length.FromMeters(x.Meters + y.Meters)); } /// @@ -843,7 +937,7 @@ private static List ParseWithRegex(string regexString, string str, IForm converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -868,18 +962,49 @@ private static List ParseWithRegex(string regexString, string str, IForm /// /// The value of 'str' cannot be null. /// Error parsing string. - public static LengthUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static LengthUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static LengthUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static LengthUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == LengthUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized LengthUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -902,6 +1027,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(LengthUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(LengthUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -910,9 +1056,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(LengthUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(LengthUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -924,9 +1072,20 @@ public string ToString(LengthUnit unit, CultureInfo culture = null, int signific /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(LengthUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(LengthUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/Level.g.cs b/UnitsNet/GeneratedCode/UnitClasses/Level.g.cs index 9512f7989f..83b169e336 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/Level.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/Level.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// Level is the logarithm of the ratio of a quantity Q to a reference value of that quantity, Q0, expressed in dimensionless units. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class Level +#else public partial struct Level : IComparable, IComparable +#endif { /// /// Base unit of Level. /// private readonly double _decibels; - public Level(double decibels) : this() +#if WINDOWS_UWP + public Level() : this(0) + { + } +#endif + + public Level(double decibels) { - _decibels = decibels; + _decibels = Convert.ToDouble(decibels); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Level(long decibels) + { + _decibels = Convert.ToDouble(decibels); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Level(decimal decibels) + { + _decibels = Convert.ToDouble(decibels); } #region Properties @@ -95,7 +134,7 @@ public static Level FromNepers(double nepers) return new Level((1/0.115129254)*nepers); } - +#if !WINDOWS_UWP /// /// Get nullable Level from nullable Decibels. /// @@ -107,7 +146,7 @@ public static Level FromNepers(double nepers) } else { - return null; + return null; } } @@ -122,31 +161,33 @@ public static Level FromNepers(double nepers) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// Level unit value. - public static Level From(double value, LevelUnit fromUnit) + public static Level From(double val, LevelUnit fromUnit) { switch (fromUnit) { case LevelUnit.Decibel: - return FromDecibels(value); + return FromDecibels(val); case LevelUnit.Neper: - return FromNepers(value); + return FromNepers(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -170,6 +211,18 @@ public static Level From(double value, LevelUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(LevelUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -178,7 +231,7 @@ public static Level From(double value, LevelUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(LevelUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(LevelUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -187,6 +240,7 @@ public static string GetAbbreviation(LevelUnit unit, CultureInfo culture = null) #region Logarithmic Arithmetic Operators +#if !WINDOWS_UWP public static Level operator -(Level right) { return new Level(-right._decibels); @@ -229,6 +283,7 @@ public static string GetAbbreviation(LevelUnit unit, CultureInfo culture = null) // Logarithmic division = subtraction return Convert.ToDouble(left._decibels - right._decibels); } +#endif #endregion @@ -241,11 +296,17 @@ public int CompareTo(object obj) return CompareTo((Level) obj); } - public int CompareTo(Level other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(Level other) { return _decibels.CompareTo(other._decibels); } +#if !WINDOWS_UWP public static bool operator <=(Level left, Level right) { return left._decibels <= right._decibels; @@ -277,6 +338,7 @@ public int CompareTo(Level other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._decibels != right._decibels; } +#endif public override bool Equals(object obj) { @@ -324,7 +386,6 @@ public double As(LevelUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -343,10 +404,43 @@ public double As(LevelUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static Level Parse(string str, IFormatProvider formatProvider = null) + public static Level Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static Level Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -370,7 +464,7 @@ public static Level Parse(string str, IFormatProvider formatProvider = null) "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => Level.FromDecibels(x.Decibels + y.Decibels)); } /// @@ -407,7 +501,7 @@ private static List ParseWithRegex(string regexString, string str, IForma converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -432,18 +526,49 @@ private static List ParseWithRegex(string regexString, string str, IForma /// /// The value of 'str' cannot be null. /// Error parsing string. - public static LevelUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static LevelUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static LevelUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static LevelUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == LevelUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized LevelUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -466,6 +591,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(LevelUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(LevelUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -474,9 +620,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(LevelUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(LevelUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -488,9 +636,20 @@ public string ToString(LevelUnit unit, CultureInfo culture = null, int significa /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(LevelUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(LevelUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/Mass.g.cs b/UnitsNet/GeneratedCode/UnitClasses/Mass.g.cs index 1fe3bd8fbf..667d984b65 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/Mass.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/Mass.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// In physics, mass (from Greek μᾶζα "barley cake, lump [of dough]") is a property of a physical system or body, giving rise to the phenomena of the body's resistance to being accelerated by a force and the strength of its mutual gravitational attraction with other bodies. Instruments such as mass balances or scales use those phenomena to measure mass. The SI unit of mass is the kilogram (kg). /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class Mass +#else public partial struct Mass : IComparable, IComparable +#endif { /// /// Base unit of Mass. /// private readonly double _kilograms; - public Mass(double kilograms) : this() +#if WINDOWS_UWP + public Mass() : this(0) + { + } +#endif + + public Mass(double kilograms) + { + _kilograms = Convert.ToDouble(kilograms); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Mass(long kilograms) { - _kilograms = kilograms; + _kilograms = Convert.ToDouble(kilograms); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Mass(decimal kilograms) + { + _kilograms = Convert.ToDouble(kilograms); } #region Properties @@ -335,7 +374,7 @@ public static Mass FromTonnes(double tonnes) return new Mass(tonnes*1e3); } - +#if !WINDOWS_UWP /// /// Get nullable Mass from nullable Centigrams. /// @@ -347,7 +386,7 @@ public static Mass FromTonnes(double tonnes) } else { - return null; + return null; } } @@ -362,7 +401,7 @@ public static Mass FromTonnes(double tonnes) } else { - return null; + return null; } } @@ -377,7 +416,7 @@ public static Mass FromTonnes(double tonnes) } else { - return null; + return null; } } @@ -392,7 +431,7 @@ public static Mass FromTonnes(double tonnes) } else { - return null; + return null; } } @@ -407,7 +446,7 @@ public static Mass FromTonnes(double tonnes) } else { - return null; + return null; } } @@ -422,7 +461,7 @@ public static Mass FromTonnes(double tonnes) } else { - return null; + return null; } } @@ -437,7 +476,7 @@ public static Mass FromTonnes(double tonnes) } else { - return null; + return null; } } @@ -452,7 +491,7 @@ public static Mass FromTonnes(double tonnes) } else { - return null; + return null; } } @@ -467,7 +506,7 @@ public static Mass FromTonnes(double tonnes) } else { - return null; + return null; } } @@ -482,7 +521,7 @@ public static Mass FromTonnes(double tonnes) } else { - return null; + return null; } } @@ -497,7 +536,7 @@ public static Mass FromTonnes(double tonnes) } else { - return null; + return null; } } @@ -512,7 +551,7 @@ public static Mass FromTonnes(double tonnes) } else { - return null; + return null; } } @@ -527,7 +566,7 @@ public static Mass FromTonnes(double tonnes) } else { - return null; + return null; } } @@ -542,7 +581,7 @@ public static Mass FromTonnes(double tonnes) } else { - return null; + return null; } } @@ -557,7 +596,7 @@ public static Mass FromTonnes(double tonnes) } else { - return null; + return null; } } @@ -572,7 +611,7 @@ public static Mass FromTonnes(double tonnes) } else { - return null; + return null; } } @@ -587,61 +626,63 @@ public static Mass FromTonnes(double tonnes) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// Mass unit value. - public static Mass From(double value, MassUnit fromUnit) + public static Mass From(double val, MassUnit fromUnit) { switch (fromUnit) { case MassUnit.Centigram: - return FromCentigrams(value); + return FromCentigrams(val); case MassUnit.Decagram: - return FromDecagrams(value); + return FromDecagrams(val); case MassUnit.Decigram: - return FromDecigrams(value); + return FromDecigrams(val); case MassUnit.Gram: - return FromGrams(value); + return FromGrams(val); case MassUnit.Hectogram: - return FromHectograms(value); + return FromHectograms(val); case MassUnit.Kilogram: - return FromKilograms(value); + return FromKilograms(val); case MassUnit.Kilotonne: - return FromKilotonnes(value); + return FromKilotonnes(val); case MassUnit.LongTon: - return FromLongTons(value); + return FromLongTons(val); case MassUnit.Megatonne: - return FromMegatonnes(value); + return FromMegatonnes(val); case MassUnit.Microgram: - return FromMicrograms(value); + return FromMicrograms(val); case MassUnit.Milligram: - return FromMilligrams(value); + return FromMilligrams(val); case MassUnit.Nanogram: - return FromNanograms(value); + return FromNanograms(val); case MassUnit.Ounce: - return FromOunces(value); + return FromOunces(val); case MassUnit.Pound: - return FromPounds(value); + return FromPounds(val); case MassUnit.ShortTon: - return FromShortTons(value); + return FromShortTons(val); case MassUnit.Stone: - return FromStone(value); + return FromStone(val); case MassUnit.Tonne: - return FromTonnes(value); + return FromTonnes(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -695,6 +736,18 @@ public static Mass From(double value, MassUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(MassUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -703,7 +756,7 @@ public static Mass From(double value, MassUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(MassUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(MassUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -712,6 +765,7 @@ public static string GetAbbreviation(MassUnit unit, CultureInfo culture = null) #region Arithmetic Operators +#if !WINDOWS_UWP public static Mass operator -(Mass right) { return new Mass(-right._kilograms); @@ -746,6 +800,7 @@ public static string GetAbbreviation(MassUnit unit, CultureInfo culture = null) { return Convert.ToDouble(left._kilograms/right._kilograms); } +#endif #endregion @@ -758,11 +813,17 @@ public int CompareTo(object obj) return CompareTo((Mass) obj); } - public int CompareTo(Mass other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(Mass other) { return _kilograms.CompareTo(other._kilograms); } +#if !WINDOWS_UWP public static bool operator <=(Mass left, Mass right) { return left._kilograms <= right._kilograms; @@ -794,6 +855,7 @@ public int CompareTo(Mass other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._kilograms != right._kilograms; } +#endif public override bool Equals(object obj) { @@ -871,7 +933,6 @@ public double As(MassUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -890,10 +951,43 @@ public double As(MassUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static Mass Parse(string str, IFormatProvider formatProvider = null) + public static Mass Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static Mass Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -917,7 +1011,7 @@ public static Mass Parse(string str, IFormatProvider formatProvider = null) "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => Mass.FromKilograms(x.Kilograms + y.Kilograms)); } /// @@ -954,7 +1048,7 @@ private static List ParseWithRegex(string regexString, string str, IFormat converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -979,18 +1073,49 @@ private static List ParseWithRegex(string regexString, string str, IFormat /// /// The value of 'str' cannot be null. /// Error parsing string. - public static MassUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static MassUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static MassUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static MassUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == MassUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized MassUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -1013,6 +1138,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(MassUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(MassUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -1021,9 +1167,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(MassUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(MassUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -1035,9 +1183,20 @@ public string ToString(MassUnit unit, CultureInfo culture = null, int significan /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(MassUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(MassUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/MassFlow.g.cs b/UnitsNet/GeneratedCode/UnitClasses/MassFlow.g.cs index 123fe3b9fe..85a7d836e3 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/MassFlow.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/MassFlow.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// Mass flow is the ratio of the mass change to the time during which the change occurred (value of mass changes per unit time). /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class MassFlow +#else public partial struct MassFlow : IComparable, IComparable +#endif { /// /// Base unit of MassFlow. /// private readonly double _gramsPerSecond; - public MassFlow(double gramspersecond) : this() +#if WINDOWS_UWP + public MassFlow() : this(0) + { + } +#endif + + public MassFlow(double gramspersecond) + { + _gramsPerSecond = Convert.ToDouble(gramspersecond); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + MassFlow(long gramspersecond) + { + _gramsPerSecond = Convert.ToDouble(gramspersecond); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + MassFlow(decimal gramspersecond) { - _gramsPerSecond = gramspersecond; + _gramsPerSecond = Convert.ToDouble(gramspersecond); } #region Properties @@ -223,7 +262,7 @@ public static MassFlow FromTonnesPerDay(double tonnesperday) return new MassFlow(tonnesperday/0.0864000); } - +#if !WINDOWS_UWP /// /// Get nullable MassFlow from nullable CentigramsPerSecond. /// @@ -235,7 +274,7 @@ public static MassFlow FromTonnesPerDay(double tonnesperday) } else { - return null; + return null; } } @@ -250,7 +289,7 @@ public static MassFlow FromTonnesPerDay(double tonnesperday) } else { - return null; + return null; } } @@ -265,7 +304,7 @@ public static MassFlow FromTonnesPerDay(double tonnesperday) } else { - return null; + return null; } } @@ -280,7 +319,7 @@ public static MassFlow FromTonnesPerDay(double tonnesperday) } else { - return null; + return null; } } @@ -295,7 +334,7 @@ public static MassFlow FromTonnesPerDay(double tonnesperday) } else { - return null; + return null; } } @@ -310,7 +349,7 @@ public static MassFlow FromTonnesPerDay(double tonnesperday) } else { - return null; + return null; } } @@ -325,7 +364,7 @@ public static MassFlow FromTonnesPerDay(double tonnesperday) } else { - return null; + return null; } } @@ -340,7 +379,7 @@ public static MassFlow FromTonnesPerDay(double tonnesperday) } else { - return null; + return null; } } @@ -355,7 +394,7 @@ public static MassFlow FromTonnesPerDay(double tonnesperday) } else { - return null; + return null; } } @@ -370,47 +409,49 @@ public static MassFlow FromTonnesPerDay(double tonnesperday) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// MassFlow unit value. - public static MassFlow From(double value, MassFlowUnit fromUnit) + public static MassFlow From(double val, MassFlowUnit fromUnit) { switch (fromUnit) { case MassFlowUnit.CentigramPerSecond: - return FromCentigramsPerSecond(value); + return FromCentigramsPerSecond(val); case MassFlowUnit.DecagramPerSecond: - return FromDecagramsPerSecond(value); + return FromDecagramsPerSecond(val); case MassFlowUnit.DecigramPerSecond: - return FromDecigramsPerSecond(value); + return FromDecigramsPerSecond(val); case MassFlowUnit.GramPerSecond: - return FromGramsPerSecond(value); + return FromGramsPerSecond(val); case MassFlowUnit.HectogramPerSecond: - return FromHectogramsPerSecond(value); + return FromHectogramsPerSecond(val); case MassFlowUnit.KilogramPerSecond: - return FromKilogramsPerSecond(value); + return FromKilogramsPerSecond(val); case MassFlowUnit.MicrogramPerSecond: - return FromMicrogramsPerSecond(value); + return FromMicrogramsPerSecond(val); case MassFlowUnit.MilligramPerSecond: - return FromMilligramsPerSecond(value); + return FromMilligramsPerSecond(val); case MassFlowUnit.NanogramPerSecond: - return FromNanogramsPerSecond(value); + return FromNanogramsPerSecond(val); case MassFlowUnit.TonnePerDay: - return FromTonnesPerDay(value); + return FromTonnesPerDay(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -450,6 +491,18 @@ public static MassFlow From(double value, MassFlowUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(MassFlowUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -458,7 +511,7 @@ public static MassFlow From(double value, MassFlowUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(MassFlowUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(MassFlowUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -467,6 +520,7 @@ public static string GetAbbreviation(MassFlowUnit unit, CultureInfo culture = nu #region Arithmetic Operators +#if !WINDOWS_UWP public static MassFlow operator -(MassFlow right) { return new MassFlow(-right._gramsPerSecond); @@ -501,6 +555,7 @@ public static string GetAbbreviation(MassFlowUnit unit, CultureInfo culture = nu { return Convert.ToDouble(left._gramsPerSecond/right._gramsPerSecond); } +#endif #endregion @@ -513,11 +568,17 @@ public int CompareTo(object obj) return CompareTo((MassFlow) obj); } - public int CompareTo(MassFlow other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(MassFlow other) { return _gramsPerSecond.CompareTo(other._gramsPerSecond); } +#if !WINDOWS_UWP public static bool operator <=(MassFlow left, MassFlow right) { return left._gramsPerSecond <= right._gramsPerSecond; @@ -549,6 +610,7 @@ public int CompareTo(MassFlow other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._gramsPerSecond != right._gramsPerSecond; } +#endif public override bool Equals(object obj) { @@ -612,7 +674,6 @@ public double As(MassFlowUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -631,10 +692,43 @@ public double As(MassFlowUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static MassFlow Parse(string str, IFormatProvider formatProvider = null) + public static MassFlow Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static MassFlow Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -658,7 +752,7 @@ public static MassFlow Parse(string str, IFormatProvider formatProvider = null) "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => MassFlow.FromGramsPerSecond(x.GramsPerSecond + y.GramsPerSecond)); } /// @@ -695,7 +789,7 @@ private static List ParseWithRegex(string regexString, string str, IFo converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -720,18 +814,49 @@ private static List ParseWithRegex(string regexString, string str, IFo /// /// The value of 'str' cannot be null. /// Error parsing string. - public static MassFlowUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static MassFlowUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static MassFlowUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static MassFlowUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == MassFlowUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized MassFlowUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -754,6 +879,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(MassFlowUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(MassFlowUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -762,9 +908,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(MassFlowUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(MassFlowUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -776,9 +924,20 @@ public string ToString(MassFlowUnit unit, CultureInfo culture = null, int signif /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(MassFlowUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(MassFlowUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/Power.g.cs b/UnitsNet/GeneratedCode/UnitClasses/Power.g.cs index e7206d6de6..624657476a 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/Power.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/Power.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// In physics, power is the rate of doing work. It is equivalent to an amount of energy consumed per unit time. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class Power +#else public partial struct Power : IComparable, IComparable +#endif { /// /// Base unit of Power. /// private readonly decimal _watts; - public Power(decimal watts) : this() +#if WINDOWS_UWP + public Power() : this(0) + { + } +#endif + + public Power(double watts) + { + _watts = Convert.ToDecimal(watts); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Power(long watts) { - _watts = watts; + _watts = Convert.ToDecimal(watts); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Power(decimal watts) + { + _watts = Convert.ToDecimal(watts); } #region Properties @@ -319,7 +358,7 @@ public static Power FromWatts(double watts) return new Power(Convert.ToDecimal(watts)); } - +#if !WINDOWS_UWP /// /// Get nullable Power from nullable BoilerHorsepower. /// @@ -331,7 +370,7 @@ public static Power FromWatts(double watts) } else { - return null; + return null; } } @@ -346,7 +385,7 @@ public static Power FromWatts(double watts) } else { - return null; + return null; } } @@ -361,7 +400,7 @@ public static Power FromWatts(double watts) } else { - return null; + return null; } } @@ -376,7 +415,7 @@ public static Power FromWatts(double watts) } else { - return null; + return null; } } @@ -391,7 +430,7 @@ public static Power FromWatts(double watts) } else { - return null; + return null; } } @@ -406,7 +445,7 @@ public static Power FromWatts(double watts) } else { - return null; + return null; } } @@ -421,7 +460,7 @@ public static Power FromWatts(double watts) } else { - return null; + return null; } } @@ -436,7 +475,7 @@ public static Power FromWatts(double watts) } else { - return null; + return null; } } @@ -451,7 +490,7 @@ public static Power FromWatts(double watts) } else { - return null; + return null; } } @@ -466,7 +505,7 @@ public static Power FromWatts(double watts) } else { - return null; + return null; } } @@ -481,7 +520,7 @@ public static Power FromWatts(double watts) } else { - return null; + return null; } } @@ -496,7 +535,7 @@ public static Power FromWatts(double watts) } else { - return null; + return null; } } @@ -511,7 +550,7 @@ public static Power FromWatts(double watts) } else { - return null; + return null; } } @@ -526,7 +565,7 @@ public static Power FromWatts(double watts) } else { - return null; + return null; } } @@ -541,7 +580,7 @@ public static Power FromWatts(double watts) } else { - return null; + return null; } } @@ -556,59 +595,61 @@ public static Power FromWatts(double watts) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// Power unit value. - public static Power From(double value, PowerUnit fromUnit) + public static Power From(double val, PowerUnit fromUnit) { switch (fromUnit) { case PowerUnit.BoilerHorsepower: - return FromBoilerHorsepower(value); + return FromBoilerHorsepower(val); case PowerUnit.ElectricalHorsepower: - return FromElectricalHorsepower(value); + return FromElectricalHorsepower(val); case PowerUnit.Femtowatt: - return FromFemtowatts(value); + return FromFemtowatts(val); case PowerUnit.Gigawatt: - return FromGigawatts(value); + return FromGigawatts(val); case PowerUnit.HydraulicHorsepower: - return FromHydraulicHorsepower(value); + return FromHydraulicHorsepower(val); case PowerUnit.Kilowatt: - return FromKilowatts(value); + return FromKilowatts(val); case PowerUnit.MechanicalHorsepower: - return FromMechanicalHorsepower(value); + return FromMechanicalHorsepower(val); case PowerUnit.Megawatt: - return FromMegawatts(value); + return FromMegawatts(val); case PowerUnit.MetricHorsepower: - return FromMetricHorsepower(value); + return FromMetricHorsepower(val); case PowerUnit.Microwatt: - return FromMicrowatts(value); + return FromMicrowatts(val); case PowerUnit.Milliwatt: - return FromMilliwatts(value); + return FromMilliwatts(val); case PowerUnit.Nanowatt: - return FromNanowatts(value); + return FromNanowatts(val); case PowerUnit.Petawatt: - return FromPetawatts(value); + return FromPetawatts(val); case PowerUnit.Picowatt: - return FromPicowatts(value); + return FromPicowatts(val); case PowerUnit.Terawatt: - return FromTerawatts(value); + return FromTerawatts(val); case PowerUnit.Watt: - return FromWatts(value); + return FromWatts(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -660,6 +701,18 @@ public static Power From(double value, PowerUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(PowerUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -668,7 +721,7 @@ public static Power From(double value, PowerUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(PowerUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(PowerUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -677,6 +730,7 @@ public static string GetAbbreviation(PowerUnit unit, CultureInfo culture = null) #region Arithmetic Operators +#if !WINDOWS_UWP public static Power operator -(Power right) { return new Power(-right._watts); @@ -711,6 +765,7 @@ public static string GetAbbreviation(PowerUnit unit, CultureInfo culture = null) { return Convert.ToDouble(left._watts/right._watts); } +#endif #endregion @@ -723,11 +778,17 @@ public int CompareTo(object obj) return CompareTo((Power) obj); } - public int CompareTo(Power other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(Power other) { return _watts.CompareTo(other._watts); } +#if !WINDOWS_UWP public static bool operator <=(Power left, Power right) { return left._watts <= right._watts; @@ -759,6 +820,7 @@ public int CompareTo(Power other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._watts != right._watts; } +#endif public override bool Equals(object obj) { @@ -834,7 +896,6 @@ public double As(PowerUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -853,10 +914,43 @@ public double As(PowerUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static Power Parse(string str, IFormatProvider formatProvider = null) + public static Power Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static Power Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -880,7 +974,7 @@ public static Power Parse(string str, IFormatProvider formatProvider = null) "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => Power.FromWatts(x.Watts + y.Watts)); } /// @@ -917,7 +1011,7 @@ private static List ParseWithRegex(string regexString, string str, IForma converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -942,18 +1036,49 @@ private static List ParseWithRegex(string regexString, string str, IForma /// /// The value of 'str' cannot be null. /// Error parsing string. - public static PowerUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static PowerUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static PowerUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static PowerUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == PowerUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized PowerUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -976,6 +1101,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(PowerUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(PowerUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -984,9 +1130,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(PowerUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(PowerUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -998,9 +1146,20 @@ public string ToString(PowerUnit unit, CultureInfo culture = null, int significa /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(PowerUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(PowerUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/PowerRatio.g.cs b/UnitsNet/GeneratedCode/UnitClasses/PowerRatio.g.cs index 0f654ae136..c54d984bc6 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/PowerRatio.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/PowerRatio.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// The strength of a signal expressed in decibels (dB) relative to one watt. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class PowerRatio +#else public partial struct PowerRatio : IComparable, IComparable +#endif { /// /// Base unit of PowerRatio. /// private readonly double _decibelWatts; - public PowerRatio(double decibelwatts) : this() +#if WINDOWS_UWP + public PowerRatio() : this(0) + { + } +#endif + + public PowerRatio(double decibelwatts) { - _decibelWatts = decibelwatts; + _decibelWatts = Convert.ToDouble(decibelwatts); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + PowerRatio(long decibelwatts) + { + _decibelWatts = Convert.ToDouble(decibelwatts); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + PowerRatio(decimal decibelwatts) + { + _decibelWatts = Convert.ToDouble(decibelwatts); } #region Properties @@ -95,7 +134,7 @@ public static PowerRatio FromDecibelWatts(double decibelwatts) return new PowerRatio(decibelwatts); } - +#if !WINDOWS_UWP /// /// Get nullable PowerRatio from nullable DecibelMilliwatts. /// @@ -107,7 +146,7 @@ public static PowerRatio FromDecibelWatts(double decibelwatts) } else { - return null; + return null; } } @@ -122,31 +161,33 @@ public static PowerRatio FromDecibelWatts(double decibelwatts) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// PowerRatio unit value. - public static PowerRatio From(double value, PowerRatioUnit fromUnit) + public static PowerRatio From(double val, PowerRatioUnit fromUnit) { switch (fromUnit) { case PowerRatioUnit.DecibelMilliwatt: - return FromDecibelMilliwatts(value); + return FromDecibelMilliwatts(val); case PowerRatioUnit.DecibelWatt: - return FromDecibelWatts(value); + return FromDecibelWatts(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -170,6 +211,18 @@ public static PowerRatio From(double value, PowerRatioUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(PowerRatioUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -178,7 +231,7 @@ public static PowerRatio From(double value, PowerRatioUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(PowerRatioUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(PowerRatioUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -187,6 +240,7 @@ public static string GetAbbreviation(PowerRatioUnit unit, CultureInfo culture = #region Logarithmic Arithmetic Operators +#if !WINDOWS_UWP public static PowerRatio operator -(PowerRatio right) { return new PowerRatio(-right._decibelWatts); @@ -229,6 +283,7 @@ public static string GetAbbreviation(PowerRatioUnit unit, CultureInfo culture = // Logarithmic division = subtraction return Convert.ToDouble(left._decibelWatts - right._decibelWatts); } +#endif #endregion @@ -241,11 +296,17 @@ public int CompareTo(object obj) return CompareTo((PowerRatio) obj); } - public int CompareTo(PowerRatio other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(PowerRatio other) { return _decibelWatts.CompareTo(other._decibelWatts); } +#if !WINDOWS_UWP public static bool operator <=(PowerRatio left, PowerRatio right) { return left._decibelWatts <= right._decibelWatts; @@ -277,6 +338,7 @@ public int CompareTo(PowerRatio other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._decibelWatts != right._decibelWatts; } +#endif public override bool Equals(object obj) { @@ -324,7 +386,6 @@ public double As(PowerRatioUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -343,10 +404,43 @@ public double As(PowerRatioUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static PowerRatio Parse(string str, IFormatProvider formatProvider = null) + public static PowerRatio Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static PowerRatio Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -370,7 +464,7 @@ public static PowerRatio Parse(string str, IFormatProvider formatProvider = null "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => PowerRatio.FromDecibelWatts(x.DecibelWatts + y.DecibelWatts)); } /// @@ -407,7 +501,7 @@ private static List ParseWithRegex(string regexString, string str, I converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -432,18 +526,49 @@ private static List ParseWithRegex(string regexString, string str, I /// /// The value of 'str' cannot be null. /// Error parsing string. - public static PowerRatioUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static PowerRatioUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static PowerRatioUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static PowerRatioUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == PowerRatioUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized PowerRatioUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -466,6 +591,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(PowerRatioUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(PowerRatioUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -474,9 +620,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(PowerRatioUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(PowerRatioUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -488,9 +636,20 @@ public string ToString(PowerRatioUnit unit, CultureInfo culture = null, int sign /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(PowerRatioUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(PowerRatioUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/Pressure.g.cs b/UnitsNet/GeneratedCode/UnitClasses/Pressure.g.cs index 7efef877f9..e3c61c0ac7 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/Pressure.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/Pressure.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// Pressure (symbol: P or p) is the ratio of force to the area over which that force is distributed. Pressure is force per unit area applied in a direction perpendicular to the surface of an object. Gauge pressure (also spelled gage pressure)[a] is the pressure relative to the local atmospheric or ambient pressure. Pressure is measured in any unit of force divided by any unit of area. The SI unit of pressure is the newton per square metre, which is called the pascal (Pa) after the seventeenth-century philosopher and scientist Blaise Pascal. A pressure of 1 Pa is small; it approximately equals the pressure exerted by a dollar bill resting flat on a table. Everyday pressures are often stated in kilopascals (1 kPa = 1000 Pa). /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class Pressure +#else public partial struct Pressure : IComparable, IComparable +#endif { /// /// Base unit of Pressure. /// private readonly double _pascals; - public Pressure(double pascals) : this() +#if WINDOWS_UWP + public Pressure() : this(0) + { + } +#endif + + public Pressure(double pascals) { - _pascals = pascals; + _pascals = Convert.ToDouble(pascals); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Pressure(long pascals) + { + _pascals = Convert.ToDouble(pascals); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Pressure(decimal pascals) + { + _pascals = Convert.ToDouble(pascals); } #region Properties @@ -591,7 +630,7 @@ public static Pressure FromTorrs(double torrs) return new Pressure(torrs*1.3332266752*1e2); } - +#if !WINDOWS_UWP /// /// Get nullable Pressure from nullable Atmospheres. /// @@ -603,7 +642,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -618,7 +657,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -633,7 +672,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -648,7 +687,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -663,7 +702,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -678,7 +717,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -693,7 +732,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -708,7 +747,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -723,7 +762,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -738,7 +777,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -753,7 +792,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -768,7 +807,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -783,7 +822,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -798,7 +837,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -813,7 +852,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -828,7 +867,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -843,7 +882,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -858,7 +897,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -873,7 +912,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -888,7 +927,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -903,7 +942,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -918,7 +957,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -933,7 +972,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -948,7 +987,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -963,7 +1002,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -978,7 +1017,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -993,7 +1032,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -1008,7 +1047,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -1023,7 +1062,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -1038,7 +1077,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -1053,7 +1092,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -1068,7 +1107,7 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } @@ -1083,93 +1122,95 @@ public static Pressure FromTorrs(double torrs) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// Pressure unit value. - public static Pressure From(double value, PressureUnit fromUnit) + public static Pressure From(double val, PressureUnit fromUnit) { switch (fromUnit) { case PressureUnit.Atmosphere: - return FromAtmospheres(value); + return FromAtmospheres(val); case PressureUnit.Bar: - return FromBars(value); + return FromBars(val); case PressureUnit.Centibar: - return FromCentibars(value); + return FromCentibars(val); case PressureUnit.Decapascal: - return FromDecapascals(value); + return FromDecapascals(val); case PressureUnit.Decibar: - return FromDecibars(value); + return FromDecibars(val); case PressureUnit.Gigapascal: - return FromGigapascals(value); + return FromGigapascals(val); case PressureUnit.Hectopascal: - return FromHectopascals(value); + return FromHectopascals(val); case PressureUnit.Kilobar: - return FromKilobars(value); + return FromKilobars(val); case PressureUnit.KilogramForcePerSquareCentimeter: - return FromKilogramsForcePerSquareCentimeter(value); + return FromKilogramsForcePerSquareCentimeter(val); case PressureUnit.KilogramForcePerSquareMeter: - return FromKilogramsForcePerSquareMeter(value); + return FromKilogramsForcePerSquareMeter(val); case PressureUnit.KilogramForcePerSquareMillimeter: - return FromKilogramsForcePerSquareMillimeter(value); + return FromKilogramsForcePerSquareMillimeter(val); case PressureUnit.KilonewtonPerSquareCentimeter: - return FromKilonewtonsPerSquareCentimeter(value); + return FromKilonewtonsPerSquareCentimeter(val); case PressureUnit.KilonewtonPerSquareMeter: - return FromKilonewtonsPerSquareMeter(value); + return FromKilonewtonsPerSquareMeter(val); case PressureUnit.KilonewtonPerSquareMillimeter: - return FromKilonewtonsPerSquareMillimeter(value); + return FromKilonewtonsPerSquareMillimeter(val); case PressureUnit.Kilopascal: - return FromKilopascals(value); + return FromKilopascals(val); case PressureUnit.KilopoundForcePerSquareFoot: - return FromKilopoundsForcePerSquareFoot(value); + return FromKilopoundsForcePerSquareFoot(val); case PressureUnit.KilopoundForcePerSquareInch: - return FromKilopoundsForcePerSquareInch(value); + return FromKilopoundsForcePerSquareInch(val); case PressureUnit.Megabar: - return FromMegabars(value); + return FromMegabars(val); case PressureUnit.Megapascal: - return FromMegapascals(value); + return FromMegapascals(val); case PressureUnit.Micropascal: - return FromMicropascals(value); + return FromMicropascals(val); case PressureUnit.Millibar: - return FromMillibars(value); + return FromMillibars(val); case PressureUnit.NewtonPerSquareCentimeter: - return FromNewtonsPerSquareCentimeter(value); + return FromNewtonsPerSquareCentimeter(val); case PressureUnit.NewtonPerSquareMeter: - return FromNewtonsPerSquareMeter(value); + return FromNewtonsPerSquareMeter(val); case PressureUnit.NewtonPerSquareMillimeter: - return FromNewtonsPerSquareMillimeter(value); + return FromNewtonsPerSquareMillimeter(val); case PressureUnit.Pascal: - return FromPascals(value); + return FromPascals(val); case PressureUnit.PoundForcePerSquareFoot: - return FromPoundsForcePerSquareFoot(value); + return FromPoundsForcePerSquareFoot(val); case PressureUnit.PoundForcePerSquareInch: - return FromPoundsForcePerSquareInch(value); + return FromPoundsForcePerSquareInch(val); case PressureUnit.Psi: - return FromPsi(value); + return FromPsi(val); case PressureUnit.TechnicalAtmosphere: - return FromTechnicalAtmospheres(value); + return FromTechnicalAtmospheres(val); case PressureUnit.TonneForcePerSquareCentimeter: - return FromTonnesForcePerSquareCentimeter(value); + return FromTonnesForcePerSquareCentimeter(val); case PressureUnit.TonneForcePerSquareMeter: - return FromTonnesForcePerSquareMeter(value); + return FromTonnesForcePerSquareMeter(val); case PressureUnit.TonneForcePerSquareMillimeter: - return FromTonnesForcePerSquareMillimeter(value); + return FromTonnesForcePerSquareMillimeter(val); case PressureUnit.Torr: - return FromTorrs(value); + return FromTorrs(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -1255,6 +1296,18 @@ public static Pressure From(double value, PressureUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(PressureUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -1263,7 +1316,7 @@ public static Pressure From(double value, PressureUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(PressureUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(PressureUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -1272,6 +1325,7 @@ public static string GetAbbreviation(PressureUnit unit, CultureInfo culture = nu #region Arithmetic Operators +#if !WINDOWS_UWP public static Pressure operator -(Pressure right) { return new Pressure(-right._pascals); @@ -1306,6 +1360,7 @@ public static string GetAbbreviation(PressureUnit unit, CultureInfo culture = nu { return Convert.ToDouble(left._pascals/right._pascals); } +#endif #endregion @@ -1318,11 +1373,17 @@ public int CompareTo(object obj) return CompareTo((Pressure) obj); } - public int CompareTo(Pressure other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(Pressure other) { return _pascals.CompareTo(other._pascals); } +#if !WINDOWS_UWP public static bool operator <=(Pressure left, Pressure right) { return left._pascals <= right._pascals; @@ -1354,6 +1415,7 @@ public int CompareTo(Pressure other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._pascals != right._pascals; } +#endif public override bool Equals(object obj) { @@ -1463,7 +1525,6 @@ public double As(PressureUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -1482,10 +1543,43 @@ public double As(PressureUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static Pressure Parse(string str, IFormatProvider formatProvider = null) + public static Pressure Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static Pressure Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -1509,7 +1603,7 @@ public static Pressure Parse(string str, IFormatProvider formatProvider = null) "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => Pressure.FromPascals(x.Pascals + y.Pascals)); } /// @@ -1546,7 +1640,7 @@ private static List ParseWithRegex(string regexString, string str, IFo converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -1571,18 +1665,49 @@ private static List ParseWithRegex(string regexString, string str, IFo /// /// The value of 'str' cannot be null. /// Error parsing string. - public static PressureUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static PressureUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static PressureUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static PressureUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == PressureUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized PressureUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -1605,6 +1730,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(PressureUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(PressureUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -1613,9 +1759,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(PressureUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(PressureUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -1627,9 +1775,20 @@ public string ToString(PressureUnit unit, CultureInfo culture = null, int signif /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(PressureUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(PressureUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/PressureChangeRate.g.cs b/UnitsNet/GeneratedCode/UnitClasses/PressureChangeRate.g.cs index 57779222af..94a1ebf1e1 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/PressureChangeRate.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/PressureChangeRate.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// Pressure change rate is the ratio of the pressure change to the time during which the change occurred (value of pressure changes per unit time). /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class PressureChangeRate +#else public partial struct PressureChangeRate : IComparable, IComparable +#endif { /// /// Base unit of PressureChangeRate. /// private readonly double _pascalsPerSecond; - public PressureChangeRate(double pascalspersecond) : this() +#if WINDOWS_UWP + public PressureChangeRate() : this(0) + { + } +#endif + + public PressureChangeRate(double pascalspersecond) + { + _pascalsPerSecond = Convert.ToDouble(pascalspersecond); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + PressureChangeRate(long pascalspersecond) + { + _pascalsPerSecond = Convert.ToDouble(pascalspersecond); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + PressureChangeRate(decimal pascalspersecond) { - _pascalsPerSecond = pascalspersecond; + _pascalsPerSecond = Convert.ToDouble(pascalspersecond); } #region Properties @@ -127,7 +166,7 @@ public static PressureChangeRate FromPascalsPerSecond(double pascalspersecond) return new PressureChangeRate(pascalspersecond); } - +#if !WINDOWS_UWP /// /// Get nullable PressureChangeRate from nullable AtmospheresPerSecond. /// @@ -139,7 +178,7 @@ public static PressureChangeRate FromPascalsPerSecond(double pascalspersecond) } else { - return null; + return null; } } @@ -154,7 +193,7 @@ public static PressureChangeRate FromPascalsPerSecond(double pascalspersecond) } else { - return null; + return null; } } @@ -169,7 +208,7 @@ public static PressureChangeRate FromPascalsPerSecond(double pascalspersecond) } else { - return null; + return null; } } @@ -184,35 +223,37 @@ public static PressureChangeRate FromPascalsPerSecond(double pascalspersecond) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// PressureChangeRate unit value. - public static PressureChangeRate From(double value, PressureChangeRateUnit fromUnit) + public static PressureChangeRate From(double val, PressureChangeRateUnit fromUnit) { switch (fromUnit) { case PressureChangeRateUnit.AtmospherePerSecond: - return FromAtmospheresPerSecond(value); + return FromAtmospheresPerSecond(val); case PressureChangeRateUnit.KilopascalPerSecond: - return FromKilopascalsPerSecond(value); + return FromKilopascalsPerSecond(val); case PressureChangeRateUnit.MegapascalPerSecond: - return FromMegapascalsPerSecond(value); + return FromMegapascalsPerSecond(val); case PressureChangeRateUnit.PascalPerSecond: - return FromPascalsPerSecond(value); + return FromPascalsPerSecond(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -240,6 +281,18 @@ public static PressureChangeRate From(double value, PressureChangeRateUnit fromU throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(PressureChangeRateUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -248,7 +301,7 @@ public static PressureChangeRate From(double value, PressureChangeRateUnit fromU /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(PressureChangeRateUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(PressureChangeRateUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -257,6 +310,7 @@ public static string GetAbbreviation(PressureChangeRateUnit unit, CultureInfo cu #region Arithmetic Operators +#if !WINDOWS_UWP public static PressureChangeRate operator -(PressureChangeRate right) { return new PressureChangeRate(-right._pascalsPerSecond); @@ -291,6 +345,7 @@ public static string GetAbbreviation(PressureChangeRateUnit unit, CultureInfo cu { return Convert.ToDouble(left._pascalsPerSecond/right._pascalsPerSecond); } +#endif #endregion @@ -303,11 +358,17 @@ public int CompareTo(object obj) return CompareTo((PressureChangeRate) obj); } - public int CompareTo(PressureChangeRate other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(PressureChangeRate other) { return _pascalsPerSecond.CompareTo(other._pascalsPerSecond); } +#if !WINDOWS_UWP public static bool operator <=(PressureChangeRate left, PressureChangeRate right) { return left._pascalsPerSecond <= right._pascalsPerSecond; @@ -339,6 +400,7 @@ public int CompareTo(PressureChangeRate other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._pascalsPerSecond != right._pascalsPerSecond; } +#endif public override bool Equals(object obj) { @@ -390,7 +452,6 @@ public double As(PressureChangeRateUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -409,10 +470,43 @@ public double As(PressureChangeRateUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static PressureChangeRate Parse(string str, IFormatProvider formatProvider = null) + public static PressureChangeRate Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static PressureChangeRate Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -436,7 +530,7 @@ public static PressureChangeRate Parse(string str, IFormatProvider formatProvide "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => PressureChangeRate.FromPascalsPerSecond(x.PascalsPerSecond + y.PascalsPerSecond)); } /// @@ -473,7 +567,7 @@ private static List ParseWithRegex(string regexString, strin converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -498,18 +592,49 @@ private static List ParseWithRegex(string regexString, strin /// /// The value of 'str' cannot be null. /// Error parsing string. - public static PressureChangeRateUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static PressureChangeRateUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static PressureChangeRateUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static PressureChangeRateUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == PressureChangeRateUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized PressureChangeRateUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -532,6 +657,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(PressureChangeRateUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(PressureChangeRateUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -540,9 +686,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(PressureChangeRateUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(PressureChangeRateUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -554,9 +702,20 @@ public string ToString(PressureChangeRateUnit unit, CultureInfo culture = null, /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(PressureChangeRateUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(PressureChangeRateUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/Ratio.g.cs b/UnitsNet/GeneratedCode/UnitClasses/Ratio.g.cs index 4e56290c82..12daea905c 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/Ratio.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/Ratio.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// In mathematics, a ratio is a relationship between two numbers of the same kind (e.g., objects, persons, students, spoonfuls, units of whatever identical dimension), usually expressed as "a to b" or a:b, sometimes expressed arithmetically as a dimensionless quotient of the two that explicitly indicates how many times the first number contains the second (not necessarily an integer). /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class Ratio +#else public partial struct Ratio : IComparable, IComparable +#endif { /// /// Base unit of Ratio. /// private readonly double _decimalFractions; - public Ratio(double decimalfractions) : this() +#if WINDOWS_UWP + public Ratio() : this(0) + { + } +#endif + + public Ratio(double decimalfractions) + { + _decimalFractions = Convert.ToDouble(decimalfractions); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Ratio(long decimalfractions) + { + _decimalFractions = Convert.ToDouble(decimalfractions); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Ratio(decimal decimalfractions) { - _decimalFractions = decimalfractions; + _decimalFractions = Convert.ToDouble(decimalfractions); } #region Properties @@ -159,7 +198,7 @@ public static Ratio FromPercent(double percent) return new Ratio(percent/1e2); } - +#if !WINDOWS_UWP /// /// Get nullable Ratio from nullable DecimalFractions. /// @@ -171,7 +210,7 @@ public static Ratio FromPercent(double percent) } else { - return null; + return null; } } @@ -186,7 +225,7 @@ public static Ratio FromPercent(double percent) } else { - return null; + return null; } } @@ -201,7 +240,7 @@ public static Ratio FromPercent(double percent) } else { - return null; + return null; } } @@ -216,7 +255,7 @@ public static Ratio FromPercent(double percent) } else { - return null; + return null; } } @@ -231,7 +270,7 @@ public static Ratio FromPercent(double percent) } else { - return null; + return null; } } @@ -246,39 +285,41 @@ public static Ratio FromPercent(double percent) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// Ratio unit value. - public static Ratio From(double value, RatioUnit fromUnit) + public static Ratio From(double val, RatioUnit fromUnit) { switch (fromUnit) { case RatioUnit.DecimalFraction: - return FromDecimalFractions(value); + return FromDecimalFractions(val); case RatioUnit.PartPerBillion: - return FromPartsPerBillion(value); + return FromPartsPerBillion(val); case RatioUnit.PartPerMillion: - return FromPartsPerMillion(value); + return FromPartsPerMillion(val); case RatioUnit.PartPerThousand: - return FromPartsPerThousand(value); + return FromPartsPerThousand(val); case RatioUnit.PartPerTrillion: - return FromPartsPerTrillion(value); + return FromPartsPerTrillion(val); case RatioUnit.Percent: - return FromPercent(value); + return FromPercent(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -310,6 +351,18 @@ public static Ratio From(double value, RatioUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(RatioUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -318,7 +371,7 @@ public static Ratio From(double value, RatioUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(RatioUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(RatioUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -327,6 +380,7 @@ public static string GetAbbreviation(RatioUnit unit, CultureInfo culture = null) #region Arithmetic Operators +#if !WINDOWS_UWP public static Ratio operator -(Ratio right) { return new Ratio(-right._decimalFractions); @@ -361,6 +415,7 @@ public static string GetAbbreviation(RatioUnit unit, CultureInfo culture = null) { return Convert.ToDouble(left._decimalFractions/right._decimalFractions); } +#endif #endregion @@ -373,11 +428,17 @@ public int CompareTo(object obj) return CompareTo((Ratio) obj); } - public int CompareTo(Ratio other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(Ratio other) { return _decimalFractions.CompareTo(other._decimalFractions); } +#if !WINDOWS_UWP public static bool operator <=(Ratio left, Ratio right) { return left._decimalFractions <= right._decimalFractions; @@ -409,6 +470,7 @@ public int CompareTo(Ratio other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._decimalFractions != right._decimalFractions; } +#endif public override bool Equals(object obj) { @@ -464,7 +526,6 @@ public double As(RatioUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -483,10 +544,43 @@ public double As(RatioUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static Ratio Parse(string str, IFormatProvider formatProvider = null) + public static Ratio Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static Ratio Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -510,7 +604,7 @@ public static Ratio Parse(string str, IFormatProvider formatProvider = null) "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => Ratio.FromDecimalFractions(x.DecimalFractions + y.DecimalFractions)); } /// @@ -547,7 +641,7 @@ private static List ParseWithRegex(string regexString, string str, IForma converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -572,18 +666,49 @@ private static List ParseWithRegex(string regexString, string str, IForma /// /// The value of 'str' cannot be null. /// Error parsing string. - public static RatioUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static RatioUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static RatioUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static RatioUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == RatioUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized RatioUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -606,6 +731,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(RatioUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(RatioUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -614,9 +760,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(RatioUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(RatioUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -628,9 +776,20 @@ public string ToString(RatioUnit unit, CultureInfo culture = null, int significa /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(RatioUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(RatioUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/RotationalSpeed.g.cs b/UnitsNet/GeneratedCode/UnitClasses/RotationalSpeed.g.cs index 93aaf7ae34..72d4dea1fb 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/RotationalSpeed.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/RotationalSpeed.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// Rotational speed (sometimes called speed of revolution) is the number of complete rotations, revolutions, cycles, or turns per time unit. Rotational speed is a cyclic frequency, measured in radians per second or in hertz in the SI System by scientists, or in revolutions per minute (rpm or min-1) or revolutions per second in everyday life. The symbol for rotational speed is ω (the Greek lowercase letter "omega"). /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class RotationalSpeed +#else public partial struct RotationalSpeed : IComparable, IComparable +#endif { /// /// Base unit of RotationalSpeed. /// private readonly double _radiansPerSecond; - public RotationalSpeed(double radianspersecond) : this() +#if WINDOWS_UWP + public RotationalSpeed() : this(0) + { + } +#endif + + public RotationalSpeed(double radianspersecond) + { + _radiansPerSecond = Convert.ToDouble(radianspersecond); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + RotationalSpeed(long radianspersecond) { - _radiansPerSecond = radianspersecond; + _radiansPerSecond = Convert.ToDouble(radianspersecond); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + RotationalSpeed(decimal radianspersecond) + { + _radiansPerSecond = Convert.ToDouble(radianspersecond); } #region Properties @@ -271,7 +310,7 @@ public static RotationalSpeed FromRevolutionsPerSecond(double revolutionsperseco return new RotationalSpeed(revolutionspersecond*6.2831853072); } - +#if !WINDOWS_UWP /// /// Get nullable RotationalSpeed from nullable CentiradiansPerSecond. /// @@ -283,7 +322,7 @@ public static RotationalSpeed FromRevolutionsPerSecond(double revolutionsperseco } else { - return null; + return null; } } @@ -298,7 +337,7 @@ public static RotationalSpeed FromRevolutionsPerSecond(double revolutionsperseco } else { - return null; + return null; } } @@ -313,7 +352,7 @@ public static RotationalSpeed FromRevolutionsPerSecond(double revolutionsperseco } else { - return null; + return null; } } @@ -328,7 +367,7 @@ public static RotationalSpeed FromRevolutionsPerSecond(double revolutionsperseco } else { - return null; + return null; } } @@ -343,7 +382,7 @@ public static RotationalSpeed FromRevolutionsPerSecond(double revolutionsperseco } else { - return null; + return null; } } @@ -358,7 +397,7 @@ public static RotationalSpeed FromRevolutionsPerSecond(double revolutionsperseco } else { - return null; + return null; } } @@ -373,7 +412,7 @@ public static RotationalSpeed FromRevolutionsPerSecond(double revolutionsperseco } else { - return null; + return null; } } @@ -388,7 +427,7 @@ public static RotationalSpeed FromRevolutionsPerSecond(double revolutionsperseco } else { - return null; + return null; } } @@ -403,7 +442,7 @@ public static RotationalSpeed FromRevolutionsPerSecond(double revolutionsperseco } else { - return null; + return null; } } @@ -418,7 +457,7 @@ public static RotationalSpeed FromRevolutionsPerSecond(double revolutionsperseco } else { - return null; + return null; } } @@ -433,7 +472,7 @@ public static RotationalSpeed FromRevolutionsPerSecond(double revolutionsperseco } else { - return null; + return null; } } @@ -448,7 +487,7 @@ public static RotationalSpeed FromRevolutionsPerSecond(double revolutionsperseco } else { - return null; + return null; } } @@ -463,53 +502,55 @@ public static RotationalSpeed FromRevolutionsPerSecond(double revolutionsperseco } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// RotationalSpeed unit value. - public static RotationalSpeed From(double value, RotationalSpeedUnit fromUnit) + public static RotationalSpeed From(double val, RotationalSpeedUnit fromUnit) { switch (fromUnit) { case RotationalSpeedUnit.CentiradianPerSecond: - return FromCentiradiansPerSecond(value); + return FromCentiradiansPerSecond(val); case RotationalSpeedUnit.DeciradianPerSecond: - return FromDeciradiansPerSecond(value); + return FromDeciradiansPerSecond(val); case RotationalSpeedUnit.DegreePerMinute: - return FromDegreesPerMinute(value); + return FromDegreesPerMinute(val); case RotationalSpeedUnit.DegreePerSecond: - return FromDegreesPerSecond(value); + return FromDegreesPerSecond(val); case RotationalSpeedUnit.MicrodegreePerSecond: - return FromMicrodegreesPerSecond(value); + return FromMicrodegreesPerSecond(val); case RotationalSpeedUnit.MicroradianPerSecond: - return FromMicroradiansPerSecond(value); + return FromMicroradiansPerSecond(val); case RotationalSpeedUnit.MillidegreePerSecond: - return FromMillidegreesPerSecond(value); + return FromMillidegreesPerSecond(val); case RotationalSpeedUnit.MilliradianPerSecond: - return FromMilliradiansPerSecond(value); + return FromMilliradiansPerSecond(val); case RotationalSpeedUnit.NanodegreePerSecond: - return FromNanodegreesPerSecond(value); + return FromNanodegreesPerSecond(val); case RotationalSpeedUnit.NanoradianPerSecond: - return FromNanoradiansPerSecond(value); + return FromNanoradiansPerSecond(val); case RotationalSpeedUnit.RadianPerSecond: - return FromRadiansPerSecond(value); + return FromRadiansPerSecond(val); case RotationalSpeedUnit.RevolutionPerMinute: - return FromRevolutionsPerMinute(value); + return FromRevolutionsPerMinute(val); case RotationalSpeedUnit.RevolutionPerSecond: - return FromRevolutionsPerSecond(value); + return FromRevolutionsPerSecond(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -555,6 +596,18 @@ public static RotationalSpeed From(double value, RotationalSpeedUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(RotationalSpeedUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -563,7 +616,7 @@ public static RotationalSpeed From(double value, RotationalSpeedUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(RotationalSpeedUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(RotationalSpeedUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -572,6 +625,7 @@ public static string GetAbbreviation(RotationalSpeedUnit unit, CultureInfo cultu #region Arithmetic Operators +#if !WINDOWS_UWP public static RotationalSpeed operator -(RotationalSpeed right) { return new RotationalSpeed(-right._radiansPerSecond); @@ -606,6 +660,7 @@ public static string GetAbbreviation(RotationalSpeedUnit unit, CultureInfo cultu { return Convert.ToDouble(left._radiansPerSecond/right._radiansPerSecond); } +#endif #endregion @@ -618,11 +673,17 @@ public int CompareTo(object obj) return CompareTo((RotationalSpeed) obj); } - public int CompareTo(RotationalSpeed other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(RotationalSpeed other) { return _radiansPerSecond.CompareTo(other._radiansPerSecond); } +#if !WINDOWS_UWP public static bool operator <=(RotationalSpeed left, RotationalSpeed right) { return left._radiansPerSecond <= right._radiansPerSecond; @@ -654,6 +715,7 @@ public int CompareTo(RotationalSpeed other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._radiansPerSecond != right._radiansPerSecond; } +#endif public override bool Equals(object obj) { @@ -723,7 +785,6 @@ public double As(RotationalSpeedUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -742,10 +803,43 @@ public double As(RotationalSpeedUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static RotationalSpeed Parse(string str, IFormatProvider formatProvider = null) + public static RotationalSpeed Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static RotationalSpeed Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -769,7 +863,7 @@ public static RotationalSpeed Parse(string str, IFormatProvider formatProvider = "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => RotationalSpeed.FromRadiansPerSecond(x.RadiansPerSecond + y.RadiansPerSecond)); } /// @@ -806,7 +900,7 @@ private static List ParseWithRegex(string regexString, string s converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -831,18 +925,49 @@ private static List ParseWithRegex(string regexString, string s /// /// The value of 'str' cannot be null. /// Error parsing string. - public static RotationalSpeedUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static RotationalSpeedUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static RotationalSpeedUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static RotationalSpeedUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == RotationalSpeedUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized RotationalSpeedUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -865,6 +990,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(RotationalSpeedUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(RotationalSpeedUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -873,9 +1019,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(RotationalSpeedUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(RotationalSpeedUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -887,9 +1035,20 @@ public string ToString(RotationalSpeedUnit unit, CultureInfo culture = null, int /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(RotationalSpeedUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(RotationalSpeedUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/SpecificEnergy.g.cs b/UnitsNet/GeneratedCode/UnitClasses/SpecificEnergy.g.cs index 0e7006b7a3..cb525e883d 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/SpecificEnergy.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/SpecificEnergy.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// The SpecificEnergy /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class SpecificEnergy +#else public partial struct SpecificEnergy : IComparable, IComparable +#endif { /// /// Base unit of SpecificEnergy. /// private readonly double _joulesPerKilogram; - public SpecificEnergy(double joulesperkilogram) : this() +#if WINDOWS_UWP + public SpecificEnergy() : this(0) + { + } +#endif + + public SpecificEnergy(double joulesperkilogram) + { + _joulesPerKilogram = Convert.ToDouble(joulesperkilogram); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + SpecificEnergy(long joulesperkilogram) + { + _joulesPerKilogram = Convert.ToDouble(joulesperkilogram); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + SpecificEnergy(decimal joulesperkilogram) { - _joulesPerKilogram = joulesperkilogram; + _joulesPerKilogram = Convert.ToDouble(joulesperkilogram); } #region Properties @@ -191,7 +230,7 @@ public static SpecificEnergy FromWattHoursPerKilogram(double watthoursperkilogra return new SpecificEnergy(watthoursperkilogram*3.6e3); } - +#if !WINDOWS_UWP /// /// Get nullable SpecificEnergy from nullable CaloriesPerGram. /// @@ -203,7 +242,7 @@ public static SpecificEnergy FromWattHoursPerKilogram(double watthoursperkilogra } else { - return null; + return null; } } @@ -218,7 +257,7 @@ public static SpecificEnergy FromWattHoursPerKilogram(double watthoursperkilogra } else { - return null; + return null; } } @@ -233,7 +272,7 @@ public static SpecificEnergy FromWattHoursPerKilogram(double watthoursperkilogra } else { - return null; + return null; } } @@ -248,7 +287,7 @@ public static SpecificEnergy FromWattHoursPerKilogram(double watthoursperkilogra } else { - return null; + return null; } } @@ -263,7 +302,7 @@ public static SpecificEnergy FromWattHoursPerKilogram(double watthoursperkilogra } else { - return null; + return null; } } @@ -278,7 +317,7 @@ public static SpecificEnergy FromWattHoursPerKilogram(double watthoursperkilogra } else { - return null; + return null; } } @@ -293,7 +332,7 @@ public static SpecificEnergy FromWattHoursPerKilogram(double watthoursperkilogra } else { - return null; + return null; } } @@ -308,43 +347,45 @@ public static SpecificEnergy FromWattHoursPerKilogram(double watthoursperkilogra } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// SpecificEnergy unit value. - public static SpecificEnergy From(double value, SpecificEnergyUnit fromUnit) + public static SpecificEnergy From(double val, SpecificEnergyUnit fromUnit) { switch (fromUnit) { case SpecificEnergyUnit.CaloriePerGram: - return FromCaloriesPerGram(value); + return FromCaloriesPerGram(val); case SpecificEnergyUnit.JoulePerKilogram: - return FromJoulesPerKilogram(value); + return FromJoulesPerKilogram(val); case SpecificEnergyUnit.KilocaloriePerGram: - return FromKilocaloriesPerGram(value); + return FromKilocaloriesPerGram(val); case SpecificEnergyUnit.KilojoulePerKilogram: - return FromKilojoulesPerKilogram(value); + return FromKilojoulesPerKilogram(val); case SpecificEnergyUnit.KilowattHourPerKilogram: - return FromKilowattHoursPerKilogram(value); + return FromKilowattHoursPerKilogram(val); case SpecificEnergyUnit.MegajoulePerKilogram: - return FromMegajoulesPerKilogram(value); + return FromMegajoulesPerKilogram(val); case SpecificEnergyUnit.MegawattHourPerKilogram: - return FromMegawattHoursPerKilogram(value); + return FromMegawattHoursPerKilogram(val); case SpecificEnergyUnit.WattHourPerKilogram: - return FromWattHoursPerKilogram(value); + return FromWattHoursPerKilogram(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -380,6 +421,18 @@ public static SpecificEnergy From(double value, SpecificEnergyUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(SpecificEnergyUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -388,7 +441,7 @@ public static SpecificEnergy From(double value, SpecificEnergyUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(SpecificEnergyUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(SpecificEnergyUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -397,6 +450,7 @@ public static string GetAbbreviation(SpecificEnergyUnit unit, CultureInfo cultur #region Arithmetic Operators +#if !WINDOWS_UWP public static SpecificEnergy operator -(SpecificEnergy right) { return new SpecificEnergy(-right._joulesPerKilogram); @@ -431,6 +485,7 @@ public static string GetAbbreviation(SpecificEnergyUnit unit, CultureInfo cultur { return Convert.ToDouble(left._joulesPerKilogram/right._joulesPerKilogram); } +#endif #endregion @@ -443,11 +498,17 @@ public int CompareTo(object obj) return CompareTo((SpecificEnergy) obj); } - public int CompareTo(SpecificEnergy other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(SpecificEnergy other) { return _joulesPerKilogram.CompareTo(other._joulesPerKilogram); } +#if !WINDOWS_UWP public static bool operator <=(SpecificEnergy left, SpecificEnergy right) { return left._joulesPerKilogram <= right._joulesPerKilogram; @@ -479,6 +540,7 @@ public int CompareTo(SpecificEnergy other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._joulesPerKilogram != right._joulesPerKilogram; } +#endif public override bool Equals(object obj) { @@ -538,7 +600,6 @@ public double As(SpecificEnergyUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -557,10 +618,43 @@ public double As(SpecificEnergyUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static SpecificEnergy Parse(string str, IFormatProvider formatProvider = null) + public static SpecificEnergy Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static SpecificEnergy Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -584,7 +678,7 @@ public static SpecificEnergy Parse(string str, IFormatProvider formatProvider = "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => SpecificEnergy.FromJoulesPerKilogram(x.JoulesPerKilogram + y.JoulesPerKilogram)); } /// @@ -621,7 +715,7 @@ private static List ParseWithRegex(string regexString, string st converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -646,18 +740,49 @@ private static List ParseWithRegex(string regexString, string st /// /// The value of 'str' cannot be null. /// Error parsing string. - public static SpecificEnergyUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static SpecificEnergyUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static SpecificEnergyUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static SpecificEnergyUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == SpecificEnergyUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized SpecificEnergyUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -680,6 +805,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(SpecificEnergyUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(SpecificEnergyUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -688,9 +834,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(SpecificEnergyUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(SpecificEnergyUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -702,9 +850,20 @@ public string ToString(SpecificEnergyUnit unit, CultureInfo culture = null, int /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(SpecificEnergyUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(SpecificEnergyUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/SpecificWeight.g.cs b/UnitsNet/GeneratedCode/UnitClasses/SpecificWeight.g.cs index 678188b3f0..ef580ef065 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/SpecificWeight.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/SpecificWeight.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// The SpecificWeight, or more precisely, the volumetric weight density, of a substance is its weight per unit volume. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class SpecificWeight +#else public partial struct SpecificWeight : IComparable, IComparable +#endif { /// /// Base unit of SpecificWeight. /// private readonly double _newtonsPerCubicMeter; - public SpecificWeight(double newtonspercubicmeter) : this() +#if WINDOWS_UWP + public SpecificWeight() : this(0) + { + } +#endif + + public SpecificWeight(double newtonspercubicmeter) + { + _newtonsPerCubicMeter = Convert.ToDouble(newtonspercubicmeter); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + SpecificWeight(long newtonspercubicmeter) { - _newtonsPerCubicMeter = newtonspercubicmeter; + _newtonsPerCubicMeter = Convert.ToDouble(newtonspercubicmeter); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + SpecificWeight(decimal newtonspercubicmeter) + { + _newtonsPerCubicMeter = Convert.ToDouble(newtonspercubicmeter); } #region Properties @@ -319,7 +358,7 @@ public static SpecificWeight FromTonnesForcePerCubicMillimeter(double tonnesforc return new SpecificWeight(tonnesforcepercubicmillimeter*9806650199606.53); } - +#if !WINDOWS_UWP /// /// Get nullable SpecificWeight from nullable KilogramsForcePerCubicCentimeter. /// @@ -331,7 +370,7 @@ public static SpecificWeight FromTonnesForcePerCubicMillimeter(double tonnesforc } else { - return null; + return null; } } @@ -346,7 +385,7 @@ public static SpecificWeight FromTonnesForcePerCubicMillimeter(double tonnesforc } else { - return null; + return null; } } @@ -361,7 +400,7 @@ public static SpecificWeight FromTonnesForcePerCubicMillimeter(double tonnesforc } else { - return null; + return null; } } @@ -376,7 +415,7 @@ public static SpecificWeight FromTonnesForcePerCubicMillimeter(double tonnesforc } else { - return null; + return null; } } @@ -391,7 +430,7 @@ public static SpecificWeight FromTonnesForcePerCubicMillimeter(double tonnesforc } else { - return null; + return null; } } @@ -406,7 +445,7 @@ public static SpecificWeight FromTonnesForcePerCubicMillimeter(double tonnesforc } else { - return null; + return null; } } @@ -421,7 +460,7 @@ public static SpecificWeight FromTonnesForcePerCubicMillimeter(double tonnesforc } else { - return null; + return null; } } @@ -436,7 +475,7 @@ public static SpecificWeight FromTonnesForcePerCubicMillimeter(double tonnesforc } else { - return null; + return null; } } @@ -451,7 +490,7 @@ public static SpecificWeight FromTonnesForcePerCubicMillimeter(double tonnesforc } else { - return null; + return null; } } @@ -466,7 +505,7 @@ public static SpecificWeight FromTonnesForcePerCubicMillimeter(double tonnesforc } else { - return null; + return null; } } @@ -481,7 +520,7 @@ public static SpecificWeight FromTonnesForcePerCubicMillimeter(double tonnesforc } else { - return null; + return null; } } @@ -496,7 +535,7 @@ public static SpecificWeight FromTonnesForcePerCubicMillimeter(double tonnesforc } else { - return null; + return null; } } @@ -511,7 +550,7 @@ public static SpecificWeight FromTonnesForcePerCubicMillimeter(double tonnesforc } else { - return null; + return null; } } @@ -526,7 +565,7 @@ public static SpecificWeight FromTonnesForcePerCubicMillimeter(double tonnesforc } else { - return null; + return null; } } @@ -541,7 +580,7 @@ public static SpecificWeight FromTonnesForcePerCubicMillimeter(double tonnesforc } else { - return null; + return null; } } @@ -556,59 +595,61 @@ public static SpecificWeight FromTonnesForcePerCubicMillimeter(double tonnesforc } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// SpecificWeight unit value. - public static SpecificWeight From(double value, SpecificWeightUnit fromUnit) + public static SpecificWeight From(double val, SpecificWeightUnit fromUnit) { switch (fromUnit) { case SpecificWeightUnit.KilogramForcePerCubicCentimeter: - return FromKilogramsForcePerCubicCentimeter(value); + return FromKilogramsForcePerCubicCentimeter(val); case SpecificWeightUnit.KilogramForcePerCubicMeter: - return FromKilogramsForcePerCubicMeter(value); + return FromKilogramsForcePerCubicMeter(val); case SpecificWeightUnit.KilogramForcePerCubicMillimeter: - return FromKilogramsForcePerCubicMillimeter(value); + return FromKilogramsForcePerCubicMillimeter(val); case SpecificWeightUnit.KilonewtonPerCubicCentimeter: - return FromKilonewtonsPerCubicCentimeter(value); + return FromKilonewtonsPerCubicCentimeter(val); case SpecificWeightUnit.KilonewtonPerCubicMeter: - return FromKilonewtonsPerCubicMeter(value); + return FromKilonewtonsPerCubicMeter(val); case SpecificWeightUnit.KilonewtonPerCubicMillimeter: - return FromKilonewtonsPerCubicMillimeter(value); + return FromKilonewtonsPerCubicMillimeter(val); case SpecificWeightUnit.KilopoundForcePerCubicFoot: - return FromKilopoundsForcePerCubicFoot(value); + return FromKilopoundsForcePerCubicFoot(val); case SpecificWeightUnit.KilopoundForcePerCubicInch: - return FromKilopoundsForcePerCubicInch(value); + return FromKilopoundsForcePerCubicInch(val); case SpecificWeightUnit.NewtonPerCubicCentimeter: - return FromNewtonsPerCubicCentimeter(value); + return FromNewtonsPerCubicCentimeter(val); case SpecificWeightUnit.NewtonPerCubicMeter: - return FromNewtonsPerCubicMeter(value); + return FromNewtonsPerCubicMeter(val); case SpecificWeightUnit.NewtonPerCubicMillimeter: - return FromNewtonsPerCubicMillimeter(value); + return FromNewtonsPerCubicMillimeter(val); case SpecificWeightUnit.PoundForcePerCubicFoot: - return FromPoundsForcePerCubicFoot(value); + return FromPoundsForcePerCubicFoot(val); case SpecificWeightUnit.PoundForcePerCubicInch: - return FromPoundsForcePerCubicInch(value); + return FromPoundsForcePerCubicInch(val); case SpecificWeightUnit.TonneForcePerCubicCentimeter: - return FromTonnesForcePerCubicCentimeter(value); + return FromTonnesForcePerCubicCentimeter(val); case SpecificWeightUnit.TonneForcePerCubicMeter: - return FromTonnesForcePerCubicMeter(value); + return FromTonnesForcePerCubicMeter(val); case SpecificWeightUnit.TonneForcePerCubicMillimeter: - return FromTonnesForcePerCubicMillimeter(value); + return FromTonnesForcePerCubicMillimeter(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -660,6 +701,18 @@ public static SpecificWeight From(double value, SpecificWeightUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(SpecificWeightUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -668,7 +721,7 @@ public static SpecificWeight From(double value, SpecificWeightUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(SpecificWeightUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(SpecificWeightUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -677,6 +730,7 @@ public static string GetAbbreviation(SpecificWeightUnit unit, CultureInfo cultur #region Arithmetic Operators +#if !WINDOWS_UWP public static SpecificWeight operator -(SpecificWeight right) { return new SpecificWeight(-right._newtonsPerCubicMeter); @@ -711,6 +765,7 @@ public static string GetAbbreviation(SpecificWeightUnit unit, CultureInfo cultur { return Convert.ToDouble(left._newtonsPerCubicMeter/right._newtonsPerCubicMeter); } +#endif #endregion @@ -723,11 +778,17 @@ public int CompareTo(object obj) return CompareTo((SpecificWeight) obj); } - public int CompareTo(SpecificWeight other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(SpecificWeight other) { return _newtonsPerCubicMeter.CompareTo(other._newtonsPerCubicMeter); } +#if !WINDOWS_UWP public static bool operator <=(SpecificWeight left, SpecificWeight right) { return left._newtonsPerCubicMeter <= right._newtonsPerCubicMeter; @@ -759,6 +820,7 @@ public int CompareTo(SpecificWeight other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._newtonsPerCubicMeter != right._newtonsPerCubicMeter; } +#endif public override bool Equals(object obj) { @@ -834,7 +896,6 @@ public double As(SpecificWeightUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -853,10 +914,43 @@ public double As(SpecificWeightUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static SpecificWeight Parse(string str, IFormatProvider formatProvider = null) + public static SpecificWeight Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static SpecificWeight Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -880,7 +974,7 @@ public static SpecificWeight Parse(string str, IFormatProvider formatProvider = "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => SpecificWeight.FromNewtonsPerCubicMeter(x.NewtonsPerCubicMeter + y.NewtonsPerCubicMeter)); } /// @@ -917,7 +1011,7 @@ private static List ParseWithRegex(string regexString, string st converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -942,18 +1036,49 @@ private static List ParseWithRegex(string regexString, string st /// /// The value of 'str' cannot be null. /// Error parsing string. - public static SpecificWeightUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static SpecificWeightUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static SpecificWeightUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static SpecificWeightUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == SpecificWeightUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized SpecificWeightUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -976,6 +1101,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(SpecificWeightUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(SpecificWeightUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -984,9 +1130,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(SpecificWeightUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(SpecificWeightUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -998,9 +1146,20 @@ public string ToString(SpecificWeightUnit unit, CultureInfo culture = null, int /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(SpecificWeightUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(SpecificWeightUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/Speed.g.cs b/UnitsNet/GeneratedCode/UnitClasses/Speed.g.cs index 18541fbfb0..fe6643ee78 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/Speed.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/Speed.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// In everyday use and in kinematics, the speed of an object is the magnitude of its velocity (the rate of change of its position); it is thus a scalar quantity.[1] The average speed of an object in an interval of time is the distance travelled by the object divided by the duration of the interval;[2] the instantaneous speed is the limit of the average speed as the duration of the time interval approaches zero. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class Speed +#else public partial struct Speed : IComparable, IComparable +#endif { /// /// Base unit of Speed. /// private readonly double _metersPerSecond; - public Speed(double meterspersecond) : this() +#if WINDOWS_UWP + public Speed() : this(0) + { + } +#endif + + public Speed(double meterspersecond) + { + _metersPerSecond = Convert.ToDouble(meterspersecond); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Speed(long meterspersecond) { - _metersPerSecond = meterspersecond; + _metersPerSecond = Convert.ToDouble(meterspersecond); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Speed(decimal meterspersecond) + { + _metersPerSecond = Convert.ToDouble(meterspersecond); } #region Properties @@ -367,7 +406,7 @@ public static Speed FromNanometersPerSecond(double nanometerspersecond) return new Speed((nanometerspersecond) * 1e-9d); } - +#if !WINDOWS_UWP /// /// Get nullable Speed from nullable CentimetersPerMinutes. /// @@ -379,7 +418,7 @@ public static Speed FromNanometersPerSecond(double nanometerspersecond) } else { - return null; + return null; } } @@ -394,7 +433,7 @@ public static Speed FromNanometersPerSecond(double nanometerspersecond) } else { - return null; + return null; } } @@ -409,7 +448,7 @@ public static Speed FromNanometersPerSecond(double nanometerspersecond) } else { - return null; + return null; } } @@ -424,7 +463,7 @@ public static Speed FromNanometersPerSecond(double nanometerspersecond) } else { - return null; + return null; } } @@ -439,7 +478,7 @@ public static Speed FromNanometersPerSecond(double nanometerspersecond) } else { - return null; + return null; } } @@ -454,7 +493,7 @@ public static Speed FromNanometersPerSecond(double nanometerspersecond) } else { - return null; + return null; } } @@ -469,7 +508,7 @@ public static Speed FromNanometersPerSecond(double nanometerspersecond) } else { - return null; + return null; } } @@ -484,7 +523,7 @@ public static Speed FromNanometersPerSecond(double nanometerspersecond) } else { - return null; + return null; } } @@ -499,7 +538,7 @@ public static Speed FromNanometersPerSecond(double nanometerspersecond) } else { - return null; + return null; } } @@ -514,7 +553,7 @@ public static Speed FromNanometersPerSecond(double nanometerspersecond) } else { - return null; + return null; } } @@ -529,7 +568,7 @@ public static Speed FromNanometersPerSecond(double nanometerspersecond) } else { - return null; + return null; } } @@ -544,7 +583,7 @@ public static Speed FromNanometersPerSecond(double nanometerspersecond) } else { - return null; + return null; } } @@ -559,7 +598,7 @@ public static Speed FromNanometersPerSecond(double nanometerspersecond) } else { - return null; + return null; } } @@ -574,7 +613,7 @@ public static Speed FromNanometersPerSecond(double nanometerspersecond) } else { - return null; + return null; } } @@ -589,7 +628,7 @@ public static Speed FromNanometersPerSecond(double nanometerspersecond) } else { - return null; + return null; } } @@ -604,7 +643,7 @@ public static Speed FromNanometersPerSecond(double nanometerspersecond) } else { - return null; + return null; } } @@ -619,7 +658,7 @@ public static Speed FromNanometersPerSecond(double nanometerspersecond) } else { - return null; + return null; } } @@ -634,7 +673,7 @@ public static Speed FromNanometersPerSecond(double nanometerspersecond) } else { - return null; + return null; } } @@ -649,65 +688,67 @@ public static Speed FromNanometersPerSecond(double nanometerspersecond) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// Speed unit value. - public static Speed From(double value, SpeedUnit fromUnit) + public static Speed From(double val, SpeedUnit fromUnit) { switch (fromUnit) { case SpeedUnit.CentimeterPerMinute: - return FromCentimetersPerMinutes(value); + return FromCentimetersPerMinutes(val); case SpeedUnit.CentimeterPerSecond: - return FromCentimetersPerSecond(value); + return FromCentimetersPerSecond(val); case SpeedUnit.DecimeterPerMinute: - return FromDecimetersPerMinutes(value); + return FromDecimetersPerMinutes(val); case SpeedUnit.DecimeterPerSecond: - return FromDecimetersPerSecond(value); + return FromDecimetersPerSecond(val); case SpeedUnit.FootPerSecond: - return FromFeetPerSecond(value); + return FromFeetPerSecond(val); case SpeedUnit.KilometerPerHour: - return FromKilometersPerHour(value); + return FromKilometersPerHour(val); case SpeedUnit.KilometerPerMinute: - return FromKilometersPerMinutes(value); + return FromKilometersPerMinutes(val); case SpeedUnit.KilometerPerSecond: - return FromKilometersPerSecond(value); + return FromKilometersPerSecond(val); case SpeedUnit.Knot: - return FromKnots(value); + return FromKnots(val); case SpeedUnit.MeterPerHour: - return FromMetersPerHour(value); + return FromMetersPerHour(val); case SpeedUnit.MeterPerMinute: - return FromMetersPerMinutes(value); + return FromMetersPerMinutes(val); case SpeedUnit.MeterPerSecond: - return FromMetersPerSecond(value); + return FromMetersPerSecond(val); case SpeedUnit.MicrometerPerMinute: - return FromMicrometersPerMinutes(value); + return FromMicrometersPerMinutes(val); case SpeedUnit.MicrometerPerSecond: - return FromMicrometersPerSecond(value); + return FromMicrometersPerSecond(val); case SpeedUnit.MilePerHour: - return FromMilesPerHour(value); + return FromMilesPerHour(val); case SpeedUnit.MillimeterPerMinute: - return FromMillimetersPerMinutes(value); + return FromMillimetersPerMinutes(val); case SpeedUnit.MillimeterPerSecond: - return FromMillimetersPerSecond(value); + return FromMillimetersPerSecond(val); case SpeedUnit.NanometerPerMinute: - return FromNanometersPerMinutes(value); + return FromNanometersPerMinutes(val); case SpeedUnit.NanometerPerSecond: - return FromNanometersPerSecond(value); + return FromNanometersPerSecond(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -765,6 +806,18 @@ public static Speed From(double value, SpeedUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(SpeedUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -773,7 +826,7 @@ public static Speed From(double value, SpeedUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(SpeedUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(SpeedUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -782,6 +835,7 @@ public static string GetAbbreviation(SpeedUnit unit, CultureInfo culture = null) #region Arithmetic Operators +#if !WINDOWS_UWP public static Speed operator -(Speed right) { return new Speed(-right._metersPerSecond); @@ -816,6 +870,7 @@ public static string GetAbbreviation(SpeedUnit unit, CultureInfo culture = null) { return Convert.ToDouble(left._metersPerSecond/right._metersPerSecond); } +#endif #endregion @@ -828,11 +883,17 @@ public int CompareTo(object obj) return CompareTo((Speed) obj); } - public int CompareTo(Speed other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(Speed other) { return _metersPerSecond.CompareTo(other._metersPerSecond); } +#if !WINDOWS_UWP public static bool operator <=(Speed left, Speed right) { return left._metersPerSecond <= right._metersPerSecond; @@ -864,6 +925,7 @@ public int CompareTo(Speed other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._metersPerSecond != right._metersPerSecond; } +#endif public override bool Equals(object obj) { @@ -945,7 +1007,6 @@ public double As(SpeedUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -964,10 +1025,43 @@ public double As(SpeedUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static Speed Parse(string str, IFormatProvider formatProvider = null) + public static Speed Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static Speed Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -991,7 +1085,7 @@ public static Speed Parse(string str, IFormatProvider formatProvider = null) "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => Speed.FromMetersPerSecond(x.MetersPerSecond + y.MetersPerSecond)); } /// @@ -1028,7 +1122,7 @@ private static List ParseWithRegex(string regexString, string str, IForma converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -1053,18 +1147,49 @@ private static List ParseWithRegex(string regexString, string str, IForma /// /// The value of 'str' cannot be null. /// Error parsing string. - public static SpeedUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static SpeedUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static SpeedUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static SpeedUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == SpeedUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized SpeedUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -1087,6 +1212,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(SpeedUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(SpeedUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -1095,9 +1241,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(SpeedUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(SpeedUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -1109,9 +1257,20 @@ public string ToString(SpeedUnit unit, CultureInfo culture = null, int significa /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(SpeedUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(SpeedUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/Temperature.g.cs b/UnitsNet/GeneratedCode/UnitClasses/Temperature.g.cs index 2135ee5f56..608c3a37cf 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/Temperature.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/Temperature.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// A temperature is a numerical measure of hot or cold. Its measurement is by detection of heat radiation or particle velocity or kinetic energy, or by the bulk behavior of a thermometric material. It may be calibrated in any of various temperature scales, Celsius, Fahrenheit, Kelvin, etc. The fundamental physical definition of temperature is provided by thermodynamics. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class Temperature +#else public partial struct Temperature : IComparable, IComparable +#endif { /// /// Base unit of Temperature. /// private readonly double _kelvins; - public Temperature(double kelvins) : this() +#if WINDOWS_UWP + public Temperature() : this(0) + { + } +#endif + + public Temperature(double kelvins) + { + _kelvins = Convert.ToDouble(kelvins); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Temperature(long kelvins) + { + _kelvins = Convert.ToDouble(kelvins); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Temperature(decimal kelvins) { - _kelvins = kelvins; + _kelvins = Convert.ToDouble(kelvins); } #region Properties @@ -191,7 +230,7 @@ public static Temperature FromKelvins(double kelvins) return new Temperature(kelvins); } - +#if !WINDOWS_UWP /// /// Get nullable Temperature from nullable DegreesCelsius. /// @@ -203,7 +242,7 @@ public static Temperature FromKelvins(double kelvins) } else { - return null; + return null; } } @@ -218,7 +257,7 @@ public static Temperature FromKelvins(double kelvins) } else { - return null; + return null; } } @@ -233,7 +272,7 @@ public static Temperature FromKelvins(double kelvins) } else { - return null; + return null; } } @@ -248,7 +287,7 @@ public static Temperature FromKelvins(double kelvins) } else { - return null; + return null; } } @@ -263,7 +302,7 @@ public static Temperature FromKelvins(double kelvins) } else { - return null; + return null; } } @@ -278,7 +317,7 @@ public static Temperature FromKelvins(double kelvins) } else { - return null; + return null; } } @@ -293,7 +332,7 @@ public static Temperature FromKelvins(double kelvins) } else { - return null; + return null; } } @@ -308,43 +347,45 @@ public static Temperature FromKelvins(double kelvins) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// Temperature unit value. - public static Temperature From(double value, TemperatureUnit fromUnit) + public static Temperature From(double val, TemperatureUnit fromUnit) { switch (fromUnit) { case TemperatureUnit.DegreeCelsius: - return FromDegreesCelsius(value); + return FromDegreesCelsius(val); case TemperatureUnit.DegreeDelisle: - return FromDegreesDelisle(value); + return FromDegreesDelisle(val); case TemperatureUnit.DegreeFahrenheit: - return FromDegreesFahrenheit(value); + return FromDegreesFahrenheit(val); case TemperatureUnit.DegreeNewton: - return FromDegreesNewton(value); + return FromDegreesNewton(val); case TemperatureUnit.DegreeRankine: - return FromDegreesRankine(value); + return FromDegreesRankine(val); case TemperatureUnit.DegreeReaumur: - return FromDegreesReaumur(value); + return FromDegreesReaumur(val); case TemperatureUnit.DegreeRoemer: - return FromDegreesRoemer(value); + return FromDegreesRoemer(val); case TemperatureUnit.Kelvin: - return FromKelvins(value); + return FromKelvins(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -380,6 +421,18 @@ public static Temperature From(double value, TemperatureUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(TemperatureUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -388,7 +441,7 @@ public static Temperature From(double value, TemperatureUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(TemperatureUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(TemperatureUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -397,6 +450,7 @@ public static string GetAbbreviation(TemperatureUnit unit, CultureInfo culture = #region Arithmetic Operators +#if !WINDOWS_UWP public static Temperature operator -(Temperature right) { return new Temperature(-right._kelvins); @@ -431,6 +485,7 @@ public static string GetAbbreviation(TemperatureUnit unit, CultureInfo culture = { return Convert.ToDouble(left._kelvins/right._kelvins); } +#endif #endregion @@ -443,11 +498,17 @@ public int CompareTo(object obj) return CompareTo((Temperature) obj); } - public int CompareTo(Temperature other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(Temperature other) { return _kelvins.CompareTo(other._kelvins); } +#if !WINDOWS_UWP public static bool operator <=(Temperature left, Temperature right) { return left._kelvins <= right._kelvins; @@ -479,6 +540,7 @@ public int CompareTo(Temperature other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._kelvins != right._kelvins; } +#endif public override bool Equals(object obj) { @@ -538,7 +600,6 @@ public double As(TemperatureUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -557,10 +618,43 @@ public double As(TemperatureUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static Temperature Parse(string str, IFormatProvider formatProvider = null) + public static Temperature Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static Temperature Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -584,7 +678,7 @@ public static Temperature Parse(string str, IFormatProvider formatProvider = nul "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => Temperature.FromKelvins(x.Kelvins + y.Kelvins)); } /// @@ -621,7 +715,7 @@ private static List ParseWithRegex(string regexString, string str, converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -646,18 +740,49 @@ private static List ParseWithRegex(string regexString, string str, /// /// The value of 'str' cannot be null. /// Error parsing string. - public static TemperatureUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static TemperatureUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static TemperatureUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static TemperatureUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == TemperatureUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized TemperatureUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -680,6 +805,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(TemperatureUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(TemperatureUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -688,9 +834,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(TemperatureUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(TemperatureUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -702,9 +850,20 @@ public string ToString(TemperatureUnit unit, CultureInfo culture = null, int sig /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(TemperatureUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(TemperatureUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/TemperatureChangeRate.g.cs b/UnitsNet/GeneratedCode/UnitClasses/TemperatureChangeRate.g.cs index c2f16f4d25..c3b50dcb00 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/TemperatureChangeRate.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/TemperatureChangeRate.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// Temperature change rate is the ratio of the temperature change to the time during which the change occurred (value of temperature changes per unit time). /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class TemperatureChangeRate +#else public partial struct TemperatureChangeRate : IComparable, IComparable +#endif { /// /// Base unit of TemperatureChangeRate. /// private readonly double _degreesCelsiusPerSecond; - public TemperatureChangeRate(double degreescelsiuspersecond) : this() +#if WINDOWS_UWP + public TemperatureChangeRate() : this(0) + { + } +#endif + + public TemperatureChangeRate(double degreescelsiuspersecond) + { + _degreesCelsiusPerSecond = Convert.ToDouble(degreescelsiuspersecond); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + TemperatureChangeRate(long degreescelsiuspersecond) + { + _degreesCelsiusPerSecond = Convert.ToDouble(degreescelsiuspersecond); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + TemperatureChangeRate(decimal degreescelsiuspersecond) { - _degreesCelsiusPerSecond = degreescelsiuspersecond; + _degreesCelsiusPerSecond = Convert.ToDouble(degreescelsiuspersecond); } #region Properties @@ -207,7 +246,7 @@ public static TemperatureChangeRate FromNanodegreesCelsiusPerSecond(double nanod return new TemperatureChangeRate((nanodegreescelsiuspersecond) * 1e-9d); } - +#if !WINDOWS_UWP /// /// Get nullable TemperatureChangeRate from nullable CentidegreesCelsiusPerSecond. /// @@ -219,7 +258,7 @@ public static TemperatureChangeRate FromNanodegreesCelsiusPerSecond(double nanod } else { - return null; + return null; } } @@ -234,7 +273,7 @@ public static TemperatureChangeRate FromNanodegreesCelsiusPerSecond(double nanod } else { - return null; + return null; } } @@ -249,7 +288,7 @@ public static TemperatureChangeRate FromNanodegreesCelsiusPerSecond(double nanod } else { - return null; + return null; } } @@ -264,7 +303,7 @@ public static TemperatureChangeRate FromNanodegreesCelsiusPerSecond(double nanod } else { - return null; + return null; } } @@ -279,7 +318,7 @@ public static TemperatureChangeRate FromNanodegreesCelsiusPerSecond(double nanod } else { - return null; + return null; } } @@ -294,7 +333,7 @@ public static TemperatureChangeRate FromNanodegreesCelsiusPerSecond(double nanod } else { - return null; + return null; } } @@ -309,7 +348,7 @@ public static TemperatureChangeRate FromNanodegreesCelsiusPerSecond(double nanod } else { - return null; + return null; } } @@ -324,7 +363,7 @@ public static TemperatureChangeRate FromNanodegreesCelsiusPerSecond(double nanod } else { - return null; + return null; } } @@ -339,45 +378,47 @@ public static TemperatureChangeRate FromNanodegreesCelsiusPerSecond(double nanod } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// TemperatureChangeRate unit value. - public static TemperatureChangeRate From(double value, TemperatureChangeRateUnit fromUnit) + public static TemperatureChangeRate From(double val, TemperatureChangeRateUnit fromUnit) { switch (fromUnit) { case TemperatureChangeRateUnit.CentidegreeCelsiusPerSecond: - return FromCentidegreesCelsiusPerSecond(value); + return FromCentidegreesCelsiusPerSecond(val); case TemperatureChangeRateUnit.DecadegreeCelsiusPerSecond: - return FromDecadegreesCelsiusPerSecond(value); + return FromDecadegreesCelsiusPerSecond(val); case TemperatureChangeRateUnit.DecidegreeCelsiusPerSecond: - return FromDecidegreesCelsiusPerSecond(value); + return FromDecidegreesCelsiusPerSecond(val); case TemperatureChangeRateUnit.DegreeCelsiusPerSecond: - return FromDegreesCelsiusPerSecond(value); + return FromDegreesCelsiusPerSecond(val); case TemperatureChangeRateUnit.HectodegreeCelsiusPerSecond: - return FromHectodegreesCelsiusPerSecond(value); + return FromHectodegreesCelsiusPerSecond(val); case TemperatureChangeRateUnit.KilodegreeCelsiusPerSecond: - return FromKilodegreesCelsiusPerSecond(value); + return FromKilodegreesCelsiusPerSecond(val); case TemperatureChangeRateUnit.MicrodegreeCelsiusPerSecond: - return FromMicrodegreesCelsiusPerSecond(value); + return FromMicrodegreesCelsiusPerSecond(val); case TemperatureChangeRateUnit.MillidegreeCelsiusPerSecond: - return FromMillidegreesCelsiusPerSecond(value); + return FromMillidegreesCelsiusPerSecond(val); case TemperatureChangeRateUnit.NanodegreeCelsiusPerSecond: - return FromNanodegreesCelsiusPerSecond(value); + return FromNanodegreesCelsiusPerSecond(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -415,6 +456,18 @@ public static TemperatureChangeRate From(double value, TemperatureChangeRateUnit throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(TemperatureChangeRateUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -423,7 +476,7 @@ public static TemperatureChangeRate From(double value, TemperatureChangeRateUnit /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(TemperatureChangeRateUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(TemperatureChangeRateUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -432,6 +485,7 @@ public static string GetAbbreviation(TemperatureChangeRateUnit unit, CultureInfo #region Arithmetic Operators +#if !WINDOWS_UWP public static TemperatureChangeRate operator -(TemperatureChangeRate right) { return new TemperatureChangeRate(-right._degreesCelsiusPerSecond); @@ -466,6 +520,7 @@ public static string GetAbbreviation(TemperatureChangeRateUnit unit, CultureInfo { return Convert.ToDouble(left._degreesCelsiusPerSecond/right._degreesCelsiusPerSecond); } +#endif #endregion @@ -478,11 +533,17 @@ public int CompareTo(object obj) return CompareTo((TemperatureChangeRate) obj); } - public int CompareTo(TemperatureChangeRate other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(TemperatureChangeRate other) { return _degreesCelsiusPerSecond.CompareTo(other._degreesCelsiusPerSecond); } +#if !WINDOWS_UWP public static bool operator <=(TemperatureChangeRate left, TemperatureChangeRate right) { return left._degreesCelsiusPerSecond <= right._degreesCelsiusPerSecond; @@ -514,6 +575,7 @@ public int CompareTo(TemperatureChangeRate other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._degreesCelsiusPerSecond != right._degreesCelsiusPerSecond; } +#endif public override bool Equals(object obj) { @@ -575,7 +637,6 @@ public double As(TemperatureChangeRateUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -594,10 +655,43 @@ public double As(TemperatureChangeRateUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static TemperatureChangeRate Parse(string str, IFormatProvider formatProvider = null) + public static TemperatureChangeRate Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static TemperatureChangeRate Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -621,7 +715,7 @@ public static TemperatureChangeRate Parse(string str, IFormatProvider formatProv "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => TemperatureChangeRate.FromDegreesCelsiusPerSecond(x.DegreesCelsiusPerSecond + y.DegreesCelsiusPerSecond)); } /// @@ -658,7 +752,7 @@ private static List ParseWithRegex(string regexString, st converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -683,18 +777,49 @@ private static List ParseWithRegex(string regexString, st /// /// The value of 'str' cannot be null. /// Error parsing string. - public static TemperatureChangeRateUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static TemperatureChangeRateUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static TemperatureChangeRateUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static TemperatureChangeRateUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == TemperatureChangeRateUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized TemperatureChangeRateUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -717,6 +842,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(TemperatureChangeRateUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(TemperatureChangeRateUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -725,9 +871,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(TemperatureChangeRateUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(TemperatureChangeRateUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -739,9 +887,20 @@ public string ToString(TemperatureChangeRateUnit unit, CultureInfo culture = nul /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(TemperatureChangeRateUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(TemperatureChangeRateUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/Torque.g.cs b/UnitsNet/GeneratedCode/UnitClasses/Torque.g.cs index d822463761..da3f608d9a 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/Torque.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/Torque.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// Torque, moment or moment of force (see the terminology below), is the tendency of a force to rotate an object about an axis,[1] fulcrum, or pivot. Just as a force is a push or a pull, a torque can be thought of as a twist to an object. Mathematically, torque is defined as the cross product of the lever-arm distance and force, which tends to produce rotation. Loosely speaking, torque is a measure of the turning force on an object such as a bolt or a flywheel. For example, pushing or pulling the handle of a wrench connected to a nut or bolt produces a torque (turning force) that loosens or tightens the nut or bolt. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class Torque +#else public partial struct Torque : IComparable, IComparable +#endif { /// /// Base unit of Torque. /// private readonly double _newtonMeters; - public Torque(double newtonmeters) : this() +#if WINDOWS_UWP + public Torque() : this(0) + { + } +#endif + + public Torque(double newtonmeters) + { + _newtonMeters = Convert.ToDouble(newtonmeters); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Torque(long newtonmeters) { - _newtonMeters = newtonmeters; + _newtonMeters = Convert.ToDouble(newtonmeters); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Torque(decimal newtonmeters) + { + _newtonMeters = Convert.ToDouble(newtonmeters); } #region Properties @@ -319,7 +358,7 @@ public static Torque FromTonneForceMillimeters(double tonneforcemillimeters) return new Torque(tonneforcemillimeters*9.80665019960652); } - +#if !WINDOWS_UWP /// /// Get nullable Torque from nullable KilogramForceCentimeters. /// @@ -331,7 +370,7 @@ public static Torque FromTonneForceMillimeters(double tonneforcemillimeters) } else { - return null; + return null; } } @@ -346,7 +385,7 @@ public static Torque FromTonneForceMillimeters(double tonneforcemillimeters) } else { - return null; + return null; } } @@ -361,7 +400,7 @@ public static Torque FromTonneForceMillimeters(double tonneforcemillimeters) } else { - return null; + return null; } } @@ -376,7 +415,7 @@ public static Torque FromTonneForceMillimeters(double tonneforcemillimeters) } else { - return null; + return null; } } @@ -391,7 +430,7 @@ public static Torque FromTonneForceMillimeters(double tonneforcemillimeters) } else { - return null; + return null; } } @@ -406,7 +445,7 @@ public static Torque FromTonneForceMillimeters(double tonneforcemillimeters) } else { - return null; + return null; } } @@ -421,7 +460,7 @@ public static Torque FromTonneForceMillimeters(double tonneforcemillimeters) } else { - return null; + return null; } } @@ -436,7 +475,7 @@ public static Torque FromTonneForceMillimeters(double tonneforcemillimeters) } else { - return null; + return null; } } @@ -451,7 +490,7 @@ public static Torque FromTonneForceMillimeters(double tonneforcemillimeters) } else { - return null; + return null; } } @@ -466,7 +505,7 @@ public static Torque FromTonneForceMillimeters(double tonneforcemillimeters) } else { - return null; + return null; } } @@ -481,7 +520,7 @@ public static Torque FromTonneForceMillimeters(double tonneforcemillimeters) } else { - return null; + return null; } } @@ -496,7 +535,7 @@ public static Torque FromTonneForceMillimeters(double tonneforcemillimeters) } else { - return null; + return null; } } @@ -511,7 +550,7 @@ public static Torque FromTonneForceMillimeters(double tonneforcemillimeters) } else { - return null; + return null; } } @@ -526,7 +565,7 @@ public static Torque FromTonneForceMillimeters(double tonneforcemillimeters) } else { - return null; + return null; } } @@ -541,7 +580,7 @@ public static Torque FromTonneForceMillimeters(double tonneforcemillimeters) } else { - return null; + return null; } } @@ -556,59 +595,61 @@ public static Torque FromTonneForceMillimeters(double tonneforcemillimeters) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// Torque unit value. - public static Torque From(double value, TorqueUnit fromUnit) + public static Torque From(double val, TorqueUnit fromUnit) { switch (fromUnit) { case TorqueUnit.KilogramForceCentimeter: - return FromKilogramForceCentimeters(value); + return FromKilogramForceCentimeters(val); case TorqueUnit.KilogramForceMeter: - return FromKilogramForceMeters(value); + return FromKilogramForceMeters(val); case TorqueUnit.KilogramForceMillimeter: - return FromKilogramForceMillimeters(value); + return FromKilogramForceMillimeters(val); case TorqueUnit.KilonewtonCentimeter: - return FromKilonewtonCentimeters(value); + return FromKilonewtonCentimeters(val); case TorqueUnit.KilonewtonMeter: - return FromKilonewtonMeters(value); + return FromKilonewtonMeters(val); case TorqueUnit.KilonewtonMillimeter: - return FromKilonewtonMillimeters(value); + return FromKilonewtonMillimeters(val); case TorqueUnit.KilopoundForceFoot: - return FromKilopoundForceFeet(value); + return FromKilopoundForceFeet(val); case TorqueUnit.KilopoundForceInch: - return FromKilopoundForceInches(value); + return FromKilopoundForceInches(val); case TorqueUnit.NewtonCentimeter: - return FromNewtonCentimeters(value); + return FromNewtonCentimeters(val); case TorqueUnit.NewtonMeter: - return FromNewtonMeters(value); + return FromNewtonMeters(val); case TorqueUnit.NewtonMillimeter: - return FromNewtonMillimeters(value); + return FromNewtonMillimeters(val); case TorqueUnit.PoundForceFoot: - return FromPoundForceFeet(value); + return FromPoundForceFeet(val); case TorqueUnit.PoundForceInch: - return FromPoundForceInches(value); + return FromPoundForceInches(val); case TorqueUnit.TonneForceCentimeter: - return FromTonneForceCentimeters(value); + return FromTonneForceCentimeters(val); case TorqueUnit.TonneForceMeter: - return FromTonneForceMeters(value); + return FromTonneForceMeters(val); case TorqueUnit.TonneForceMillimeter: - return FromTonneForceMillimeters(value); + return FromTonneForceMillimeters(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -660,6 +701,18 @@ public static Torque From(double value, TorqueUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(TorqueUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -668,7 +721,7 @@ public static Torque From(double value, TorqueUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(TorqueUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(TorqueUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -677,6 +730,7 @@ public static string GetAbbreviation(TorqueUnit unit, CultureInfo culture = null #region Arithmetic Operators +#if !WINDOWS_UWP public static Torque operator -(Torque right) { return new Torque(-right._newtonMeters); @@ -711,6 +765,7 @@ public static string GetAbbreviation(TorqueUnit unit, CultureInfo culture = null { return Convert.ToDouble(left._newtonMeters/right._newtonMeters); } +#endif #endregion @@ -723,11 +778,17 @@ public int CompareTo(object obj) return CompareTo((Torque) obj); } - public int CompareTo(Torque other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(Torque other) { return _newtonMeters.CompareTo(other._newtonMeters); } +#if !WINDOWS_UWP public static bool operator <=(Torque left, Torque right) { return left._newtonMeters <= right._newtonMeters; @@ -759,6 +820,7 @@ public int CompareTo(Torque other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._newtonMeters != right._newtonMeters; } +#endif public override bool Equals(object obj) { @@ -834,7 +896,6 @@ public double As(TorqueUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -853,10 +914,43 @@ public double As(TorqueUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static Torque Parse(string str, IFormatProvider formatProvider = null) + public static Torque Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static Torque Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -880,7 +974,7 @@ public static Torque Parse(string str, IFormatProvider formatProvider = null) "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => Torque.FromNewtonMeters(x.NewtonMeters + y.NewtonMeters)); } /// @@ -917,7 +1011,7 @@ private static List ParseWithRegex(string regexString, string str, IForm converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -942,18 +1036,49 @@ private static List ParseWithRegex(string regexString, string str, IForm /// /// The value of 'str' cannot be null. /// Error parsing string. - public static TorqueUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static TorqueUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static TorqueUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static TorqueUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == TorqueUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized TorqueUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -976,6 +1101,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(TorqueUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(TorqueUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -984,9 +1130,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(TorqueUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(TorqueUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -998,9 +1146,20 @@ public string ToString(TorqueUnit unit, CultureInfo culture = null, int signific /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(TorqueUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(TorqueUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/VitaminA.g.cs b/UnitsNet/GeneratedCode/UnitClasses/VitaminA.g.cs index f6871015ed..cee429d30b 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/VitaminA.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/VitaminA.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// Vitamin A: 1 IU is the biological equivalent of 0.3 μg retinol, or of 0.6 μg beta-carotene. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class VitaminA +#else public partial struct VitaminA : IComparable, IComparable +#endif { /// /// Base unit of VitaminA. /// private readonly double _internationalUnits; - public VitaminA(double internationalunits) : this() +#if WINDOWS_UWP + public VitaminA() : this(0) + { + } +#endif + + public VitaminA(double internationalunits) { - _internationalUnits = internationalunits; + _internationalUnits = Convert.ToDouble(internationalunits); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + VitaminA(long internationalunits) + { + _internationalUnits = Convert.ToDouble(internationalunits); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + VitaminA(decimal internationalunits) + { + _internationalUnits = Convert.ToDouble(internationalunits); } #region Properties @@ -79,7 +118,7 @@ public static VitaminA FromInternationalUnits(double internationalunits) return new VitaminA(internationalunits); } - +#if !WINDOWS_UWP /// /// Get nullable VitaminA from nullable InternationalUnits. /// @@ -91,29 +130,31 @@ public static VitaminA FromInternationalUnits(double internationalunits) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// VitaminA unit value. - public static VitaminA From(double value, VitaminAUnit fromUnit) + public static VitaminA From(double val, VitaminAUnit fromUnit) { switch (fromUnit) { case VitaminAUnit.InternationalUnit: - return FromInternationalUnits(value); + return FromInternationalUnits(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -135,6 +176,18 @@ public static VitaminA From(double value, VitaminAUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(VitaminAUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -143,7 +196,7 @@ public static VitaminA From(double value, VitaminAUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(VitaminAUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(VitaminAUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -152,6 +205,7 @@ public static string GetAbbreviation(VitaminAUnit unit, CultureInfo culture = nu #region Arithmetic Operators +#if !WINDOWS_UWP public static VitaminA operator -(VitaminA right) { return new VitaminA(-right._internationalUnits); @@ -186,6 +240,7 @@ public static string GetAbbreviation(VitaminAUnit unit, CultureInfo culture = nu { return Convert.ToDouble(left._internationalUnits/right._internationalUnits); } +#endif #endregion @@ -198,11 +253,17 @@ public int CompareTo(object obj) return CompareTo((VitaminA) obj); } - public int CompareTo(VitaminA other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(VitaminA other) { return _internationalUnits.CompareTo(other._internationalUnits); } +#if !WINDOWS_UWP public static bool operator <=(VitaminA left, VitaminA right) { return left._internationalUnits <= right._internationalUnits; @@ -234,6 +295,7 @@ public int CompareTo(VitaminA other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._internationalUnits != right._internationalUnits; } +#endif public override bool Equals(object obj) { @@ -279,7 +341,6 @@ public double As(VitaminAUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -298,10 +359,43 @@ public double As(VitaminAUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static VitaminA Parse(string str, IFormatProvider formatProvider = null) + public static VitaminA Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static VitaminA Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -325,7 +419,7 @@ public static VitaminA Parse(string str, IFormatProvider formatProvider = null) "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => VitaminA.FromInternationalUnits(x.InternationalUnits + y.InternationalUnits)); } /// @@ -362,7 +456,7 @@ private static List ParseWithRegex(string regexString, string str, IFo converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -387,18 +481,49 @@ private static List ParseWithRegex(string regexString, string str, IFo /// /// The value of 'str' cannot be null. /// Error parsing string. - public static VitaminAUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static VitaminAUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static VitaminAUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static VitaminAUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == VitaminAUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized VitaminAUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -421,6 +546,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(VitaminAUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(VitaminAUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -429,9 +575,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(VitaminAUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(VitaminAUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -443,9 +591,20 @@ public string ToString(VitaminAUnit unit, CultureInfo culture = null, int signif /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(VitaminAUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(VitaminAUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } diff --git a/UnitsNet/GeneratedCode/UnitClasses/Volume.g.cs b/UnitsNet/GeneratedCode/UnitClasses/Volume.g.cs index b62c528daa..28d5e4d23c 100644 --- a/UnitsNet/GeneratedCode/UnitClasses/Volume.g.cs +++ b/UnitsNet/GeneratedCode/UnitClasses/Volume.g.cs @@ -27,6 +27,12 @@ using JetBrains.Annotations; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture = System.String; +#else +using Culture = System.IFormatProvider; +#endif + // ReSharper disable once CheckNamespace namespace UnitsNet @@ -35,16 +41,49 @@ namespace UnitsNet /// Volume is the quantity of three-dimensional space enclosed by some closed boundary, for example, the space that a substance (solid, liquid, gas, or plasma) or shape occupies or contains.[1] Volume is often quantified numerically using the SI derived unit, the cubic metre. The volume of a container is generally understood to be the capacity of the container, i. e. the amount of fluid (gas or liquid) that the container could hold, rather than the amount of space the container itself displaces. /// // ReSharper disable once PartialTypeWithSinglePart +#if WINDOWS_UWP + public sealed partial class Volume +#else public partial struct Volume : IComparable, IComparable +#endif { /// /// Base unit of Volume. /// private readonly double _cubicMeters; - public Volume(double cubicmeters) : this() +#if WINDOWS_UWP + public Volume() : this(0) + { + } +#endif + + public Volume(double cubicmeters) { - _cubicMeters = cubicmeters; + _cubicMeters = Convert.ToDouble(cubicmeters); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Volume(long cubicmeters) + { + _cubicMeters = Convert.ToDouble(cubicmeters); + } + + // Method overloads and with same number of parameters not supported in Universal Windows Platform (WinRT Components). + // Decimal type not supported in Universal Windows Platform (WinRT Components). +#if WINDOWS_UWP + private +#else + public +#endif + Volume(decimal cubicmeters) + { + _cubicMeters = Convert.ToDouble(cubicmeters); } #region Properties @@ -545,7 +584,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) return new Volume(usteaspoons*4.92892159375e-6); } - +#if !WINDOWS_UWP /// /// Get nullable Volume from nullable AuTablespoons. /// @@ -557,7 +596,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -572,7 +611,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -587,7 +626,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -602,7 +641,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -617,7 +656,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -632,7 +671,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -647,7 +686,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -662,7 +701,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -677,7 +716,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -692,7 +731,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -707,7 +746,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -722,7 +761,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -737,7 +776,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -752,7 +791,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -767,7 +806,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -782,7 +821,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -797,7 +836,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -812,7 +851,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -827,7 +866,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -842,7 +881,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -857,7 +896,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -872,7 +911,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -887,7 +926,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -902,7 +941,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -917,7 +956,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -932,7 +971,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -947,7 +986,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -962,7 +1001,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -977,7 +1016,7 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } @@ -992,87 +1031,89 @@ public static Volume FromUsTeaspoons(double usteaspoons) } else { - return null; + return null; } } +#endif /// /// Dynamically convert from value and unit enum to . /// - /// Value to convert from. + /// Value to convert from. /// Unit to convert from. /// Volume unit value. - public static Volume From(double value, VolumeUnit fromUnit) + public static Volume From(double val, VolumeUnit fromUnit) { switch (fromUnit) { case VolumeUnit.AuTablespoon: - return FromAuTablespoons(value); + return FromAuTablespoons(val); case VolumeUnit.Centiliter: - return FromCentiliters(value); + return FromCentiliters(val); case VolumeUnit.CubicCentimeter: - return FromCubicCentimeters(value); + return FromCubicCentimeters(val); case VolumeUnit.CubicDecimeter: - return FromCubicDecimeters(value); + return FromCubicDecimeters(val); case VolumeUnit.CubicFoot: - return FromCubicFeet(value); + return FromCubicFeet(val); case VolumeUnit.CubicInch: - return FromCubicInches(value); + return FromCubicInches(val); case VolumeUnit.CubicKilometer: - return FromCubicKilometers(value); + return FromCubicKilometers(val); case VolumeUnit.CubicMeter: - return FromCubicMeters(value); + return FromCubicMeters(val); case VolumeUnit.CubicMicrometer: - return FromCubicMicrometers(value); + return FromCubicMicrometers(val); case VolumeUnit.CubicMile: - return FromCubicMiles(value); + return FromCubicMiles(val); case VolumeUnit.CubicMillimeter: - return FromCubicMillimeters(value); + return FromCubicMillimeters(val); case VolumeUnit.CubicYard: - return FromCubicYards(value); + return FromCubicYards(val); case VolumeUnit.Deciliter: - return FromDeciliters(value); + return FromDeciliters(val); case VolumeUnit.Hectoliter: - return FromHectoliters(value); + return FromHectoliters(val); case VolumeUnit.ImperialGallon: - return FromImperialGallons(value); + return FromImperialGallons(val); case VolumeUnit.ImperialOunce: - return FromImperialOunces(value); + return FromImperialOunces(val); case VolumeUnit.Liter: - return FromLiters(value); + return FromLiters(val); case VolumeUnit.MetricCup: - return FromMetricCups(value); + return FromMetricCups(val); case VolumeUnit.MetricTeaspoon: - return FromMetricTeaspoons(value); + return FromMetricTeaspoons(val); case VolumeUnit.Microliter: - return FromMicroliters(value); + return FromMicroliters(val); case VolumeUnit.Milliliter: - return FromMilliliters(value); + return FromMilliliters(val); case VolumeUnit.Tablespoon: - return FromTablespoons(value); + return FromTablespoons(val); case VolumeUnit.Teaspoon: - return FromTeaspoons(value); + return FromTeaspoons(val); case VolumeUnit.UkTablespoon: - return FromUkTablespoons(value); + return FromUkTablespoons(val); case VolumeUnit.UsCustomaryCup: - return FromUsCustomaryCups(value); + return FromUsCustomaryCups(val); case VolumeUnit.UsGallon: - return FromUsGallons(value); + return FromUsGallons(val); case VolumeUnit.UsLegalCup: - return FromUsLegalCups(value); + return FromUsLegalCups(val); case VolumeUnit.UsOunce: - return FromUsOunces(value); + return FromUsOunces(val); case VolumeUnit.UsTablespoon: - return FromUsTablespoons(value); + return FromUsTablespoons(val); case VolumeUnit.UsTeaspoon: - return FromUsTeaspoons(value); + return FromUsTeaspoons(val); default: throw new NotImplementedException("fromUnit: " + fromUnit); } } +#if !WINDOWS_UWP /// /// Dynamically convert from value and unit enum to . /// @@ -1152,6 +1193,18 @@ public static Volume From(double value, VolumeUnit fromUnit) throw new NotImplementedException("fromUnit: " + fromUnit); } } +#endif + + /// + /// Get unit abbreviation string. + /// + /// Unit to get abbreviation for. + /// Unit abbreviation string. + [UsedImplicitly] + public static string GetAbbreviation(VolumeUnit unit) + { + return GetAbbreviation(unit, null); + } /// /// Get unit abbreviation string. @@ -1160,7 +1213,7 @@ public static Volume From(double value, VolumeUnit fromUnit) /// Culture to use for localization. Defaults to Thread.CurrentUICulture. /// Unit abbreviation string. [UsedImplicitly] - public static string GetAbbreviation(VolumeUnit unit, CultureInfo culture = null) + public static string GetAbbreviation(VolumeUnit unit, [CanBeNull] Culture culture) { return UnitSystem.GetCached(culture).GetDefaultAbbreviation(unit); } @@ -1169,6 +1222,7 @@ public static string GetAbbreviation(VolumeUnit unit, CultureInfo culture = null #region Arithmetic Operators +#if !WINDOWS_UWP public static Volume operator -(Volume right) { return new Volume(-right._cubicMeters); @@ -1203,6 +1257,7 @@ public static string GetAbbreviation(VolumeUnit unit, CultureInfo culture = null { return Convert.ToDouble(left._cubicMeters/right._cubicMeters); } +#endif #endregion @@ -1215,11 +1270,17 @@ public int CompareTo(object obj) return CompareTo((Volume) obj); } - public int CompareTo(Volume other) +#if WINDOWS_UWP + internal +#else + public +#endif + int CompareTo(Volume other) { return _cubicMeters.CompareTo(other._cubicMeters); } +#if !WINDOWS_UWP public static bool operator <=(Volume left, Volume right) { return left._cubicMeters <= right._cubicMeters; @@ -1251,6 +1312,7 @@ public int CompareTo(Volume other) // ReSharper disable once CompareOfFloatsByEqualityOperator return left._cubicMeters != right._cubicMeters; } +#endif public override bool Equals(object obj) { @@ -1354,7 +1416,6 @@ public double As(VolumeUnit unit) /// Parse a string with one or two quantities of the format "<quantity> <unit>". /// /// String to parse. Typically in the form: {number} {unit} - /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. /// /// Length.Parse("5.5 m", new CultureInfo("en-US")); /// @@ -1373,10 +1434,43 @@ public double As(VolumeUnit unit) /// We wrap exceptions in to allow you to distinguish /// Units.NET exceptions from other exceptions. /// - public static Volume Parse(string str, IFormatProvider formatProvider = null) + public static Volume Parse(string str) + { + return Parse(str, null); + } + + /// + /// Parse a string with one or two quantities of the format "<quantity> <unit>". + /// + /// String to parse. Typically in the form: {number} {unit} + /// Format to use when parsing number and unit. If it is null, it defaults to for parsing the number and for parsing the unit abbreviation by culture/language. + /// + /// Length.Parse("5.5 m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// + /// Expected string to have one or two pairs of quantity and unit in the format + /// "<quantity> <unit>". Eg. "5.5 m" or "1ft 2in" + /// + /// + /// More than one unit is represented by the specified unit abbreviation. + /// Example: Volume.Parse("1 cup") will throw, because it can refer to any of + /// , and . + /// + /// + /// If anything else goes wrong, typically due to a bug or unhandled case. + /// We wrap exceptions in to allow you to distinguish + /// Units.NET exceptions from other exceptions. + /// + public static Volume Parse(string str, [CanBeNull] Culture culture) { if (str == null) throw new ArgumentNullException("str"); +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif var numFormat = formatProvider != null ? (NumberFormatInfo) formatProvider.GetFormat(typeof (NumberFormatInfo)) : NumberFormatInfo.CurrentInfo; @@ -1400,7 +1494,7 @@ public static Volume Parse(string str, IFormatProvider formatProvider = null) "Expected string to have at least one pair of quantity and unit in the format" + " \"<quantity> <unit>\". Eg. \"5.5 m\" or \"1ft 2in\""); } - return quantities.Aggregate((x, y) => x + y); + return quantities.Aggregate((x, y) => Volume.FromCubicMeters(x.CubicMeters + y.CubicMeters)); } /// @@ -1437,7 +1531,7 @@ private static List ParseWithRegex(string regexString, string str, IForm converted.Add(From(value, unit)); } - catch(AmbiguousUnitParseException ambiguousException) + catch(AmbiguousUnitParseException) { throw; } @@ -1462,18 +1556,49 @@ private static List ParseWithRegex(string regexString, string str, IForm /// /// The value of 'str' cannot be null. /// Error parsing string. - public static VolumeUnit ParseUnit(string str, IFormatProvider formatProvider = null) + public static VolumeUnit ParseUnit(string str) + { + return ParseUnit(str, (IFormatProvider)null); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. + public static VolumeUnit ParseUnit(string str, [CanBeNull] string cultureName) + { + return ParseUnit(str, cultureName == null ? null : new CultureInfo(cultureName)); + } + + /// + /// Parse a unit string. + /// + /// + /// Length.ParseUnit("m", new CultureInfo("en-US")); + /// + /// The value of 'str' cannot be null. + /// Error parsing string. +#if WINDOWS_UWP + internal +#else + public +#endif + static VolumeUnit ParseUnit(string str, IFormatProvider formatProvider = null) { if (str == null) throw new ArgumentNullException("str"); - var unitSystem = UnitSystem.GetCached(formatProvider); + var unitSystem = UnitSystem.GetCached(formatProvider); var unit = unitSystem.Parse(str.Trim()); if (unit == VolumeUnit.Undefined) { var newEx = new UnitsNetException("Error parsing string. The unit is not a recognized VolumeUnit."); newEx.Data["input"] = str; - newEx.Data["formatprovider"] = formatProvider == null ? null : formatProvider.ToString(); + newEx.Data["formatprovider"] = formatProvider?.ToString() ?? "(null)"; throw newEx; } @@ -1496,6 +1621,27 @@ public override string ToString() return ToString(ToStringDefaultUnit); } + /// + /// Get string representation of value and unit. Using current UI culture and two significant digits after radix. + /// + /// Unit representation to use. + /// String representation. + public string ToString(VolumeUnit unit) + { + return ToString(unit, null, 2); + } + + /// + /// Get string representation of value and unit. Using two significant digits after radix. + /// + /// Unit representation to use. + /// Culture to use for localization and number formatting. + /// String representation. + public string ToString(VolumeUnit unit, [CanBeNull] Culture culture) + { + return ToString(unit, culture, 2); + } + /// /// Get string representation of value and unit. /// @@ -1504,9 +1650,11 @@ public override string ToString() /// The number of significant digits after the radix point. /// String representation. [UsedImplicitly] - public string ToString(VolumeUnit unit, CultureInfo culture = null, int significantDigitsAfterRadix = 2) + public string ToString(VolumeUnit unit, [CanBeNull] Culture culture, int significantDigitsAfterRadix) { - return ToString(unit, culture, UnitFormatter.GetFormat(As(unit), significantDigitsAfterRadix)); + double value = As(unit); + string format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix); + return ToString(unit, culture, format); } /// @@ -1518,9 +1666,20 @@ public string ToString(VolumeUnit unit, CultureInfo culture = null, int signific /// Arguments for string format. Value and unit are implictly included as arguments 0 and 1. /// String representation. [UsedImplicitly] - public string ToString(VolumeUnit unit, CultureInfo culture, string format, params object[] args) - { - return string.Format(culture, format, UnitFormatter.GetFormatArgs(unit, As(unit), culture, args)); + public string ToString(VolumeUnit unit, [CanBeNull] Culture culture, [NotNull] string format, + [NotNull] params object[] args) + { + if (format == null) throw new ArgumentNullException(nameof(format)); + if (args == null) throw new ArgumentNullException(nameof(args)); + +#if WINDOWS_UWP + IFormatProvider formatProvider = culture == null ? null : new CultureInfo(culture); +#else + IFormatProvider formatProvider = culture; +#endif + double value = As(unit); + object[] formatArgs = UnitFormatter.GetFormatArgs(unit, value, formatProvider, args); + return string.Format(formatProvider, format, formatArgs); } } } From ce466a33161da8ca1cd958ec45f637bfd540a9e9 Mon Sep 17 00:00:00 2001 From: Andreas Gullberg Larsen Date: Sat, 9 Apr 2016 23:09:00 +0200 Subject: [PATCH 10/17] testapp: Add C# UWP app --- UnitsNet.TestApps.Uwp.Csharp/.gitignore | 1 + UnitsNet.TestApps.Uwp.Csharp/App.xaml | 8 + UnitsNet.TestApps.Uwp.Csharp/App.xaml.cs | 105 +++++++++++++ .../Assets/LockScreenLogo.scale-200.png | Bin 0 -> 1430 bytes .../Assets/SplashScreen.scale-200.png | Bin 0 -> 7700 bytes .../Assets/Square150x150Logo.scale-200.png | Bin 0 -> 2937 bytes .../Assets/Square44x44Logo.scale-200.png | Bin 0 -> 1647 bytes ...x44Logo.targetsize-24_altform-unplated.png | Bin 0 -> 1255 bytes .../Assets/StoreLogo.png | Bin 0 -> 1451 bytes .../Assets/Wide310x150Logo.scale-200.png | Bin 0 -> 3204 bytes UnitsNet.TestApps.Uwp.Csharp/MainPage.xaml | 13 ++ UnitsNet.TestApps.Uwp.Csharp/MainPage.xaml.cs | 32 ++++ .../Package.appxmanifest | 49 ++++++ .../Properties/AssemblyInfo.cs | 29 ++++ .../Properties/Default.rd.xml | 31 ++++ .../UnitsNet.TestApps.Uwp.Csharp.csproj | 141 ++++++++++++++++++ .../UnitsNet.TestApps.Uwp.Csharp.pfx | Bin 0 -> 2454 bytes UnitsNet.TestApps.Uwp.Csharp/project.json | 17 +++ 18 files changed, 426 insertions(+) create mode 100644 UnitsNet.TestApps.Uwp.Csharp/.gitignore create mode 100644 UnitsNet.TestApps.Uwp.Csharp/App.xaml create mode 100644 UnitsNet.TestApps.Uwp.Csharp/App.xaml.cs create mode 100644 UnitsNet.TestApps.Uwp.Csharp/Assets/LockScreenLogo.scale-200.png create mode 100644 UnitsNet.TestApps.Uwp.Csharp/Assets/SplashScreen.scale-200.png create mode 100644 UnitsNet.TestApps.Uwp.Csharp/Assets/Square150x150Logo.scale-200.png create mode 100644 UnitsNet.TestApps.Uwp.Csharp/Assets/Square44x44Logo.scale-200.png create mode 100644 UnitsNet.TestApps.Uwp.Csharp/Assets/Square44x44Logo.targetsize-24_altform-unplated.png create mode 100644 UnitsNet.TestApps.Uwp.Csharp/Assets/StoreLogo.png create mode 100644 UnitsNet.TestApps.Uwp.Csharp/Assets/Wide310x150Logo.scale-200.png create mode 100644 UnitsNet.TestApps.Uwp.Csharp/MainPage.xaml create mode 100644 UnitsNet.TestApps.Uwp.Csharp/MainPage.xaml.cs create mode 100644 UnitsNet.TestApps.Uwp.Csharp/Package.appxmanifest create mode 100644 UnitsNet.TestApps.Uwp.Csharp/Properties/AssemblyInfo.cs create mode 100644 UnitsNet.TestApps.Uwp.Csharp/Properties/Default.rd.xml create mode 100644 UnitsNet.TestApps.Uwp.Csharp/UnitsNet.TestApps.Uwp.Csharp.csproj create mode 100644 UnitsNet.TestApps.Uwp.Csharp/UnitsNet.TestApps.Uwp.Csharp.pfx create mode 100644 UnitsNet.TestApps.Uwp.Csharp/project.json diff --git a/UnitsNet.TestApps.Uwp.Csharp/.gitignore b/UnitsNet.TestApps.Uwp.Csharp/.gitignore new file mode 100644 index 0000000000..96382d195c --- /dev/null +++ b/UnitsNet.TestApps.Uwp.Csharp/.gitignore @@ -0,0 +1 @@ +/project.lock.json diff --git a/UnitsNet.TestApps.Uwp.Csharp/App.xaml b/UnitsNet.TestApps.Uwp.Csharp/App.xaml new file mode 100644 index 0000000000..b1c066daf0 --- /dev/null +++ b/UnitsNet.TestApps.Uwp.Csharp/App.xaml @@ -0,0 +1,8 @@ + + + diff --git a/UnitsNet.TestApps.Uwp.Csharp/App.xaml.cs b/UnitsNet.TestApps.Uwp.Csharp/App.xaml.cs new file mode 100644 index 0000000000..1fba308c44 --- /dev/null +++ b/UnitsNet.TestApps.Uwp.Csharp/App.xaml.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Windows.ApplicationModel; +using Windows.ApplicationModel.Activation; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Navigation; + +namespace UWP +{ + /// + /// Provides application-specific behavior to supplement the default Application class. + /// + sealed partial class App : Application + { + /// + /// Initializes the singleton application object. This is the first line of authored code + /// executed, and as such is the logical equivalent of main() or WinMain(). + /// + public App() + { + this.InitializeComponent(); + this.Suspending += OnSuspending; + } + + /// + /// Invoked when the application is launched normally by the end user. Other entry points + /// will be used such as when the application is launched to open a specific file. + /// + /// Details about the launch request and process. + protected override void OnLaunched(LaunchActivatedEventArgs e) + { + +#if DEBUG + if (System.Diagnostics.Debugger.IsAttached) + { + this.DebugSettings.EnableFrameRateCounter = true; + } +#endif + + Frame rootFrame = Window.Current.Content as Frame; + + // Do not repeat app initialization when the Window already has content, + // just ensure that the window is active + if (rootFrame == null) + { + // Create a Frame to act as the navigation context and navigate to the first page + rootFrame = new Frame(); + + rootFrame.NavigationFailed += OnNavigationFailed; + + if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) + { + //TODO: Load state from previously suspended application + } + + // Place the frame in the current Window + Window.Current.Content = rootFrame; + } + + if (rootFrame.Content == null) + { + // When the navigation stack isn't restored navigate to the first page, + // configuring the new page by passing required information as a navigation + // parameter + rootFrame.Navigate(typeof(MainPage), e.Arguments); + } + // Ensure the current window is active + Window.Current.Activate(); + } + + /// + /// Invoked when Navigation to a certain page fails + /// + /// The Frame which failed navigation + /// Details about the navigation failure + void OnNavigationFailed(object sender, NavigationFailedEventArgs e) + { + throw new Exception("Failed to load Page " + e.SourcePageType.FullName); + } + + /// + /// Invoked when application execution is being suspended. Application state is saved + /// without knowing whether the application will be terminated or resumed with the contents + /// of memory still intact. + /// + /// The source of the suspend request. + /// Details about the suspend request. + private void OnSuspending(object sender, SuspendingEventArgs e) + { + var deferral = e.SuspendingOperation.GetDeferral(); + //TODO: Save application state and stop any background activity + deferral.Complete(); + } + } +} diff --git a/UnitsNet.TestApps.Uwp.Csharp/Assets/LockScreenLogo.scale-200.png b/UnitsNet.TestApps.Uwp.Csharp/Assets/LockScreenLogo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..735f57adb5dfc01886d137b4e493d7e97cf13af3 GIT binary patch literal 1430 zcmaJ>TTC2P7~aKltDttVHYH6u8Io4i*}3fO&d$gd*bA_<3j~&e7%8(eXJLfhS!M@! zKrliY>>6yT4+Kr95$!DoD(Qn-5TP|{V_KS`k~E6(LGS@#`v$hQo&^^BKsw3HIsZBT z_y6C2n`lK@apunKojRQ^(_P}Mgewt$(^BBKCTZ;*xa?J3wQ7~@S0lUvbcLeq1Bg4o zH-bvQi|wt~L7q$~a-gDFP!{&TQfc3fX*6=uHv* zT&1&U(-)L%Xp^djI2?~eBF2cxC@YOP$+9d?P&h?lPy-9M2UT9fg5jKm1t$m#iWE{M zIf%q9@;fyT?0UP>tcw-bLkz;s2LlKl2qeP0w zECS7Ate+Awk|KQ+DOk;fl}Xsy4o^CY=pwq%QAAKKl628_yNPsK>?A>%D8fQG6IgdJ ztnxttBz#NI_a@fk7SU`WtrpsfZsNs9^0(2a z@C3#YO3>k~w7?2hipBf{#b6`}Xw1hlG$yi?;1dDs7k~xDAw@jiI*+tc;t2Lflg&bM)0!Y;0_@=w%`LW^8DsYpS#-bLOklX9r?Ei}TScw|4DbpW%+7 zFgAI)f51s}{y-eWb|vrU-Ya!GuYKP)J7z#*V_k^Xo>4!1Yqj*m)x&0L^tg3GJbVAJ zJ-Pl$R=NAabouV=^z_t;^K*0AvFs!vYU>_<|I^#c?>>CR<(T?=%{;U=aI*SbZADLH z&(f2wz_Y0??Tf|g;?|1Znw6}6U43Q#qNRwv1vp9uFn1)V#*4p&%$mP9x&15^OaBiDS(XppT|z^>;B{PLVEbS3IFYV yGvCsSX*m literal 0 HcmV?d00001 diff --git a/UnitsNet.TestApps.Uwp.Csharp/Assets/SplashScreen.scale-200.png b/UnitsNet.TestApps.Uwp.Csharp/Assets/SplashScreen.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..023e7f1feda78d5100569825acedfd213a0d84e9 GIT binary patch literal 7700 zcmeHLYj~4Yw%(;oxoEH#Kxq-eR|+VkP17b#Vk;?4QwkI+A{L04G+#<<(x#Un1#+h5>eArRq zTw$)ZvTWW_Y?bDho0nPVTh08+s`sp!j74rJTTtXIDww0SILedFv?sZ?yb@@}GN;#8 znk_b~Q(A0YR#uV4ef!osoV1M3;vQ8N$O|fStfgf$S5;ddUNv`tWtGjM;koG#N;7M< zP*84lnx(bn_KF&9Z5Ai$)#Cs3a|$OFw>WKCT$of*L7_CqQEinflT|W{JT+aKp-E0v zsxmYg)1(T>DROm+LN1eQw8}KCTp=C!$H7`PU!t9_Hw@TsTI2`udRZv*!a5`#A9hK6Y95L(CDUX&_@QxKV z_feX{UhA#ZWlvgpL$#w^D#lq`_A4AzDqd|Zv6y9PX&DNcN|l}_D^{q@GG&H^Pg583 z8FI6N8^H7b5WjGp;urW)d7F+_lcp%KsLX0viCmE(OHH+=%ZfD_=`voUuoUxFO^L;- z;!;2{g-YiiO6m4bs89OuF9!p{FGtH-f%8<2gY!h9s)4ciN%{Kh1+`}{^}M~+TDH9N z^Z5PlgVXMC&2&k*Hw^Lb9gny#ro$MOIxIt{+r)EA10$VR3 zanN8D{TUkl+v0CQ_>ZoHP<M-x#8@8ZiT#$Kh`(uRaX1g$Bg|qy$<#7 zSSAi{Nb8Y=lvNVeio+UGLCAtoLBfL`iOv`)yoJMDJBN>4IH@(l7YRF;61@>qq1iM9 zr@b#OC~SAxSle?5Pp8Z78{VO0YFr1x7kZU64Z23eLf2T2#6J_t;-E}DkB?NufZ0Ug zi?J&byXeaB-uTNVhuiM!UVQw}bZrJ3GtAETYp->!{q#zfN7D3AS9@Q7*V^85jGx#R z(QxYV(wW#F0XF9^^s>>H8pPlVJ>)3Oz z&_X8Sf@~?cH_O*cgi$U#`v`RRfv#y3m(ZpKk^5uLup+lVs$~}FZU$r_+}#hl%?g5m z-u-}-666ssp-xWQak~>PPy$mRc|~?pVSs1_@mBEXpPVfLF6(Ktf1S* zPPh@QZ=tFMs?LM2(5P3L2;l_6XX6s&cYsP1ip#eg0`ZEP0HGYh{UmS@o`MihLLvkU zgyAG0G`b1|qjxxh1(ODKFE%AP}Dq=3vK$P7TXP4GrM1kQ72!GUVMDl`rDC&2;TA}*nF z8$nQD&6ys_nc1*E7$*1S@R8$ymy(sQV}imGSedB@{!QR5P&N_H=-^o!?LsWs+2|mH z-e=)T^SvI)=_JIm7}j4;@*Z17=(#}m=~YF~z~CLI+vdAGlJDcdF$TM?CVI1%LhUrN zaa6DJ=Yh$)$k&Oz{-~8yw^GM^8prYxSxo zvI4k#ibryMa%%*8oI-5m61Koa_A_xg=(fwp0aBX{;X4Q;NXUhtaoJDo1>TqhWtn=_ zd5~chq#&6~c%8JZK#t_&J(9EVUU&upYeIovLt1>vaHe}UUq>#RGQj!EN#5+0@T`(@ z^g~>*c`VGRiSt;!$_4+0hk^I!@O3``5=sZ8IwlxWW7km1B&_t&E*u0_9UBa#VqwY* zz>nxv?FAsVnRaD(Bui=6i==BFUw0k4n$>`umU`F2l?7CYTD^)c2X+d9X&ddS9|gj? zM?knGkGCX&W8offw8aLC2$D{PjC3nVZwd4k?eZH8*mZ)U@3Qk8RDFOz_#WUA#vnzy zyP>KrCfKwSXea7}jgJjBc}PGY+4#6%lbZyjhy`5sZd_Vy6Wz;ixa?czkN}J9It1K6 zY!eu>|AwF^fwZlLAYyQI*lM@^>O>Iu6Vf6i>Q$?v!SeUS<{>UYMwz$*%Aq?w^`j{h z!$GZbhu=^D{&ET8;))LL%ZBDZkQqRd2;u~!d9bHGmLRhLDctNgYyjsuvoSZ#iVdoB z2!f--UUA#U;<{je#?cYt^{PIyKa%hW>}uepWMyAI{{Zo7?2>?$c9;whJae%oN|I-kpTQSx_C$Z&;f zi2i)qmEn=y4U0uvk)$m;zKfjPK@oc?I`}1Jzl$Q~aoKBd3kt7L#7gyt|A_qgz6ai< z=X%D1i!d2h?rHR^R8SUj&G||dkC?DT>{o#Yau<@uqVT{Xef&XG}5*E4aPk{}~ zplx&XhaV)&1EfI3Em;Bw#O5SV^c;{twb-1Rw)+=0!e_BLbd7tYmXCH0wrlOSS+~`7He8Iqx0{CN+DVit9;*6L~JAN zD&cyT)2?h}xnYmL?^)<7YyzZ3$FHU^Eg;DLqAV{#wv#Wj7S`Jdl1pX&{3(uZ?!uh} zDc$ZTNV*7le_W6}Hju~GMTxZQ1aWCeUc%!jv3MHAzt>Y-nQK%zfT*3ebDQA5b?iGn; zBjv3B+GhLTexd_(CzZDP4|#n5^~scvB6#Pk%Ho!kQ>yYw((Dv{6=$g3jT1!u6gORW zx5#`7Wy-ZHRa~IxGHdrp(bm%lf>2%J660nj$fCqN(epv@y!l9s7@k6EvxS{AMP>WY zX4$@F8^kayphIx-RGO$+LYl9YdoI5d|4#q9##`_F5Xnx`&GPzp2fB{-{P@ATw=X@~ z_|&^UMWAKD;jjBKTK(~o?cUFRK8EX=6>cXpfzg4ZpMB>*w_^8GSiT-Jp|xBOnzM+j z*09-@-~qJ(eqWq5@R4i^u4^{McCP(!3}C|v_WsTR*bIUxN(Nx`u##3B4{sE`Z`v8w zAwIG`?1~PkID~W{uDzmqH98Pew_1(;x2%8r^vY{)_&J2K)cN{W+h5+g)ZcjP&Ci#O zgy|8K@4kyMfwilHd&6TDlhb%++Pk!>9HRld6HT7gwyZGrxS$}CsD6`>6!!2K1@Mjf z(P0WYB7V_OFZyeWrbOFb>O54BNXf~K&?}3=^v;v_wT{DKr?jN^DtN&DXwX%u?s*c6`%8>WFz z7}YW^tp0bp^NriE)AB6M2l<7rn7fzePtR*omOevpfm9n?}2V*+0iW;S)C zhg`NAjL?D=W#k*$aR{>pGf~lD-rVtD;5jW1_*Jn1j1=es@Kcx4ySM_bwcQCT=d+DV z>Sz~L=Hj@(X%31nK$mWI@7d>}ORB`K(p=+`UD)+99YUGQc7y^bHZ1F(8|tL0 zdK*DT0kSXG_{BKTpP2*2PecdKV9;dq$^ZZDP;Nyq1kp-&GI5eAyZsK!e3V zK@rPy*{(`KIfo+lc878mDKk^V#`VT05}64kBtk%DgwLrOvLMj5-;*GNKv6c6pzMuL z6EP%ob|_0IW}lLRXCP2!9wWhEw3LA7iF#1O1mIZ@Z=6&bz41F;@S_GvYAG-#CW3z{ zP3+6vHhvP&A3$##Vo9$dT^#MoGg^|MDm=Bt1d2RRwSZ<;ZHICpLBv5Xs!D?BH^(9_ z7`H=N&^v|Z-%mP}wNzG{aiFCsRgwzwq!N6obW9+7(R; z(SZ=23`|`>qil!LMGG{_Heq!BD>(Y-zV9wD)}hz25JA37YR%39;kI4y9pgtcUass6 zP24}ZY$vvYeI`zy&)A_X#nY3017ap*0&jx|mVwyGhg3;!keU53a}Uhm3BZI$N$6Se zLWlAmy1S0xKJm4G_U@sN_Tm=`$xWJSEwKU98rZ&)1R^*$$1vA3oG#&*%SMxY_~oGP zP&PFJatFLM-Ps%84IV-+Ow)T{C7cqUAvauy4C z(FRz&?6$Rypj{xO!`y=*J5o4@U8Q-(y5(*=YoKeZ+-1YdljXxkA#B)zo=FeQH#?Le zycNUmEEHWO9a=X^pb#&cOq7-`7UA87#|S22)<7RUtZo|(zibX=w;K3qur9vy#`MNV z6UUcf9ZwEnKCCp+OoBnF@OdbvH)ANXO0o~Pi9l8=x3))}L<#vO0-~O4!~--Ket?d} zJaqsj<@CD1%S2cTW%rOP{Vto%0sGW~1RMa_j^)5nil0Yw- z0EE#bP+l4#P^%PQ+N*oxu1Zq05xZ!bXfYTg>9c{(Iw*lnjR^>kz%lAN^zFce7rppy zY8zA~3GD=A6d*hze&l4D_wA~+O!56)BZTe_rEu}Ezi<4!kG|W#amBZ5{&XS2@6R~H z{9o^y*BkH4$~yX9U&@CgbOzX1bn9xqF|zh$Dh0Y5y*E0e90*$!ObrHY3Ok0`2=O~r zCuke6KrP9KOf?V(YDsM<6pX2nVoN%M$LT^q#FmtaF?1^27F*IcNX~XRB(|hCFvdcc zc)$=S-)acdk$g4?_>jRqxpI6M3vHZk?0c^3=byamYDNf;uB{3NlKW5IhnOS3DNkMV z?tK8?kJ}pmvp%&&eTVOVjHP`q34hN1@!aK}H(K!vI`~gf|Gv+FNEQD5Yd<~yX7k_l h&G-K)@HZb3BABY{)U1?^%I#E6`MGoTtustd{~yM6srvu` literal 0 HcmV?d00001 diff --git a/UnitsNet.TestApps.Uwp.Csharp/Assets/Square150x150Logo.scale-200.png b/UnitsNet.TestApps.Uwp.Csharp/Assets/Square150x150Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..af49fec1a5484db1d52a7f9b5ec90a27c7030186 GIT binary patch literal 2937 zcma)84OCO-8BSud5)jwMLRVKgX(S?$n?Ld|vrsm<$CF7)&zTbyy1FE5bU`Q17MRv`9ue$;R(@8kR;#vJ*IM0>cJIAOte!d7oRgdH zd%ySjdB6L9=gX^A6)VzH7p2l@v~3zJAMw|DFy#^)F@@F*`mqUn=Il>l)8_+ab;nOW{%+iPx z+s{Eu|&pIs)Z7{La9~?xKfyl z#43?gjEL15d4WbOZo#SiP%>DB^+BcnJ=7dHEe;r#G=tuw|ka z%q@}##Uh7;tc%L_64m(kHtw74ty%BJMb)_1)#S0j`)F8_1jF7vScpsnH=0V19bO8y zR`0SjIdCUo&=>JwMQF8KHA<{ODHTiQh}0^@5QRmCA?gOH6_H3K^-_sNB^RrdNuK-R zOO*vOrKCVvDwgUck`kF(E7j{I#iiN;b*ZdCt4m@HPA`EuEqGGf4%!K<;(=I=&Vyrw z%TwcWtxa}8mCZ%Cyf&ActJ6_$ox5z6-D!0-dvnRx6t7y3d+h6QYpKWO;8OdnvERo7 zuEf>ih5`wqY)~o@OeVt-wM?Q!>QzdGRj!bz6fzYrfw$hZfAKzr2-M+D+R>}~oT574c;_3zquHcElqKIsryILt3g8n3jcMb+j?i?-L3FpZJ z2WRVBRdDPc+G5aaYg#5hpE+6nQ|(VSoxT3|biF;BUq#==-27Xi=gihDPYP$7?=9cP zYKE$jeQ|3~_L0VG-(F~2ZPyD0=k{J4Q~h(t__{-mz_w8{JDY9{`1ouzz!Vr5!ECdE z6U~O1k8c}24V7~zzXWTV-Pe4)y}wQJS&q%H5`Fo_f_JvIU489aCX$;P`u#!I-=^4ijC2{&9!O&h>mi?9oYD=GC#%)6{GzN6nQYw+Fal50!#x^asjBBR50i`+mho*ttoqV)ubM2KD9S~k7+FR4>{29?6 z{!l6kDdyTN0YJ9LgkPWeXm|gyi@zM3?0@{&pXT12w|78&W-q!RRF)&iLCEZVH<|fR zN0fr2^t8H(>L?>K#>^+jWROLral(Qy-xoBq1U7A&DV||wClb)Otd9?(gZ|8znMF}D zf<1haWz^s0qgecz;RFGt0C-B4g`jNGHsFU+;{<%t65v^sjk^h$lmWn#B0#_)9ij&d z-~lc`A)YYExi^7sBuPM^Y|wA2g*5?`K?#7tzELQYNxGo$UB$4J8RJp1k(8Jj+~hMT zlN~>M@KTTh^--8y3PK_NZ@AC!{PT=CziBzGd+wTJ^@icH!Bd}%)g8V)%K?|c&WTUk zy}qv1C%(fjRoZ4ozC3{O%@5?)XzH35zHns$pgU*Q?fj4v?fp1Qbm+j;3l;9jam9Da zXVcKjPlQ73x78QPu|Ffm6x?`~e3oD=gl=4kYK?={kD5j~QCXU)`HSdduNNENzA*2$ zOm3PzF!lN5e*06-f1Uot67wY#{o-S1!KZ7E=!~7ynnk9_iJR#kFoNbAOT#^2Gd17F zMmvU6>lndZQGd|ax9kUoXXO+$N?|j@6qpsF&_j7YXvwo_C{JpmLw5&#e6k>atv%es z5)7r*Wvv_JkUpT}M!_o!nVlEk1Zbl=a*2hQ*<|%*K1Glj^FcF`6kTzGQ3lz~2tCc@ z&x|tj;aH&1&9HwcJBcT`;{?a+pnej;M1HO(6Z{#J!cZA04hnFl;NXA+&`=7bjW_^o zfC40u3LMG?NdPtwGl>Tq6u}*QG)}-y;)lu-_>ee3kibW(69n0$0Zy!}9rQz%*v1iO zT9_H>99yIrSPYVy6^);rR}7Yo=J_T@hi+qhTZXnVWyf;JDYm5#eYLTxr*?kiNn!+Y zQ+LUkBafNJ#rH#C(?d5^;gw9o#%daEI{mA*LHPIHPU`#|H$hD zwm>0&+kahQ)E#%~k>&5@&#Vg82H?s%71=)(soi@174pi9--2{w{1$}Sz4zGn3Du&x bht0Iza^2ykEt4(epJ78uh5nDlX8(TxzDYwP literal 0 HcmV?d00001 diff --git a/UnitsNet.TestApps.Uwp.Csharp/Assets/Square44x44Logo.scale-200.png b/UnitsNet.TestApps.Uwp.Csharp/Assets/Square44x44Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..ce342a2ec8a61291ba76c54604aea7e9d20af11b GIT binary patch literal 1647 zcmaJ?eM}Q)7(e+G1Q(|`V9JhTI2>MkceK4;p;PR&$Pi?ejk3YQ_3o`S&|W_dsOZ8# zWPTt69g`t$ab`0cj-Y0yiBSOqmd)tG7G(}M5aP0_%&9TijB#&)I{zSE^4@#z^FF`l z`8{8`o%wlL(UI|y2!cdsuVamHH~H86F!*-15em4)NqUpCQM5?aoC_eCf@lV4wvF2a zjDQn1JBL69f&@2M3rvzJcfE!eZ8FZUBlFlC5RD)it33{mF9#B82AiyQE%w)`vlwa> zv{<1sm&kSKK$&%2jSFn7$t&P%%6Ue>R=EAnG8N7fqynWG8L3p!4801a;8{+nliO(qd(jNJ_?+9W3#hLIDLoT6~3fx9=`CC-D}-AMrpEO7HK zt3$GicGPc?GmDjy7K2P@La;eu4!$zWCZ`ym{Z$b zu-O6RM&K4JT|BIZB`E-gxqG%FzanI#+2FFmqHqXG7yxWB=w55RGOM)$xMb(>kSNR z2w=1AZi%z=AmG~yea~XaXJR!v7vLn(RUnELfiB1|6D84ICOS}^Zo2AdN}<&*h}G_u z{xZ!(%>tLT3J3<5XhWy-tg+6)0nmUUENLW8TWA{R6bgVd3X;anYFZ^IRis*_P-C-r z;i>%1^eL3UI2-{w8nuFFcs0e~7J{O2k^~Ce%+Ly4U?|=!0LH=t6()xi<^I-rs+9sF z*q{E-CxZbGPeu#a;XJwE;9S1?#R&uns>^0G3p`hEUF*v`M?@h%T%J%RChmD|EVydq zmHWh*_=S%emRC*mhxaVLzT@>Z2SX0u9v*DIJ@WC^kLVdlGV6LpK$KIrlJqc zpJ921)+3JJdTx|<`G&kXpKkjGJv=76R`yYIQ{#c-`%+`#V(7}Q;&@6U8!Td1`d;?N z_9mnI#?AA}4J!r)LN4!E-@H5eXauuB7TOawS>Y|{-P?NNx-lq+z1W-+y(;39P&&LP zL{N80?&=C*qKmdA^moMZRuPcD!B<*mq$ch=0Cnlitw#txRWhb3%TQvPqjkC`F69G4b! ze7z9MZ#+;_#l?H37UqUhDFb^l&s2{oM$3I0o^Q!yx;;V)QmCMo)Tb_ui|mit8MS?U zm##6$sZZ1$@|s%?l@>4Z<*Q}sRBSKMhb4I{e5LdEhsHIHTe8Bod5c>6QtT>$XgUBz z6MK`kO$=jmt@FqggOhJ5j~e@ygRbG;<{Vu)*+nn9aQeo0;$#j;|MS=S$&L?BeV25z xs3B`@=#`5TF{^6(A1rvdY@|-RtQ|iS5{tyX+wH?;n8E)G$kykv-D^wh{{!TZT%7;_ literal 0 HcmV?d00001 diff --git a/UnitsNet.TestApps.Uwp.Csharp/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/UnitsNet.TestApps.Uwp.Csharp/Assets/Square44x44Logo.targetsize-24_altform-unplated.png new file mode 100644 index 0000000000000000000000000000000000000000..f6c02ce97e0a802b85f6021e822c89f8bf57d5cd GIT binary patch literal 1255 zcmaJ>TWs4@7*5+{G#S+&C!qC#> zf>5N3P6jO*Cz>ug*(_DmW=)kea&m$gZ^+nyiF`;j%w@}y8)>p*SH}C`m?DXeieF2U zyQHecc_L%Gh!7GMt+hG06y;+|p4>m~}PjA}rKViGiEnn7G0ZO<>G|7q;2?NwGCM3s?eued6%hd$B+ z*kQJ{#~$S=DFE(%=E+UkmlEI*%3llUf~8Ja9YU1Vui0IbGBkW_gHB%Rd&!!ioX zs40O?i9I{};kle7GMvE7(rk`la=gTI)47=>%?q@^iL-nUo3}h4S}N-KHn8t5mVP8w z&bSErwp+37 zNJJ8?a|{r5Q3R0Z5s-LB1WHOwYC@7pCHWND#cL1cZ?{kJ368_*(UDWUDyb<}0y@o# zfMF016iMWPCb6obAxT$JlB6(2DrlXDTB&!0`!m??4F(qWMhjVZo?JXQmz`1*58Z=& zcDmB|S-E@j?BoFGix0flckqdS4jsPNzhfWyWIM98GxcLs89C(~dw%$_t;JjX-SD}E zfiGV;{8Q%8r}w9x>EEigW81>`kvnU@pK)4+xk9@+bNj9L!AAZ@SZ@q|)&BmY3+HZx zul~BeG4|}-;L%cHViQGQX?^zFfO0&#cHwel=d`lH9sJ-@Sl@n*(8J2>%Ac`IxyY?Q z{=GhWvC#gu-~Ia7*n{=+;qM?Ul_wy1+u7ho;=`>EwP^g~R@{unBds`!#@}tluZQpS zm)M~nYEifJWJGx?_6DcTy>#uh%>!H9=hb^(v`=m3F1{L>db=<5_tm+_&knAQ2EU$s Mu9UqpbNZeC0BbUo^Z)<= literal 0 HcmV?d00001 diff --git a/UnitsNet.TestApps.Uwp.Csharp/Assets/StoreLogo.png b/UnitsNet.TestApps.Uwp.Csharp/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..7385b56c0e4d3c6b0efe3324aa1194157d837826 GIT binary patch literal 1451 zcmaJ>eN5D57_Z|bH;{0+1#mbl)eTU3{h)Wf7EZV?;HD@XL@{B`Ui%(2aMxQ~xdXSv z5nzWi(LW)U2=Vc-cY@s7nPt{i0hc6!7xN4NNHI#EQl>YNBy8l4%x9gr_W-j zEZMQmmTIy(>;lblRfh`dIyTgc9W5d!VP$L4(kKrN1c5G~(O_#xG zAJCNTstD^5SeXFB+&$h=ToJP2H>xr$iqPs-#O*;4(!Fjw25-!gEb*)mU}=)J;Iu>w zxK(5XoD0wrPSKQ~rbL^Cw6O_03*l*}i=ydbu7adJ6y;%@tjFeXIXT+ms30pmbOP%Q zX}S;+LBh8Tea~TSkHzvX6$rYb)+n&{kSbIqh|c7hmlxmwSiq5iVhU#iEQ<>a18|O^Sln-8t&+t`*{qBWo5M?wFM(JuimAOb5!K#D}XbslM@#1ZVz_;!9U zpfEpLAOz=0g@bd6Xj_ILi-x^!M}73h^o@}hM$1jflTs|Yuj9AL@A3<-?MV4!^4q`e z)fO@A;{9K^?W?DbnesnPr6kK>$zaKo&;FhFd(GYFCIU^T+OIMb%Tqo+P%oq(IdX7S zf6+HLO?7o0m+p>~Tp5UrXWh!UH!wZ5kv!E`_w)PTpI(#Iw{AS`gH4^b(bm^ZCq^FZ zY9DD7bH}rq9mg88+KgA$Zp!iWncuU2n1AuIa@=sWvUR-s`Qb{R*kk(SPU^`$6BXz8 zn#7yaFOIK%qGxyi`dYtm#&qqox0$h=pNi#u=M8zUG@bpiZ=3sT=1}Trr}39cC)H|v zbL?W)=&s4zrh)7>L(|cc%$1#!zfL?HjpeP%T+x_a+jZ16b^iKOHxFEX$7d|8${H-* zIrOJ5w&i$>*D>AKaIoYg`;{L@jM((Kt?$N$5OnuPqVvq**Nm}(f0wwOF%iX_Pba;V z;m@wxX&NcV3?<1+u?A{y_DIj7#m3Af1rCE)o`D&Y3}0%7E;iX1yMDiS)sh0wKi!36 zL!Wmq?P^Ku&rK~HJd97KkLTRl>ScGFYZNlYytWnhmuu|)L&ND8_PmkayQb{HOY640 bno1(wj@u8DCVuFR|31B*4ek@pZJqxCDDe1x literal 0 HcmV?d00001 diff --git a/UnitsNet.TestApps.Uwp.Csharp/Assets/Wide310x150Logo.scale-200.png b/UnitsNet.TestApps.Uwp.Csharp/Assets/Wide310x150Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..288995b397fdbef1fb7e85afd71445d5de1952c5 GIT binary patch literal 3204 zcmbVPeQXow8NYmBd90>}0NP?GhXW~VaeThm=a0tV#EwJMI!)6M3}|c4_Bl3=Kd>G0 z(GHx1wl<7(tP?FsOQkTilSo*iIvF%uArExJ73~P zSv1xEy!U(Wd4A9D`FQV@W3@F^qJ@PEF$@z`Z!*BbFsS(^?B zyiAzJ+q})bkgiQHWqEb*jJD-coHYr1^iocg)l!Qa{Xqs-l~6J}p-|##ZHYofskQ3$ zI0;xzXyhazBeXhIsg5A=%ufo@f)1yy&ScKS0;HF^!r_2UE^lpZEom(+@duma3awTv zCrCL-%D_SvYWIcdHkmI}#50(fkUi)Qgx!80ju>g1za^}ff>JI8Z@^-iCiaCgg@TgF z+vtE?Q9{VQUX&MW9SYYmGcxA14%N2@7FwBTD4N<(2{nWgV8$e3?-F=L^&FrtWn~(U_Q~~^uYiyeY6-KoTnfh9AWz@ zIKje0)u!_Lw)E}G!#kEfwKVdNt(UAf9*f>tEL_(=xco-T%jTi@7YlC3hs2ik%Le0H ztj}RTeCF(5mwvi3_56>-yB?l;J>-1%!9~=fs|QcNG3J~a@JCu`4SB460s0ZO+##4fFUSGLcj_ja^fL4&BKALfb#$6$O?>P@qx2Agl^x0i&ugt zsy5Pyu=()`7HRMG3IB7F1@`_ z+-!J%#i6e^U$e#+C%Q>_qVRzWRsG^W_n+@OcX@vzI&z;mzHNb!GQ?LWA(wtpqHqTM z1OFw_{Zn?fD)p)`c`kOgv{de=v@suGRqY{N^U7gI1VF3*F=obwaXI6ob5__Yn zVTguS!%(NI09J8x#AO_aW!9W7k*UvB;IWDFC3srwftr{kHj%g)fvnAm;&h_dnl~

MY- zf+K}sCe8qU6Ujs`3ua{U0Of$R_gVQBuUA za0v=mu#vIOqiiAZOr&h*$WyOw&k-xr$;G4Ixa!#TJNr>95(h>l%)PUy4p+^SgR(uR zta%k*?ny-+nAr8spEk1fo{J4i!b^Fia`N{_F6@zidA2ZTTrjl#^5Z-2KfB@Cu}l9s z(*|Z2jc?p~vn2f)3y9i*7zJV1L{$?|&q)4oaT;uXi6>1GkRXVTOzAz(RHEmr=eFIi z`}<>-Q?K0GN8!IYxeP1XKXO+jsJbp~o^);Bc;%b7Flpe7;1`Ny@3r7ZR;?R)aJt8C ziNlEC<@3f_lIV4TwV}&e;D!Ee5_|e#g0LUh=5vmYWYm7&2h*M>QPKvGh9-)wfMMW3 z8J9b%1k7dzPzO0_NGQy92BZ^FR6R~6;^6?lqO;-QUP4BY%cG%3vEhbm#>4vIhPBh3 z-+pZGjh$x%Hp{?=FHsMp0&wNPlj00us{&`1ZOZTqs8%4X&xH=UDr*xyBW(Zp&Em94 zf)ZSfn#yg0N)>!1kWdkqJ^S*z0FF5|fj&qcE#Na|%OY0$uO>!&hP+1ywfD_WXk@4J(?MBftK7>$Nvqh@tDuarN%PrTLQ2Uzysx>UV=V zk^RrDSvdQ?0;=hY67EgII-f4`t=+i*yS=Y~!XlqIy_4x&%+OdfbKOFPXS2X5%4R{N z$SQMX^AK6(fA + + + + + diff --git a/UnitsNet.TestApps.Uwp.Csharp/MainPage.xaml.cs b/UnitsNet.TestApps.Uwp.Csharp/MainPage.xaml.cs new file mode 100644 index 0000000000..7905f7df5f --- /dev/null +++ b/UnitsNet.TestApps.Uwp.Csharp/MainPage.xaml.cs @@ -0,0 +1,32 @@ +using Windows.UI.Xaml.Controls; +using UnitsNet; +using UnitsNet.Units; + +namespace UWP +{ + ///

+ /// An empty page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class MainPage : Page + { + /// + /// Example of public property returning WinRT component compatible type. + /// + public Temperature MyTemperature { get; set; } + + public MainPage() + { + InitializeComponent(); + + // Test some variations, From() constructors, Parse(), As() + string celsius = Temperature.FromDegreesCelsius(100).ToString(TemperatureUnit.DegreeCelsius); + string fahrenheit = Temperature.Parse("100 °C").ToString(TemperatureUnit.DegreeFahrenheit); + string kelvin = Temperature.FromDegreesCelsius(Temperature.Parse(fahrenheit).As(TemperatureUnit.DegreeCelsius)).ToString(TemperatureUnit.Kelvin); + + // Arithmetic operators not allowed in WinRT Components, but SHOULD be allowed in UWP C# apps + // new Temperature(5) + new Temperature(6) + + MyTextBlock.Text = $"{celsius} = {fahrenheit} = {kelvin}"; + } + } +} diff --git a/UnitsNet.TestApps.Uwp.Csharp/Package.appxmanifest b/UnitsNet.TestApps.Uwp.Csharp/Package.appxmanifest new file mode 100644 index 0000000000..c54c162213 --- /dev/null +++ b/UnitsNet.TestApps.Uwp.Csharp/Package.appxmanifest @@ -0,0 +1,49 @@ + + + + + + + + + + UWP + Andreas + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UnitsNet.TestApps.Uwp.Csharp/Properties/AssemblyInfo.cs b/UnitsNet.TestApps.Uwp.Csharp/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..eaf72df06f --- /dev/null +++ b/UnitsNet.TestApps.Uwp.Csharp/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("UWP")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("UWP")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: ComVisible(false)] \ No newline at end of file diff --git a/UnitsNet.TestApps.Uwp.Csharp/Properties/Default.rd.xml b/UnitsNet.TestApps.Uwp.Csharp/Properties/Default.rd.xml new file mode 100644 index 0000000000..80a960ce32 --- /dev/null +++ b/UnitsNet.TestApps.Uwp.Csharp/Properties/Default.rd.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/UnitsNet.TestApps.Uwp.Csharp/UnitsNet.TestApps.Uwp.Csharp.csproj b/UnitsNet.TestApps.Uwp.Csharp/UnitsNet.TestApps.Uwp.Csharp.csproj new file mode 100644 index 0000000000..fe4e4934b1 --- /dev/null +++ b/UnitsNet.TestApps.Uwp.Csharp/UnitsNet.TestApps.Uwp.Csharp.csproj @@ -0,0 +1,141 @@ + + + + + Debug + x86 + {76255CC9-A854-441F-AF5C-2606509D3C5E} + AppContainerExe + Properties + UWP + UWP + en-US + UAP + 10.0.10586.0 + 10.0.10240.0 + 14 + 512 + {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + UnitsNet.TestApps.Uwp.Csharp.pfx + BD7344E28A4F4103AFCAA74215B0E3CFE3DC589E + + + true + bin\x86\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + x86 + false + prompt + true + + + bin\x86\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + x86 + false + prompt + true + true + + + true + bin\ARM\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + ARM + false + prompt + true + + + bin\ARM\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + ARM + false + prompt + true + true + + + true + bin\x64\Debug\ + DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP + ;2008 + full + x64 + false + prompt + true + + + bin\x64\Release\ + TRACE;NETFX_CORE;WINDOWS_UWP + true + ;2008 + pdbonly + x64 + false + prompt + true + true + + + + + + + + App.xaml + + + MainPage.xaml + + + + + + Designer + + + + + + + + + + + + + + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + + 14.0 + + + + \ No newline at end of file diff --git a/UnitsNet.TestApps.Uwp.Csharp/UnitsNet.TestApps.Uwp.Csharp.pfx b/UnitsNet.TestApps.Uwp.Csharp/UnitsNet.TestApps.Uwp.Csharp.pfx new file mode 100644 index 0000000000000000000000000000000000000000..60d193b2a2e63b16fe52f9ca322991ca722457f4 GIT binary patch literal 2454 zcmZuz2{=^k7r%E_W6L&_G?o%s?=VLAT71?hOUh1*u}p(BlPyu*kfnq~N*a{xOS11- z(jrnRR48N+nUsX)yY>A4{rf-9ckgrFdw#!j&U@bHy!W2>LNFl?1)?FCV2UHCM4Lx1 z3W0c#4HI-RFhLukH6a+w{XY}-JqE@OBlHj=FL46@i4x=oQEV9V6@oEbNCwCMUmBTQ z7{ga}ls{J1t?eQTh400{nBKzniVVAZLo!c_+a(I_dFJ}vlNQlDcw9B)8}D+@^h$=s z<|UNUd3V)p#;m;gu%S)rX_s|W3#Xk==uEZIQCrLX7r#{2uhZ}C+5JJ%cq#4Pq4q6B znsaGhW>fFo_poE`DaYGA`?C8w@$Qyop7r8utIp@=2!hFM;kye~RqrAyFwXk*o~QYx z>og?P%bm+kzA!%SXXXr%m|!p@Tru=e9Gj z<97{`(__nr6HB=*yeS8v1*v##bW zr}pCAj=GBK=upVxPkm=BeTyyA2*6lx<#NGFeG+*^`cWZ&XMKD6>B(1S{P$_Z8{;=cCEX@K3zv;`nJX) zE|LCefEZjF)@RzRQPjek7%-_M`%N*=OULG3nKnqb3T!KW=jTJ~z*QbfD=W&E3vutF zwgpNS?<2~$On)&kxUDUpFbZz|`_ z=aY=Q`R8x@Ww8xByr$obVtU$OljCuUJ13?ZytL>WL@GbO~%^Kul8^( zxDvg~GokUzmZB2pY^=wgWr8omxNie%&d%dRWG#CF8GKC=8#XQGGf8K*n>}%6X6fvw z#q@vio4-U=v91cGi@lJs;}%FJ$mi0!G?>QD@RXQQ%d7cXrMkbSo0A)=OTrTRR$h>7 z_BAK~)^2~jEhh1&*0ZujE;XxsHv8BhftuA2%qp75?nt+$j}@3*UtGGYIy$-O()MMO z5MBGpjk;$lB2}$gGm|!?DvtmIY~LA*s^)qd#%?RUeX*cb?(9%adn3_Db!=PXPP0$C zEBbl~i+xuYHdc!ar>ZcSg6PrAs z-!Z);F1cf9{qWIb=P-g<%KBFtM~;j%S|ql8P>J!p z7bkEx#LE|Q@9rX>>4wCAw@Ct#jKg3+001C||B(`83z9i-2!H@>U@M^e>q!RG5seIZ zAiO$20lWYja;pP}0Z)YAifA;%@28!HSSf%G!qEUNKnrri5ma#?284A*L9z|W3fKeC z5jQ4q6ks9Z1sn(D06S#-$@l}_2r@$SP#^%|jv|#Ga(qQ z^Lyn#4+QjP42)JlXc8jQe|CK|8%A*<7&ZI5=MyB60MuIyj2cAveh3De*k}}pLWwAs z?>!4Sq?PToDBN3d>wXR-^g9VCfCV5ivIr!ML+{6+#qoyzG^Xbv7DSQ~B2yu4NKXrb zs5+1{0(Bv6G6ZS;g8v!=g9?964PpT_46Xr?mGGlr5CkHtqF|dinT6-R{*QVNtLuaj z?8Rmwr_!qRQ5geOeCK6-M}TlfVa(bcDQhY{nT3m2trR%=98i#Io>lz5o{ib#zDD4Y zp1%!_khQD)!d%Mx3k>#3*_(5T^>1xWV#&PV}j(iz40-V~Ghek)uhB}8f))l`>afNN0>z|g0TbNlK-P0g=zW*G}38<18DHx0736$cu$sDX#nC=@5I`<;Vg8R0Alo&S~D+1K# zdIp#Jrk#CU&>%IZVhUU%>M7c}MIVSz2uXgg=No;WYDeT5dVY`9_r)kr*=p;TgcNnO zS3)Q2zLoTkl|W(XGg)aAkLL4SI+^(IAG`r13*m8CRbezr8Y2<78Z~JhkUyRt*O4tw oT=)pa7L;Nn;wC$a9tAY?Fh9BW5em2w=1kqCpMOS3!}xXm11eS=1ONa4 literal 0 HcmV?d00001 diff --git a/UnitsNet.TestApps.Uwp.Csharp/project.json b/UnitsNet.TestApps.Uwp.Csharp/project.json new file mode 100644 index 0000000000..b11f1c8a10 --- /dev/null +++ b/UnitsNet.TestApps.Uwp.Csharp/project.json @@ -0,0 +1,17 @@ +{ + "dependencies": { + "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0", + "UnitsNet.WindowsRuntimeComponent": "3.30.0-alpha4" + }, + "frameworks": { + "uap10.0": {} + }, + "runtimes": { + "win10-arm": {}, + "win10-arm-aot": {}, + "win10-x86": {}, + "win10-x86-aot": {}, + "win10-x64": {}, + "win10-x64-aot": {} + } +} \ No newline at end of file From d900d5cc65021d08f4500a890557763c714bbfbb Mon Sep 17 00:00:00 2001 From: Andreas Gullberg Larsen Date: Sat, 9 Apr 2016 23:09:16 +0200 Subject: [PATCH 11/17] testapp: Add JavaScript UWP app --- UnitsNet.TestApps.Uwp.JavaScript/.gitignore | 1 + .../UnitsNet.TestApps.Uwp.JavaScript.jsproj | 100 + ...t.TestApps.Uwp.JavaScript_TemporaryKey.pfx | Bin 0 -> 2454 bytes .../WinJS/css/ui-dark.css | 7304 ++ .../WinJS/css/ui-light.css | 7304 ++ .../WinJS/fonts/Symbols.ttf | Bin 0 -> 47488 bytes .../WinJS/js/base.js | 26523 ++++++++ .../WinJS/js/en-US/ui.strings.js | 529 + .../WinJS/js/ui.js | 54913 ++++++++++++++++ .../css/default.css | 2 + UnitsNet.TestApps.Uwp.JavaScript/default.html | 47 + .../images/LockScreenLogo.scale-200.png | Bin 0 -> 1430 bytes .../images/SplashScreen.scale-200.png | Bin 0 -> 7700 bytes .../images/Square150x150Logo.scale-200.png | Bin 0 -> 2937 bytes .../images/Square44x44Logo.scale-200.png | Bin 0 -> 1647 bytes ...x44Logo.targetsize-24_altform-unplated.png | Bin 0 -> 1255 bytes .../images/StoreLogo.png | Bin 0 -> 1451 bytes .../images/Wide310x150Logo.scale-200.png | Bin 0 -> 3204 bytes .../js/default.js | 32 + .../package.appxmanifest | 28 + .../packages.config | 4 + 21 files changed, 96787 insertions(+) create mode 100644 UnitsNet.TestApps.Uwp.JavaScript/.gitignore create mode 100644 UnitsNet.TestApps.Uwp.JavaScript/UnitsNet.TestApps.Uwp.JavaScript.jsproj create mode 100644 UnitsNet.TestApps.Uwp.JavaScript/UnitsNet.TestApps.Uwp.JavaScript_TemporaryKey.pfx create mode 100644 UnitsNet.TestApps.Uwp.JavaScript/WinJS/css/ui-dark.css create mode 100644 UnitsNet.TestApps.Uwp.JavaScript/WinJS/css/ui-light.css create mode 100644 UnitsNet.TestApps.Uwp.JavaScript/WinJS/fonts/Symbols.ttf create mode 100644 UnitsNet.TestApps.Uwp.JavaScript/WinJS/js/base.js create mode 100644 UnitsNet.TestApps.Uwp.JavaScript/WinJS/js/en-US/ui.strings.js create mode 100644 UnitsNet.TestApps.Uwp.JavaScript/WinJS/js/ui.js create mode 100644 UnitsNet.TestApps.Uwp.JavaScript/css/default.css create mode 100644 UnitsNet.TestApps.Uwp.JavaScript/default.html create mode 100644 UnitsNet.TestApps.Uwp.JavaScript/images/LockScreenLogo.scale-200.png create mode 100644 UnitsNet.TestApps.Uwp.JavaScript/images/SplashScreen.scale-200.png create mode 100644 UnitsNet.TestApps.Uwp.JavaScript/images/Square150x150Logo.scale-200.png create mode 100644 UnitsNet.TestApps.Uwp.JavaScript/images/Square44x44Logo.scale-200.png create mode 100644 UnitsNet.TestApps.Uwp.JavaScript/images/Square44x44Logo.targetsize-24_altform-unplated.png create mode 100644 UnitsNet.TestApps.Uwp.JavaScript/images/StoreLogo.png create mode 100644 UnitsNet.TestApps.Uwp.JavaScript/images/Wide310x150Logo.scale-200.png create mode 100644 UnitsNet.TestApps.Uwp.JavaScript/js/default.js create mode 100644 UnitsNet.TestApps.Uwp.JavaScript/package.appxmanifest create mode 100644 UnitsNet.TestApps.Uwp.JavaScript/packages.config diff --git a/UnitsNet.TestApps.Uwp.JavaScript/.gitignore b/UnitsNet.TestApps.Uwp.JavaScript/.gitignore new file mode 100644 index 0000000000..07e6e472cc --- /dev/null +++ b/UnitsNet.TestApps.Uwp.JavaScript/.gitignore @@ -0,0 +1 @@ +/node_modules diff --git a/UnitsNet.TestApps.Uwp.JavaScript/UnitsNet.TestApps.Uwp.JavaScript.jsproj b/UnitsNet.TestApps.Uwp.JavaScript/UnitsNet.TestApps.Uwp.JavaScript.jsproj new file mode 100644 index 0000000000..1d059bbdec --- /dev/null +++ b/UnitsNet.TestApps.Uwp.JavaScript/UnitsNet.TestApps.Uwp.JavaScript.jsproj @@ -0,0 +1,100 @@ + + + + + Debug + AnyCPU + + + Debug + ARM + + + Debug + x64 + + + Debug + x86 + + + Release + AnyCPU + + + Release + ARM + true + + + Release + x64 + true + + + Release + x86 + true + + + + fce9c341-d288-4517-9d2d-5c4bdf5d8f20 + + + + 14.0 + + + + + UAP + 10.0.10586.0 + 10.0.10240.0 + $(VersionNumberMajor).$(VersionNumberMinor) + en-US + UnitsNet.TestApps.Uwp.JavaScript_TemporaryKey.pfx + + + + Designer + + + + + + + + + + + + + + + + + + + + + + + ..\packages\UnitsNet.WindowsRuntimeComponent.3.30.0-alpha7\lib\uap10.0\UnitsNet.winmd + true + True + True + + + + + \ No newline at end of file diff --git a/UnitsNet.TestApps.Uwp.JavaScript/UnitsNet.TestApps.Uwp.JavaScript_TemporaryKey.pfx b/UnitsNet.TestApps.Uwp.JavaScript/UnitsNet.TestApps.Uwp.JavaScript_TemporaryKey.pfx new file mode 100644 index 0000000000000000000000000000000000000000..7112de92fa4d999f146ba04bd305b8578f9749db GIT binary patch literal 2454 zcmZve3pf;Q8^>q%#LA&WIpwrkB5PP{)4^6K)?(#QSZBLYlq5u9M+zyF-YCbMD>)Rh zQW2|qkwZlh^%A|#lt|cj>iWLEzUz8tuKT&}|L>XmexB=|nR^C;@t05_8iMgwIK1Xr zv$OMJpb(f1<7pTezYW1u2*xh{-xPKX17k-JJc!r;Zqd=js)>FdnZ9XhqX0Jbx!eJz+8eE$pd}|5wvCCAip)(RlyAGY1nk^&`{Ow1G zkKw?L3+vw5-#e4lH9tP9qt)UeY^`^L{eb<~?xH=*1q*zM1zTdzsnaU*dpKU5eZ^iA z;f=3O58Ct+bW5^spwsjtW#t}OmBAogX5(C1`zr-)P83b;VIpZIMNlKXXRpMDeN3WP z7E@jDxZ_r~XFYrFn}C1M`@67WGks#ZTwtMc$jVzjrAyAeH{JSF_HCX(W3;NXC@1b^ zaVMQepj>`-hBz%GTel_Z94NPgm~*KjHF`Me5~YE@Gw6t#G@0XP>LmnV{j?jTj1Cd+ z^qlE4e>OH}IEOlWAsz2MntJn=to4aaMH(chwEFYOD%YnU^zVHkeL?g?Q=E&1l^XTb z*KYgCDbkC?9UD?l9w1~$^@)1AjaA>w<8fPatjBiBN6%?2{h+xhR{D3W75|_+%VT3%%kL=5PJl7?z*d1J*rx#=Se&~auT5pZC1C){}tJBg( zeTrG{sr=|!WrI+gSlUt2HnX<6Cr4pp{-kXHH9g7$-r?izFCgrd^!J%Kj>TtONDHiJ zpYdBu3vacL#IR73`|5)ul45T%3LET6%W1K(AAtoIpAh$(_ua>g8iuK%v^$U2r&I8L ziK-dbX?U|F3VkeSvElu-7E8w&)=E;joeMgobsQ~FgWA91tUL7;Ii}wP8YwJS@dPkJ{f~eXmfH+E?tfJum&Mjj)P@Z^^td_%3snb>BoG#N zJ_abFq3Si4zPPEvTkV1$=_#bIxkcaKH}sk3xDKVcJZJMTXe>E8tBvv9Kbm>Mu*pxZ zj#GAf%Y|l>_qJEmO}eRWu=Ytdy0?Wkl7z0FJM6JI){~uYSB}aYT*NOKF;k7>dyB-l zf!gP7l+_Hn@{V;@P0oZE#JQ~z_3jbOh@Xo%EF~Lzm-q%>d7+Pr*SeVbT`s~rV?cTV z-I+z1n95_fisJ2sl^2x#O}V7>BW3jXdkLm--qUYf6=a+GeZ#LOvPOlbxW?i~;sc!d zHBU>Fx6S){`q%?ubv=RFcI{(fk@tmJ)b(AwJQt#P2JOj;WwQ0VKkHr%$!TbhT(+Zb zpDUSICxX|=DHt6M$YU^xx*x3^Gvst~HY$Y4g*RY)hh4)P6G}f#=XP$l$$g%inz-sL zre|D+wvl^GfcH0?f9|lio?kx5&DwmiBJ{I#7ek%bO;A-j-o1a#O@GecUL78tmKV*L zV~^P6$pMT_+}u)4`>19N#~s&buHkewdUByS=Df)6+)SS`XseO5YHdY6 zb+%=6NHt%cd#ASaoyRgum)i=h{nak<(z-Yd1_S^A+W$W&rAt>d1H1tU&;<+u4xo>W z`hYfI08kLhK|FoL)BDLh5K09+5%yz_3T#16HsFCouo0pQY=K;Gcr6@=0b%MIP?xD_ z1y};UfEN%590iUe#sPu=Wxy60e~=@?<>tS7p~%{+>El(qD(kuTRpMwTp%$qLx~_ z7mKkES>l=ba>Rz#!BC=1 zdACF|&^v5x8xg8v=eTyV%J^!y!1?{$2!?G0-| zP=G-}0JQFh+W13>LLxX}%CA}9l557^}5o+5LJy_ORJMcB=OCFQ* z<{SZZM$=-YNJ%cwP;Q|LY?ZsKu`h8lshh;t*QG7as7DX&$^WRnO2oQs#&fc?sV`fL z{k_+M>5rPrti0b8@`4;Q!R;tk%mHg_3RnA?=#*&>I%gCpe2y)$94dNk(G~P`yH&v# z#YO s$4*=;pc?-~Q%}Zs>-aK8O2+=9VPheWC+l^SLA))IelN0(`Qs1iAA%79jsO4v literal 0 HcmV?d00001 diff --git a/UnitsNet.TestApps.Uwp.JavaScript/WinJS/css/ui-dark.css b/UnitsNet.TestApps.Uwp.JavaScript/WinJS/css/ui-dark.css new file mode 100644 index 0000000000..991c9316d3 --- /dev/null +++ b/UnitsNet.TestApps.Uwp.JavaScript/WinJS/css/ui-dark.css @@ -0,0 +1,7304 @@ +/* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. */ +@keyframes WinJS-node-inserted { + from { + outline-color: #000; + } + to { + outline-color: #001; + } +} +@keyframes WinJS-opacity-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} +@keyframes WinJS-opacity-out { + from { + opacity: 1; + } + to { + opacity: 0; + } +} +@keyframes WinJS-scale-up { + from { + transform: scale(0.85); + } + to { + transform: scale(1); + } +} +@keyframes WinJS-scale-down { + from { + transform: scale(1); + } + to { + transform: scale(0.85); + } +} +@keyframes WinJS-default-remove { + from { + transform: translateX(11px); + } + to { + transform: none; + } +} +@keyframes WinJS-default-remove-rtl { + from { + transform: translateX(-11px); + } + to { + transform: none; + } +} +@keyframes WinJS-default-apply { + from { + transform: none; + } + to { + transform: translateX(11px); + } +} +@keyframes WinJS-default-apply-rtl { + from { + transform: none; + } + to { + transform: translateX(-11px); + } +} +@keyframes WinJS-showEdgeUI { + from { + transform: translateY(-70px); + } + to { + transform: none; + } +} +@keyframes WinJS-showPanel { + from { + transform: translateX(364px); + } + to { + transform: none; + } +} +@keyframes WinJS-showPanel-rtl { + from { + transform: translateX(-364px); + } + to { + transform: none; + } +} +@keyframes WinJS-hideEdgeUI { + from { + transform: none; + } + to { + transform: translateY(-70px); + } +} +@keyframes WinJS-hidePanel { + from { + transform: none; + } + to { + transform: translateX(364px); + } +} +@keyframes WinJS-hidePanel-rtl { + from { + transform: none; + } + to { + transform: translateX(-364px); + } +} +@keyframes WinJS-showPopup { + from { + transform: translateY(50px); + } + to { + transform: none; + } +} +@keyframes WinJS-dragSourceEnd { + from { + transform: translateX(11px) scale(1.05); + } + to { + transform: none; + } +} +@keyframes WinJS-dragSourceEnd-rtl { + from { + transform: translateX(-11px) scale(1.05); + } + to { + transform: none; + } +} +@keyframes WinJS-enterContent { + from { + transform: translateY(28px); + } + to { + transform: none; + } +} +@keyframes WinJS-exit { + from { + transform: none; + } + to { + transform: none; + } +} +@keyframes WinJS-enterPage { + from { + transform: translateY(28px); + } + to { + transform: none; + } +} +@keyframes WinJS-updateBadge { + from { + transform: translateY(24px); + } + to { + transform: none; + } +} +@-webkit-keyframes WinJS-node-inserted { + from { + outline-color: #000; + } + to { + outline-color: #001; + } +} +@-webkit-keyframes -webkit-WinJS-opacity-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} +@-webkit-keyframes -webkit-WinJS-opacity-out { + from { + opacity: 1; + } + to { + opacity: 0; + } +} +@-webkit-keyframes -webkit-WinJS-scale-up { + from { + -webkit-transform: scale(0.85); + } + to { + -webkit-transform: scale(1); + } +} +@-webkit-keyframes -webkit-WinJS-scale-down { + from { + -webkit-transform: scale(1); + } + to { + -webkit-transform: scale(0.85); + } +} +@-webkit-keyframes -webkit-WinJS-default-remove { + from { + -webkit-transform: translateX(11px); + } + to { + -webkit-transform: none; + } +} +@-webkit-keyframes -webkit-WinJS-default-remove-rtl { + from { + -webkit-transform: translateX(-11px); + } + to { + -webkit-transform: none; + } +} +@-webkit-keyframes -webkit-WinJS-default-apply { + from { + -webkit-transform: none; + } + to { + -webkit-transform: translateX(11px); + } +} +@-webkit-keyframes -webkit-WinJS-default-apply-rtl { + from { + -webkit-transform: none; + } + to { + -webkit-transform: translateX(-11px); + } +} +@-webkit-keyframes -webkit-WinJS-showEdgeUI { + from { + -webkit-transform: translateY(-70px); + } + to { + -webkit-transform: none; + } +} +@-webkit-keyframes -webkit-WinJS-showPanel { + from { + -webkit-transform: translateX(364px); + } + to { + -webkit-transform: none; + } +} +@-webkit-keyframes -webkit-WinJS-showPanel-rtl { + from { + -webkit-transform: translateX(-364px); + } + to { + -webkit-transform: none; + } +} +@-webkit-keyframes -webkit-WinJS-hideEdgeUI { + from { + -webkit-transform: none; + } + to { + -webkit-transform: translateY(-70px); + } +} +@-webkit-keyframes -webkit-WinJS-hidePanel { + from { + -webkit-transform: none; + } + to { + -webkit-transform: translateX(364px); + } +} +@-webkit-keyframes -webkit-WinJS-hidePanel-rtl { + from { + -webkit-transform: none; + } + to { + -webkit-transform: translateX(-364px); + } +} +@-webkit-keyframes -webkit-WinJS-showPopup { + from { + -webkit-transform: translateY(50px); + } + to { + -webkit-transform: none; + } +} +@-webkit-keyframes -webkit-WinJS-dragSourceEnd { + from { + -webkit-transform: translateX(11px) scale(1.05); + } + to { + -webkit-transform: none; + } +} +@-webkit-keyframes -webkit-WinJS-dragSourceEnd-rtl { + from { + -webkit-transform: translateX(-11px) scale(1.05); + } + to { + -webkit-transform: none; + } +} +@-webkit-keyframes -webkit-WinJS-enterContent { + from { + -webkit-transform: translateY(28px); + } + to { + -webkit-transform: none; + } +} +@-webkit-keyframes -webkit-WinJS-exit { + from { + -webkit-transform: none; + } + to { + -webkit-transform: none; + } +} +@-webkit-keyframes -webkit-WinJS-enterPage { + from { + -webkit-transform: translateY(28px); + } + to { + -webkit-transform: none; + } +} +@-webkit-keyframes -webkit-WinJS-updateBadge { + from { + -webkit-transform: translateY(24px); + } + to { + -webkit-transform: none; + } +} +@font-face { + font-family: "Segoe UI Command"; + src: local("Segoe MDL2 Assets"); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: "Symbols"; + src: url(../fonts/Symbols.ttf); +} +.win-type-header, +.win-h1 { + font-size: 46px; + font-weight: 200; + line-height: 1.216; + letter-spacing: 0px; +} +.win-type-subheader, +.win-h2 { + font-size: 34px; + font-weight: 200; + line-height: 1.176; +} +.win-type-title, +.win-h3 { + font-size: 24px; + font-weight: 300; + line-height: 1.167; +} +.win-type-subtitle, +.win-h4 { + font-size: 20px; + font-weight: 400; + line-height: 1.2; +} +.win-type-body, +.win-h6 { + font-size: 15px; + font-weight: 400; + line-height: 1.333; +} +.win-type-base, +.win-h5 { + font-size: 15px; + font-weight: 500; + line-height: 1.333; +} +.win-type-caption { + font-size: 12px; + font-weight: 400; + line-height: 1.167; +} +@font-face { + font-family: "Segoe UI"; + font-weight: 200; + src: local("Segoe UI Light"); +} +@font-face { + font-family: "Segoe UI"; + font-weight: 300; + src: local("Segoe UI Semilight"); +} +@font-face { + font-family: "Segoe UI"; + font-weight: 400; + src: local("Segoe UI"); +} +@font-face { + font-family: "Segoe UI"; + font-weight: 500; + src: local("Segoe UI Semibold"); +} +@font-face { + font-family: "Segoe UI"; + font-weight: 600; + src: local("Segoe UI Bold"); +} +@font-face { + font-family: "Segoe UI"; + font-style: italic; + font-weight: 400; + src: local("Segoe UI Italic"); +} +@font-face { + font-family: "Segoe UI"; + font-style: italic; + font-weight: 700; + src: local("Segoe UI Bold Italic"); +} +@font-face { + font-family: "Microsoft Yahei UI"; + font-weight: 200; + src: local("Microsoft Yahei UI Light"); +} +@font-face { + font-family: "Microsoft Yahei UI"; + font-weight: 300; + src: local("Microsoft Yahei UI"); +} +@font-face { + font-family: "Microsoft Yahei UI"; + font-weight: 500; + src: local("Microsoft Yahei UI"); +} +@font-face { + font-family: "Microsoft Yahei UI"; + font-weight: 600; + src: local("Microsoft Yahei UI Bold"); +} +@font-face { + font-family: "Microsoft JhengHei UI"; + font-weight: 200; + src: local("Microsoft JhengHei UI Light"); +} +@font-face { + font-family: "Microsoft JhengHei UI"; + font-weight: 300; + src: local("Microsoft JhengHei UI"); +} +@font-face { + font-family: "Microsoft JhengHei UI"; + font-weight: 500; + src: local("Microsoft JhengHei UI"); +} +@font-face { + font-family: "Microsoft JhengHei UI"; + font-weight: 600; + src: local("Microsoft JhengHei UI Bold"); +} +.win-type-header:-ms-lang(am, ti), +.win-type-subheader:-ms-lang(am, ti), +.win-type-title:-ms-lang(am, ti), +.win-type-subtitle:-ms-lang(am, ti), +.win-type-base:-ms-lang(am, ti), +.win-type-body:-ms-lang(am, ti), +.win-type-caption:-ms-lang(am, ti), +.win-h1:-ms-lang(am, ti), +.win-h2:-ms-lang(am, ti), +.win-h3:-ms-lang(am, ti), +.win-h4:-ms-lang(am, ti), +.win-h5:-ms-lang(am, ti), +.win-h6:-ms-lang(am, ti), +.win-button:-ms-lang(am, ti), +.win-dropdown:-ms-lang(am, ti), +.win-textbox:-ms-lang(am, ti), +.win-link:-ms-lang(am, ti), +.win-textarea:-ms-lang(am, ti) { + font-family: "Ebrima", "Ebrima", "Nirmala UI", "Gadugi", "Segoe UI Emoji", "Segoe MDL2 Assets", "Symbols", "Yu Gothic UI", "Yu Gothic", "Meiryo UI", "Leelawadee UI", "Microsoft YaHei UI", "Microsoft JhengHei UI", "Malgun Gothic", "Segoe UI Historic", "Estrangelo Edessa", "Microsoft Himalaya", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", "Microsoft Yi Baiti", "Mongolian Baiti", "MV Boli", "Myanmar Text", "Javanese Text", "Cambria Math"; +} +.win-type-header:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-type-subheader:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-type-title:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-type-subtitle:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-type-base:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-type-body:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-type-caption:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-h1:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-h2:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-h3:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-h4:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-h5:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-h6:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-button:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-dropdown:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-textbox:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-link:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-textarea:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te) { + font-family: "Nirmala UI", "Ebrima", "Nirmala UI", "Gadugi", "Segoe UI Emoji", "Segoe MDL2 Assets", "Symbols", "Yu Gothic UI", "Yu Gothic", "Meiryo UI", "Leelawadee UI", "Microsoft YaHei UI", "Microsoft JhengHei UI", "Malgun Gothic", "Segoe UI Historic", "Estrangelo Edessa", "Microsoft Himalaya", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", "Microsoft Yi Baiti", "Mongolian Baiti", "MV Boli", "Myanmar Text", "Javanese Text", "Cambria Math"; +} +.win-type-header:-ms-lang(chr-CHER-US), +.win-type-subheader:-ms-lang(chr-CHER-US), +.win-type-title:-ms-lang(chr-CHER-US), +.win-type-subtitle:-ms-lang(chr-CHER-US), +.win-type-base:-ms-lang(chr-CHER-US), +.win-type-body:-ms-lang(chr-CHER-US), +.win-type-caption:-ms-lang(chr-CHER-US), +.win-h1:-ms-lang(chr-CHER-US), +.win-h2:-ms-lang(chr-CHER-US), +.win-h3:-ms-lang(chr-CHER-US), +.win-h4:-ms-lang(chr-CHER-US), +.win-h5:-ms-lang(chr-CHER-US), +.win-h6:-ms-lang(chr-CHER-US), +.win-button:-ms-lang(chr-CHER-US), +.win-dropdown:-ms-lang(chr-CHER-US), +.win-textbox:-ms-lang(chr-CHER-US), +.win-link:-ms-lang(chr-CHER-US), +.win-textarea:-ms-lang(chr-CHER-US) { + font-family: "Gadugi", "Ebrima", "Nirmala UI", "Gadugi", "Segoe UI Emoji", "Segoe MDL2 Assets", "Symbols", "Yu Gothic UI", "Yu Gothic", "Meiryo UI", "Leelawadee UI", "Microsoft YaHei UI", "Microsoft JhengHei UI", "Malgun Gothic", "Segoe UI Historic", "Estrangelo Edessa", "Microsoft Himalaya", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", "Microsoft Yi Baiti", "Mongolian Baiti", "MV Boli", "Myanmar Text", "Javanese Text", "Cambria Math"; +} +.win-type-header:-ms-lang(ja), +.win-type-subheader:-ms-lang(ja), +.win-type-title:-ms-lang(ja), +.win-type-subtitle:-ms-lang(ja), +.win-type-base:-ms-lang(ja), +.win-type-body:-ms-lang(ja), +.win-type-caption:-ms-lang(ja), +.win-h1:-ms-lang(ja), +.win-h2:-ms-lang(ja), +.win-h3:-ms-lang(ja), +.win-h4:-ms-lang(ja), +.win-h5:-ms-lang(ja), +.win-h6:-ms-lang(ja), +.win-button:-ms-lang(ja), +.win-dropdown:-ms-lang(ja), +.win-textbox:-ms-lang(ja), +.win-link:-ms-lang(ja), +.win-textarea:-ms-lang(ja) { + font-family: "Yu Gothic UI", "Ebrima", "Nirmala UI", "Gadugi", "Segoe UI Emoji", "Segoe MDL2 Assets", "Symbols", "Yu Gothic UI", "Yu Gothic", "Meiryo UI", "Leelawadee UI", "Microsoft YaHei UI", "Microsoft JhengHei UI", "Malgun Gothic", "Segoe UI Historic", "Estrangelo Edessa", "Microsoft Himalaya", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", "Microsoft Yi Baiti", "Mongolian Baiti", "MV Boli", "Myanmar Text", "Javanese Text", "Cambria Math"; +} +.win-type-header:-ms-lang(km, lo, th, bug-Bugi), +.win-type-subheader:-ms-lang(km, lo, th, bug-Bugi), +.win-type-title:-ms-lang(km, lo, th, bug-Bugi), +.win-type-subtitle:-ms-lang(km, lo, th, bug-Bugi), +.win-type-base:-ms-lang(km, lo, th, bug-Bugi), +.win-type-body:-ms-lang(km, lo, th, bug-Bugi), +.win-type-caption:-ms-lang(km, lo, th, bug-Bugi), +.win-h1:-ms-lang(km, lo, th, bug-Bugi), +.win-h2:-ms-lang(km, lo, th, bug-Bugi), +.win-h3:-ms-lang(km, lo, th, bug-Bugi), +.win-h4:-ms-lang(km, lo, th, bug-Bugi), +.win-h5:-ms-lang(km, lo, th, bug-Bugi), +.win-h6:-ms-lang(km, lo, th, bug-Bugi), +.win-button:-ms-lang(km, lo, th, bug-Bugi), +.win-dropdown:-ms-lang(km, lo, th, bug-Bugi), +.win-textbox:-ms-lang(km, lo, th, bug-Bugi), +.win-link:-ms-lang(km, lo, th, bug-Bugi), +.win-textarea:-ms-lang(km, lo, th, bug-Bugi) { + font-family: "Leelawadee UI", "Ebrima", "Nirmala UI", "Gadugi", "Segoe UI Emoji", "Segoe MDL2 Assets", "Symbols", "Yu Gothic UI", "Yu Gothic", "Meiryo UI", "Leelawadee UI", "Microsoft YaHei UI", "Microsoft JhengHei UI", "Malgun Gothic", "Segoe UI Historic", "Estrangelo Edessa", "Microsoft Himalaya", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", "Microsoft Yi Baiti", "Mongolian Baiti", "MV Boli", "Myanmar Text", "Javanese Text", "Cambria Math"; +} +.win-type-header:-ms-lang(ko), +.win-type-subheader:-ms-lang(ko), +.win-type-title:-ms-lang(ko), +.win-type-subtitle:-ms-lang(ko), +.win-type-base:-ms-lang(ko), +.win-type-body:-ms-lang(ko), +.win-type-caption:-ms-lang(ko), +.win-h1:-ms-lang(ko), +.win-h2:-ms-lang(ko), +.win-h3:-ms-lang(ko), +.win-h4:-ms-lang(ko), +.win-h5:-ms-lang(ko), +.win-h6:-ms-lang(ko), +.win-button:-ms-lang(ko), +.win-dropdown:-ms-lang(ko), +.win-textbox:-ms-lang(ko), +.win-link:-ms-lang(ko), +.win-textarea:-ms-lang(ko) { + font-family: "Malgun Gothic", "Ebrima", "Nirmala UI", "Gadugi", "Segoe UI Emoji", "Segoe MDL2 Assets", "Symbols", "Yu Gothic UI", "Yu Gothic", "Meiryo UI", "Leelawadee UI", "Microsoft YaHei UI", "Microsoft JhengHei UI", "Malgun Gothic", "Segoe UI Historic", "Estrangelo Edessa", "Microsoft Himalaya", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", "Microsoft Yi Baiti", "Mongolian Baiti", "MV Boli", "Myanmar Text", "Javanese Text", "Cambria Math"; +} +.win-type-header:-ms-lang(jv-Java), +.win-type-subheader:-ms-lang(jv-Java), +.win-type-title:-ms-lang(jv-Java), +.win-type-subtitle:-ms-lang(jv-Java), +.win-type-base:-ms-lang(jv-Java), +.win-type-body:-ms-lang(jv-Java), +.win-type-caption:-ms-lang(jv-Java), +.win-h1:-ms-lang(jv-Java), +.win-h2:-ms-lang(jv-Java), +.win-h3:-ms-lang(jv-Java), +.win-h4:-ms-lang(jv-Java), +.win-h5:-ms-lang(jv-Java), +.win-h6:-ms-lang(jv-Java), +.win-button:-ms-lang(jv-Java), +.win-dropdown:-ms-lang(jv-Java), +.win-textbox:-ms-lang(jv-Java), +.win-link:-ms-lang(jv-Java), +.win-textarea:-ms-lang(jv-Java) { + font-family: "Javanese Text", "Ebrima", "Nirmala UI", "Gadugi", "Segoe UI Emoji", "Segoe MDL2 Assets", "Symbols", "Yu Gothic UI", "Yu Gothic", "Meiryo UI", "Leelawadee UI", "Microsoft YaHei UI", "Microsoft JhengHei UI", "Malgun Gothic", "Segoe UI Historic", "Estrangelo Edessa", "Microsoft Himalaya", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", "Microsoft Yi Baiti", "Mongolian Baiti", "MV Boli", "Myanmar Text", "Javanese Text", "Cambria Math"; +} +.win-type-header:-ms-lang(cop-Copt), +.win-type-subheader:-ms-lang(cop-Copt), +.win-type-title:-ms-lang(cop-Copt), +.win-type-subtitle:-ms-lang(cop-Copt), +.win-type-base:-ms-lang(cop-Copt), +.win-type-body:-ms-lang(cop-Copt), +.win-type-caption:-ms-lang(cop-Copt), +.win-h1:-ms-lang(cop-Copt), +.win-h2:-ms-lang(cop-Copt), +.win-h3:-ms-lang(cop-Copt), +.win-h4:-ms-lang(cop-Copt), +.win-h5:-ms-lang(cop-Copt), +.win-h6:-ms-lang(cop-Copt), +.win-button:-ms-lang(cop-Copt), +.win-dropdown:-ms-lang(cop-Copt), +.win-textbox:-ms-lang(cop-Copt), +.win-link:-ms-lang(cop-Copt), +.win-textarea:-ms-lang(cop-Copt) { + font-family: "Segoe MDL2 Assets", "Ebrima", "Nirmala UI", "Gadugi", "Segoe UI Emoji", "Segoe MDL2 Assets", "Symbols", "Yu Gothic UI", "Yu Gothic", "Meiryo UI", "Leelawadee UI", "Microsoft YaHei UI", "Microsoft JhengHei UI", "Malgun Gothic", "Segoe UI Historic", "Estrangelo Edessa", "Microsoft Himalaya", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", "Microsoft Yi Baiti", "Mongolian Baiti", "MV Boli", "Myanmar Text", "Javanese Text", "Cambria Math"; +} +.win-type-header:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-type-subheader:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-type-title:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-type-subtitle:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-type-base:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-type-body:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-type-caption:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-h1:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-h2:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-h3:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-h4:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-h5:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-h6:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-button:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-dropdown:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-textbox:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-link:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-textarea:-ms-lang(zh-CN, zh-Hans, zh-SG) { + font-family: "Microsoft YaHei UI", "Ebrima", "Nirmala UI", "Gadugi", "Segoe UI Emoji", "Segoe MDL2 Assets", "Symbols", "Yu Gothic UI", "Yu Gothic", "Meiryo UI", "Leelawadee UI", "Microsoft YaHei UI", "Microsoft JhengHei UI", "Malgun Gothic", "Segoe UI Historic", "Estrangelo Edessa", "Microsoft Himalaya", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", "Microsoft Yi Baiti", "Mongolian Baiti", "MV Boli", "Myanmar Text", "Javanese Text", "Cambria Math"; +} +.win-type-header:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-type-subheader:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-type-title:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-type-subtitle:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-type-base:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-type-body:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-type-caption:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-h1:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-h2:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-h3:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-h4:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-h5:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-h6:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-button:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-dropdown:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-textbox:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-link:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-textarea:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO) { + font-family: "Microsoft JhengHei UI", "Ebrima", "Nirmala UI", "Gadugi", "Segoe UI Emoji", "Segoe MDL2 Assets", "Symbols", "Yu Gothic UI", "Yu Gothic", "Meiryo UI", "Leelawadee UI", "Microsoft YaHei UI", "Microsoft JhengHei UI", "Malgun Gothic", "Segoe UI Historic", "Estrangelo Edessa", "Microsoft Himalaya", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", "Microsoft Yi Baiti", "Mongolian Baiti", "MV Boli", "Myanmar Text", "Javanese Text", "Cambria Math"; +} +html, +body { + width: 100%; + height: 100%; + margin: 0px; + cursor: default; + -webkit-touch-callout: none; + -ms-scroll-translation: vertical-to-horizontal; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +html { + overflow: hidden; + direction: ltr; +} +html:lang(ar), +html:lang(dv), +html:lang(fa), +html:lang(he), +html:lang(ku-Arab), +html:lang(pa-Arab), +html:lang(prs), +html:lang(ps), +html:lang(sd-Arab), +html:lang(syr), +html:lang(ug), +html:lang(ur), +html:lang(qps-plocm) { + direction: rtl; +} +body { + -ms-content-zooming: none; +} +iframe { + border: 0; +} +.win-type-header, +.win-type-subheader, +.win-type-title, +.win-type-subtitle, +.win-type-base, +.win-type-body, +.win-type-caption, +.win-h1, +.win-h2, +.win-h3, +.win-h4, +.win-h5, +.win-h6, +.win-button, +.win-dropdown, +.win-textbox, +.win-link, +.win-textarea { + font-family: "Segoe UI", sans-serif, "Segoe MDL2 Assets", "Symbols"; +} +.win-textbox, +.win-textarea { + -ms-user-select: element; + border-style: solid; + border-width: 2px; + border-radius: 0; + margin: 8px 0px; + width: 296px; + min-width: 64px; + min-height: 28px; + background-clip: border-box; + box-sizing: border-box; + padding: 3px 6px 5px 10px; + outline: 0; + font-size: 15px; + font-weight: 400; + line-height: 1.333; +} +.win-textbox::-ms-value { + margin: 0; + padding: 0; +} +.win-textbox::-ms-clear, +.win-textbox::-ms-reveal { + padding-right: 2px; + margin-right: -8px; + margin-left: 2px; + margin-top: -8px; + margin-bottom: -8px; + width: 30px; + height: 32px; +} +.win-textbox:lang(ar)::-ms-clear, +.win-textbox:lang(dv)::-ms-clear, +.win-textbox:lang(fa)::-ms-clear, +.win-textbox:lang(he)::-ms-clear, +.win-textbox:lang(ku-Arab)::-ms-clear, +.win-textbox:lang(pa-Arab)::-ms-clear, +.win-textbox:lang(prs)::-ms-clear, +.win-textbox:lang(ps)::-ms-clear, +.win-textbox:lang(sd-Arab)::-ms-clear, +.win-textbox:lang(syr)::-ms-clear, +.win-textbox:lang(ug)::-ms-clear, +.win-textbox:lang(ur)::-ms-clear, +.win-textbox:lang(qps-plocm)::-ms-clear, +.win-textbox:lang(ar)::-ms-reveal, +.win-textbox:lang(dv)::-ms-reveal, +.win-textbox:lang(fa)::-ms-reveal, +.win-textbox:lang(he)::-ms-reveal, +.win-textbox:lang(ku-Arab)::-ms-reveal, +.win-textbox:lang(pa-Arab)::-ms-reveal, +.win-textbox:lang(prs)::-ms-reveal, +.win-textbox:lang(ps)::-ms-reveal, +.win-textbox:lang(sd-Arab)::-ms-reveal, +.win-textbox:lang(syr)::-ms-reveal, +.win-textbox:lang(ug)::-ms-reveal, +.win-textbox:lang(ur)::-ms-reveal, +.win-textbox:lang(qps-plocm)::-ms-reveal { + margin-left: -8px; + margin-right: 2px; +} +.win-textarea { + resize: none; + overflow-y: auto; +} +.win-radio, +.win-checkbox { + width: 20px; + height: 20px; + margin-right: 8px; + margin-top: 12px; + margin-bottom: 12px; +} +.win-radio:lang(ar), +.win-checkbox:lang(ar), +.win-radio:lang(dv), +.win-checkbox:lang(dv), +.win-radio:lang(fa), +.win-checkbox:lang(fa), +.win-radio:lang(he), +.win-checkbox:lang(he), +.win-radio:lang(ku-Arab), +.win-checkbox:lang(ku-Arab), +.win-radio:lang(pa-Arab), +.win-checkbox:lang(pa-Arab), +.win-radio:lang(prs), +.win-checkbox:lang(prs), +.win-radio:lang(ps), +.win-checkbox:lang(ps), +.win-radio:lang(sd-Arab), +.win-checkbox:lang(sd-Arab), +.win-radio:lang(syr), +.win-checkbox:lang(syr), +.win-radio:lang(ug), +.win-checkbox:lang(ug), +.win-radio:lang(ur), +.win-checkbox:lang(ur), +.win-radio:lang(qps-plocm), +.win-checkbox:lang(qps-plocm) { + margin-left: 8px; + margin-right: 0px; +} +.win-radio::-ms-check, +.win-checkbox::-ms-check { + border-style: solid; + display: inline-block; + border-width: 2px; + background-clip: border-box; +} +.win-button { + border-style: solid; + margin: 0px; + min-height: 32px; + min-width: 120px; + padding: 4px 8px; + border-width: 2px; + background-clip: border-box; + border-radius: 0; + touch-action: manipulation; + -webkit-appearance: none; + font-size: 15px; + font-weight: 400; + line-height: 1.333; +} +.win-button.win-button-file { + border: none; + min-width: 100px; + min-height: 20px; + width: 340px; + height: 32px; + padding: 0px; + margin: 7px 8px 21px 8px; + background-clip: padding-box; +} +.win-button.win-button-file::-ms-value { + margin: 0; + border-width: 2px; + border-style: solid; + border-right-style: none; + border-radius: 0; + background-clip: border-box; + font-size: 15px; + font-weight: 400; + line-height: 1.333; +} +.win-button.win-button-file:lang(ar)::-ms-value, +.win-button.win-button-file:lang(dv)::-ms-value, +.win-button.win-button-file:lang(fa)::-ms-value, +.win-button.win-button-file:lang(he)::-ms-value, +.win-button.win-button-file:lang(ku-Arab)::-ms-value, +.win-button.win-button-file:lang(pa-Arab)::-ms-value, +.win-button.win-button-file:lang(prs)::-ms-value, +.win-button.win-button-file:lang(ps)::-ms-value, +.win-button.win-button-file:lang(sd-Arab)::-ms-value, +.win-button.win-button-file:lang(syr)::-ms-value, +.win-button.win-button-file:lang(ug)::-ms-value, +.win-button.win-button-file:lang(ur)::-ms-value, +.win-button.win-button-file:lang(qps-plocm)::-ms-value { + border-left-style: none; + border-right-style: solid; +} +.win-button.win-button-file::-ms-browse { + margin: 0; + padding: 0 18px; + border-width: 2px; + border-style: solid; + background-clip: padding-box; + font-size: 15px; + font-weight: 400; + line-height: 1.333; +} +.win-dropdown { + min-width: 56px; + max-width: 368px; + min-height: 32px; + margin: 8px 0; + border-style: solid; + border-width: 2px; + background-clip: border-box; + background-image: none; + box-sizing: border-box; + border-radius: 0; + font-size: 15px; + font-weight: 400; + line-height: 1.333; +} +.win-dropdown::-ms-value { + padding: 5px 12px 7px 12px; + margin: 0; +} +.win-dropdown::-ms-expand { + border: none; + margin-right: 5px; + margin-left: 3px; + margin-bottom: -2px; + font-size: 20px; +} +select[multiple].win-dropdown { + padding: 0 0 0 12px; + vertical-align: bottom; +} +.win-dropdown option { + font-size: 15px; + font-weight: 400; + line-height: 1.333; +} +.win-progress-bar, +.win-progress-ring, +.win-ring { + width: 180px; + height: 4px; + -webkit-appearance: none; +} +.win-progress-bar:not(:indeterminate), +.win-progress-ring:not(:indeterminate), +.win-ring:not(:indeterminate) { + border-style: none; +} +.win-progress-bar::-ms-fill, +.win-progress-ring::-ms-fill, +.win-ring::-ms-fill { + border-style: none; +} +.win-progress-bar.win-medium, +.win-progress-ring.win-medium, +.win-ring.win-medium { + width: 296px; +} +.win-progress-bar.win-large, +.win-progress-ring.win-large, +.win-ring.win-large { + width: 100%; +} +.win-progress-bar:indeterminate::-webkit-progress-value, +.win-progress-ring:indeterminate::-webkit-progress-value, +.win-ring:indeterminate::-webkit-progress-value { + position: relative; + -webkit-animation: win-progress-indeterminate 3s linear infinite; +} +.win-progress-bar.win-paused:not(:indeterminate), +.win-progress-ring.win-paused:not(:indeterminate), +.win-ring.win-paused:not(:indeterminate) { + animation-name: win-progress-fade-out; + animation-duration: 3s; + animation-timing-function: cubic-bezier(0.03, 0.76, 0.31, 1); + opacity: 0.5; +} +.win-progress-bar.win-error::-ms-fill, +.win-progress-ring.win-error::-ms-fill, +.win-ring.win-error::-ms-fill { + opacity: 0; +} +.win-progress-ring, +.win-ring { + width: 20px; + height: 20px; +} +.win-progress-ring:indeterminate::-ms-fill, +.win-ring:indeterminate::-ms-fill { + animation-name: -ms-ring; +} +.win-progress-ring.win-medium, +.win-ring.win-medium { + width: 40px; + height: 40px; +} +.win-progress-ring.win-large, +.win-ring.win-large { + width: 60px; + height: 60px; +} +@-webkit-keyframes win-progress-indeterminate { + 0% { + left: 0; + width: 25%; + } + 50% { + left: calc(75%); + width: 25%; + } + 75% { + left: calc(100%); + width: 0%; + } + 75.1% { + left: 0; + width: 0%; + } + 100% { + left: 0; + width: 25%; + } +} +@keyframes win-progress-fade-out { + from { + opacity: 1.0; + } + to { + opacity: 0.5; + } +} +.win-slider { + -webkit-appearance: none; + width: 280px; + height: 22px; + padding-top: 17px; + padding-bottom: 32px; +} +.win-slider::-ms-track { + height: 2px; + border-style: none; +} +.win-slider::-webkit-slider-runnable-track { + height: 2px; + border-style: none; +} +.win-slider::-moz-range-track { + height: 2px; + border-style: none; +} +.win-slider::-ms-thumb { + width: 24px; + height: 8px; + border-radius: 4px; + border-style: none; +} +.win-slider::-webkit-slider-thumb { + -webkit-appearance: none; + margin-top: -4px; + width: 24px; + height: 8px; + border-radius: 4px; + border-style: none; +} +.win-slider::-moz-range-thumb { + width: 24px; + height: 8px; + border-radius: 4px; + border-style: none; +} +.win-slider.win-vertical { + writing-mode: bt-lr; + width: 22px; + height: 280px; +} +.win-slider.win-vertical::-ms-track { + width: 2px; + height: auto; +} +.win-slider.win-vertical::-ms-thumb { + width: 8px; + height: 24px; +} +.win-slider.win-vertical:lang(ar), +.win-slider.win-vertical:lang(dv), +.win-slider.win-vertical:lang(fa), +.win-slider.win-vertical:lang(he), +.win-slider.win-vertical:lang(ku-Arab), +.win-slider.win-vertical:lang(pa-Arab), +.win-slider.win-vertical:lang(prs), +.win-slider.win-vertical:lang(ps), +.win-slider.win-vertical:lang(sd-Arab), +.win-slider.win-vertical:lang(syr), +.win-slider.win-vertical:lang(ug), +.win-slider.win-vertical:lang(ur), +.win-slider.win-vertical:lang(qps-plocm) { + writing-mode: bt-rl; +} +.win-link { + text-decoration: underline; + cursor: pointer; + touch-action: manipulation; +} +.win-code { + font-family: "Consolas", "Menlo", "Monaco", "Courier New", monospace; + font-size: 15px; + font-weight: 400; + line-height: 1.333; +} +.win-type-ellipsis { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +h1.win-type-ellipsis, +.win-type-header.win-type-ellipsis, +.win-h1.win-type-ellipsis { + line-height: 1.4286; +} +h2.win-type-ellipsis, +.win-type-subheader.win-type-ellipsis, +.win-h2.win-type-ellipsis { + line-height: 1.5; +} +.win-scrollview { + overflow-x: auto; + overflow-y: hidden; + height: 400px; + width: 100%; +} +h1.win-type-header, +h2.win-type-subheader, +h3.win-type-title, +h4.win-type-subtitle, +h5.win-type-base, +h6.win-type-body, +h1.win-h1, +h2.win-h2, +h3.win-h3, +h4.win-h4, +h5.win-h5, +h6.win-h6 { + margin-top: 0px; + margin-bottom: 0px; +} +.win-type-body p, +p.win-type-body { + font-weight: 300; +} +.win-listview { + overflow: hidden; + height: 400px; +} +.win-listview .win-surface { + overflow: visible; +} +.win-listview > .win-viewport.win-horizontal .win-surface { + height: 100%; +} +.win-listview > .win-viewport.win-vertical .win-surface { + width: 100%; +} +.win-listview > .win-viewport { + position: relative; + width: 100%; + height: 100%; + z-index: 0; + -ms-overflow-style: -ms-autohiding-scrollbar; + -webkit-overflow-scrolling: touch; + white-space: nowrap; +} +.win-listview > .win-viewport.win-horizontal { + overflow-x: auto; + overflow-y: hidden; +} +.win-listview > .win-viewport.win-vertical { + overflow-x: hidden; + overflow-y: auto; +} +.win-listview .win-itemscontainer { + overflow: hidden; +} +.win-listview .win-itemscontainer-padder { + width: 0; + height: 0; + margin: 0; + padding: 0; + border: 0; + overflow: hidden; +} +.win-listview > .win-horizontal .win-container { + margin: 10px 5px 0px 5px; +} +.win-listview > .win-vertical .win-container { + margin: 10px 24px 0px 7px; +} +.win-listview.win-rtl > .win-vertical .win-container { + margin: 10px 7px 0px 24px; +} +.win-listview .win-container, +.win-listview .win-itembox, +.win-itemcontainer.win-container, +.win-itemcontainer .win-itembox { + cursor: default; + z-index: 0; +} +.win-listview .win-container { + touch-action: pan-x pan-y pinch-zoom; +} +.win-semanticzoom .win-listview > .win-viewport * { + touch-action: auto; +} +.win-semanticzoom .win-listview > .win-viewport.win-zooming-x { + overflow-x: visible; +} +.win-semanticzoom .win-listview > .win-viewport.win-zooming-y { + overflow-y: visible; +} +.win-listview .win-itembox, +.win-itemcontainer .win-itembox { + width: 100%; + height: 100%; +} +.win-listview .win-item, +.win-itemcontainer .win-item { + z-index: 1; +} +.win-listview .win-item, +.win-itemcontainer .win-item { + overflow: hidden; + position: relative; +} +.win-listview > .win-vertical .win-item { + width: 100%; +} +.win-listview .win-item:focus, +.win-itemcontainer .win-item:focus { + outline-style: none; +} +.win-listview .win-focusedoutline, +.win-itemcontainer .win-focusedoutline { + width: calc(100% - 4px); + height: calc(100% - 4px); + left: 2px; + top: 2px; + position: absolute; + z-index: 5; + pointer-events: none; +} +.win-container.win-selected .win-selectionborder { + border-width: 2px; + border-style: solid; +} +html.win-hoverable .win-container.win-selected:hover .win-selectionborder { + border-width: 2px; + border-style: solid; +} +html.win-hoverable .win-listview .win-itembox:hover::before, +html.win-hoverable .win-itemcontainer .win-itembox:hover::before { + position: absolute; + left: 0px; + top: 0px; + content: ""; + width: calc(100% - 4px); + height: calc(100% - 4px); + pointer-events: none; + border-style: solid; + border-width: 2px; + z-index: 3; +} +html.win-hoverable .win-listview.win-selectionstylefilled .win-itembox:hover::before, +html.win-hoverable .win-itemcontainer.win-selectionstylefilled .win-itembox:hover::before, +html.win-hoverable .win-listview .win-itembox.win-selected:hover::before, +html.win-hoverable .win-itemcontainer.win-itembox.win-selected:hover::before, +html.win-hoverable .win-itemcontainer.win-itembox.win-selected:hover::before { + display: none; +} +.win-listview .win-groupheader { + padding: 10px 10px 10px 2px; + overflow: hidden; + outline-width: 0.01px; + outline-style: none; + float: left; + font-size: 34px; + font-weight: 200; + line-height: 1.176; +} +.win-listview .win-groupheadercontainer { + z-index: 1; + touch-action: pan-x pan-y pinch-zoom; + overflow: hidden; +} +.win-listview .win-horizontal .win-headercontainer, +.win-listview .win-horizontal .win-footercontainer { + height: 100%; + display: inline-block; + overflow: hidden; + white-space: normal; +} +.win-listview .win-vertical .win-headercontainer, +.win-listview .win-vertical .win-footercontainer { + width: 100%; + display: block; + overflow: hidden; + white-space: normal; +} +.win-listview .win-groupheader.win-focused { + outline-style: dotted; +} +.win-listview.win-rtl .win-groupheader { + padding-left: 10px; + padding-right: 2px; + float: right; +} +.win-listview.win-groups .win-horizontal .win-groupleader { + margin-left: 70px; +} +.win-listview.win-groups.win-rtl .win-horizontal .win-groupleader { + margin-left: 0; + margin-right: 70px; +} +.win-listview.win-groups .win-vertical .win-listlayout .win-groupleader, +.win-listview.win-groups .win-vertical .win-gridlayout .win-groupleader { + margin-top: 70px; +} +.win-listview.win-groups > .win-vertical .win-surface.win-listlayout, +.win-listview.win-groups > .win-vertical .win-surface.win-gridlayout { + margin-top: -65px; +} +.win-listview.win-groups > .win-horizontal .win-surface { + margin-left: -70px; +} +.win-listview.win-groups.win-rtl > .win-horizontal .win-surface { + margin-left: 0; + margin-right: -70px; +} +.win-listview .win-surface { + -webkit-margin-collapse: separate; + white-space: normal; +} +.win-surface ._win-proxy { + position: relative; + overflow: hidden; + width: 0; + height: 0; + touch-action: none; +} +.win-selectionborder { + position: absolute; + opacity: inherit; + z-index: 2; + pointer-events: none; +} +.win-container.win-selected .win-selectionborder { + top: 0; + left: 0; + right: 0; + bottom: 0; +} +.win-selectionbackground { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 0; +} +.win-selectioncheckmarkbackground { + position: absolute; + top: 2px; + right: 2px; + width: 14px; + height: 11px; + margin: 0; + padding: 0; + border-left-width: 2px; + border-right-width: 2px; + border-top-width: 4px; + border-bottom-width: 3px; + border-style: solid; + z-index: 3; + display: none; +} +.win-listview.win-rtl .win-selectioncheckmarkbackground, +.win-itemcontainer.win-rtl .win-selectioncheckmarkbackground { + left: 2px; + right: auto; +} +.win-selectionmode.win-itemcontainer .win-selectioncheckmarkbackground, +.win-selectionmode.win-itemcontainer.win-selectionmode .win-selectioncheckmark, +.win-selectionmode .win-itemcontainer .win-selectioncheckmarkbackground, +.win-selectionmode .win-itemcontainer.win-selectionmode .win-selectioncheckmark, +.win-listview .win-selectionmode .win-selectioncheckmarkbackground, +.win-listview .win-selectionmode .win-selectioncheckmark { + display: block; +} +.win-selectioncheckmark { + position: absolute; + margin: 0; + padding: 2px; + right: 1px; + top: 1px; + font-family: "Segoe MDL2 Assets", "Symbols"; + font-size: 14px; + z-index: 4; + line-height: 1; + display: none; +} +.win-rtl .win-selectioncheckmark { + right: auto; + left: 0px; +} +.win-selectionstylefilled.win-container, +.win-selectionstylefilled .win-container { + overflow: hidden; +} +.win-selectionmode .win-itemcontainer.win-container .win-itembox::after, +.win-selectionmode.win-itemcontainer.win-container .win-itembox::after, +.win-listview .win-surface.win-selectionmode .win-itembox::after { + content: ""; + position: absolute; + width: 18px; + height: 18px; + pointer-events: none; + right: 2px; + top: 2px; + z-index: 3; +} +.win-rtl .win-selectionmode .win-itemcontainer.win-container .win-itembox::after, +.win-itemcontainer.win-rtl.win-selectionmode.win-container .win-itembox::after, +.win-listview.win-rtl .win-surface.win-selectionmode .win-itembox::after { + right: auto; + left: 2px; +} +.win-listview.win-selectionstylefilled .win-surface.win-selectionmode .win-item { + transition: transform 250ms cubic-bezier(0.17, 0.79, 0.215, 1.0025); + -webkit-transition: -webkit-transform 250ms cubic-bezier(0.17, 0.79, 0.215, 1.0025); + transform: translate(40px, 0px); + -webkit-transform: translate(40px, 0px); +} +.win-listview.win-rtl.win-selectionstylefilled .win-surface.win-selectionmode .win-item { + transition: transform 250ms cubic-bezier(0.17, 0.79, 0.215, 1.0025); + -webkit-transition: -webkit-transform 250ms cubic-bezier(0.17, 0.79, 0.215, 1.0025); + transform: translate(-40px, 0px); + -webkit-transform: translate(-40px, 0px); +} +.win-listview.win-selectionstylefilled .win-surface.win-hidingselectionmode .win-item { + transition: transform 250ms cubic-bezier(0.17, 0.79, 0.215, 1.0025); + -webkit-transition: -webkit-transform 250ms cubic-bezier(0.17, 0.79, 0.215, 1.0025); + transform: none; + -webkit-transform: none; +} +.win-listview.win-rtl.win-selectionstylefilled .win-surface.win-hideselectionmode .win-item { + transition: transform 250ms cubic-bezier(0.17, 0.79, 0.215, 1.0025); + -webkit-transition: -webkit-transform 250ms cubic-bezier(0.17, 0.79, 0.215, 1.0025); + transform: none; + -webkit-transform: none; +} +.win-listview.win-selectionstylefilled .win-surface.win-selectionmode .win-itembox::after { + left: 12px; + right: auto; + top: 50%; + margin-top: -9px; + display: block; + border: 2px solid; + width: 16px; + height: 16px; +} +.win-listview.win-selectionstylefilled.win-rtl .win-surface.win-selectionmode .win-itembox::after { + left: auto; + right: 12px; +} +.win-listview.win-selectionstylefilled .win-surface.win-selectionmode .win-selectioncheckmarkbackground { + left: 12px; + top: 50%; + margin-top: -9px; + display: block; + border: 2px solid; + width: 16px; + height: 16px; +} +.win-listview.win-selectionstylefilled.win-rtl .win-surface.win-selectionmode .win-selectioncheckmarkbackground { + left: auto; + right: 12px; +} +.win-listview.win-selectionstylefilled .win-surface.win-selectionmode .win-selectioncheckmark { + left: 13px; + top: 50%; + margin-top: -8px; + display: block; + width: 14px; + height: 14px; +} +.win-listview.win-selectionstylefilled.win-rtl .win-surface.win-selectionmode .win-selectioncheckmark { + left: 0; + right: 10px; +} +.win-selectionmode .win-itemcontainer.win-selectionstylefilled.win-container .win-itembox.win-selected::after, +.win-itemcontainer.win-selectionmode.win-selectionstylefilled.win-container .win-itembox.win-selected::after, +.win-listview.win-selectionstylefilled .win-surface.win-selectionmode .win-itembox.win-nonselectable::after, +.win-listview .win-surface.win-selectionmode .win-itembox.win-selected::after { + display: none; +} +.win-listview .win-progress { + left: 50%; + top: 50%; + width: 60px; + height: 60px; + margin-left: -30px; + margin-top: -30px; + z-index: 1; + position: absolute; +} +.win-listview .win-progress::-ms-fill { + animation-name: -ms-ring; +} +.win-listview .win-itemsblock { + overflow: hidden; +} +.win-listview .win-surface.win-nocssgrid.win-gridlayout, +.win-listview .win-horizontal .win-nocssgrid.win-listlayout, +.win-listview .win-vertical .win-nocssgrid.win-listlayout.win-headerpositionleft { + display: -ms-inline-flexbox; + display: -webkit-inline-flex; + display: inline-flex; + vertical-align: top; +} +.win-listview .win-horizontal .win-surface.win-nocssgrid { + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-line-pack: start; + -webkit-align-content: flex-start; + align-content: flex-start; +} +.win-listview .win-vertical .win-surface.win-nocssgrid { + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row; + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-line-pack: start; + -webkit-align-content: flex-start; + align-content: flex-start; +} +.win-listview .win-vertical .win-structuralnodes.win-single-itemsblock.win-listlayout .win-itemscontainer.win-laidout, +.win-listview .win-horizontal .win-structuralnodes.win-single-itemsblock.win-listlayout .win-itemscontainer.win-laidout, +.win-listview .win-vertical .win-structuralnodes.win-single-itemsblock.win-gridlayout .win-uniformgridlayout.win-itemscontainer.win-laidout, +.win-listview .win-horizontal .win-structuralnodes.win-single-itemsblock.win-gridlayout .win-uniformgridlayout.win-itemscontainer.win-laidout { + display: block; +} +.win-listview .win-vertical .win-structuralnodes.win-single-itemsblock.win-listlayout .win-itemscontainer.win-laidout .win-itemscontainer-padder, +.win-listview .win-horizontal .win-structuralnodes.win-single-itemsblock.win-listlayout .win-itemscontainer.win-laidout .win-itemscontainer-padder, +.win-listview .win-vertical .win-structuralnodes.win-single-itemsblock.win-gridlayout .win-uniformgridlayout.win-itemscontainer.win-laidout .win-itemscontainer-padder, +.win-listview .win-horizontal .win-structuralnodes.win-single-itemsblock.win-gridlayout .win-uniformgridlayout.win-itemscontainer.win-laidout .win-itemscontainer-padder { + height: 0; + width: 0; +} +.win-listview.win-groups .win-vertical .win-listlayout.win-headerpositionleft .win-itemscontainer, +.win-listview.win-groups .win-vertical .win-listlayout.win-headerpositionleft .win-groupheadercontainer, +.win-listview.win-groups .win-horizontal .win-listlayout .win-itemscontainer, +.win-listview.win-groups .win-horizontal .win-listlayout .win-groupheadercontainer { + display: none; +} +.win-listview.win-groups .win-vertical .win-listlayout.win-headerpositionleft .win-itemscontainer.win-laidout, +.win-listview.win-groups .win-vertical .win-listlayout.win-headerpositionleft .win-groupheadercontainer.win-laidout, +.win-listview.win-groups .win-horizontal .win-listlayout .win-groupheadercontainer.win-laidout { + display: block; +} +.win-listview .win-listlayout .win-itemscontainer { + overflow: visible; +} +.win-listview .win-listlayout .win-itemsblock { + padding-bottom: 4px; + margin-bottom: -4px; +} +.win-listview > .win-vertical .win-listlayout.win-headerpositiontop .win-groupheader { + float: none; +} +.win-listview > .win-vertical .win-surface.win-listlayout { + margin-bottom: 5px; +} +.win-listview .win-vertical .win-listlayout.win-headerpositionleft.win-surface { + display: -ms-inline-grid; + -ms-grid-columns: auto 1fr; + -ms-grid-rows: auto; +} +.win-listview .win-vertical .win-listlayout.win-headerpositionleft .win-groupheadercontainer { + -ms-grid-column: 1; +} +.win-listview .win-vertical .win-listlayout.win-headerpositionleft .win-itemscontainer { + -ms-grid-column: 2; +} +.win-listview > .win-horizontal .win-surface.win-listlayout { + display: -ms-inline-grid; + -ms-grid-columns: auto; + -ms-grid-rows: auto; + vertical-align: top; +} +.win-listview .win-horizontal .win-listlayout .win-itemsblock { + height: 100%; +} +.win-listview .win-horizontal .win-listlayout .win-itemscontainer { + margin-bottom: 24px; +} +.win-listview .win-horizontal .win-listlayout .win-container { + height: calc(100% - 10px); +} +.win-listview > .win-horizontal .win-surface.win-listlayout.win-headerpositiontop { + -ms-grid-rows: auto 1fr; +} +.win-listview .win-horizontal .win-listlayout.win-headerpositiontop .win-groupheadercontainer { + -ms-grid-row: 1; +} +.win-listview .win-horizontal .win-listlayout.win-headerpositiontop .win-itemscontainer { + -ms-grid-row: 2; +} +.win-listview .win-gridlayout.win-surface { + display: -ms-inline-grid; + vertical-align: top; +} +.win-listview .win-gridlayout .win-container { + margin: 5px; +} +.win-listview .win-vertical .win-gridlayout.win-headerpositionleft .win-groupheadercontainer, +.win-listview .win-vertical .win-gridlayout.win-headerpositiontop .win-groupheadercontainer { + -ms-grid-column: 1; +} +.win-listview.win-groups .win-gridlayout .win-itemscontainer, +.win-listview.win-groups .win-gridlayout .win-groupheadercontainer { + display: none; +} +.win-listview.win-groups .win-gridlayout .win-groupheadercontainer.win-laidout { + display: block; +} +.win-listview .win-horizontal .win-gridlayout.win-headerpositiontop.win-surface { + -ms-grid-columns: auto; + -ms-grid-rows: auto 1fr; +} +.win-listview .win-horizontal .win-gridlayout.win-headerpositiontop .win-groupheadercontainer { + -ms-grid-row: 1; +} +.win-listview .win-horizontal .win-gridlayout.win-headerpositiontop .win-itemscontainer { + -ms-grid-row: 2; +} +.win-listview .win-horizontal .win-gridlayout.win-headerpositionleft.win-surface { + -ms-grid-columns: auto; + -ms-grid-rows: auto; +} +.win-listview .win-horizontal .win-gridlayout.win-headerpositionleft .win-groupheadercontainer { + -ms-grid-row: 1; +} +.win-listview .win-horizontal .win-gridlayout.win-headerpositionleft .win-itemscontainer { + -ms-grid-row: 1; +} +.win-listview .win-vertical .win-gridlayout.win-headerpositiontop.win-surface { + -ms-grid-columns: auto; + -ms-grid-rows: auto; +} +.win-listview .win-vertical .win-gridlayout.win-headerpositiontop .win-itemscontainer { + -ms-grid-column: 1; +} +.win-listview .win-vertical .win-gridlayout.win-headerpositionleft.win-surface { + -ms-grid-columns: auto 1fr; + -ms-grid-rows: auto; +} +.win-listview .win-vertical .win-gridlayout.win-headerpositionleft .win-itemscontainer { + -ms-grid-column: 2; +} +.win-listview .win-gridlayout.win-structuralnodes .win-uniformgridlayout.win-itemscontainer.win-laidout { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row; +} +.win-listview .win-horizontal .win-listlayout .win-itemscontainer, +.win-listview.win-groups .win-horizontal .win-listlayout .win-itemscontainer.win-laidout, +.win-listview .win-horizontal .win-listlayout .win-itemsblock, +.win-listview .win-horizontal .win-gridlayout .win-uniformgridlayout.win-itemscontainer.win-laidout, +.win-listview .win-horizontal .win-gridlayout .win-uniformgridlayout .win-itemsblock { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-line-pack: start; + -webkit-align-content: flex-start; + align-content: flex-start; +} +.win-listview .win-horizontal .win-itemscontainer-padder { + height: 100%; +} +.win-listview .win-horizontal .win-gridlayout .win-uniformgridlayout .win-itemsblock { + height: 100%; +} +.win-listview .win-horizontal .win-gridlayout .win-cellspanninggridlayout.win-itemscontainer.win-laidout { + display: -ms-grid; +} +.win-listview .win-vertical .win-gridlayout.win-structuralnodes .win-uniformgridlayout.win-itemscontainer.win-laidout { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; +} +.win-listview .win-vertical .win-gridlayout .win-uniformgridlayout.win-itemscontainer.win-laidout, +.win-listview .win-vertical .win-gridlayout .win-uniformgridlayout .win-itemsblock { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row; + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-line-pack: start; + -webkit-align-content: flex-start; + align-content: flex-start; +} +.win-listview .win-vertical .win-gridlayout .win-uniformgridlayout .win-itemsblock { + width: 100%; +} +.win-listview .win-cellspanninggridlayout .win-container.win-laidout { + display: block; +} +.win-listview .win-cellspanninggridlayout .win-container { + display: none; +} +.win-listview .win-itembox { + position: relative; +} +.win-listview.win-dragover .win-itembox { + transform: scale(0.86); + -webkit-transform: scale(0.86); +} +.win-listview .win-itembox.win-dragsource, +.win-itemcontainer .win-itembox.win-dragsource { + opacity: 0.5; + transition: opacity cubic-bezier(0.1, 0.9, 0.2, 1) 167ms, transform cubic-bezier(0.1, 0.9, 0.2, 1) 220ms; + -webkit-transition: opacity cubic-bezier(0.1, 0.9, 0.2, 1) 167ms, transform cubic-bezier(0.1, 0.9, 0.2, 1) 220ms; +} +.win-listview.win-dragover .win-itembox.win-dragsource { + opacity: 0; + transition: none; + -webkit-transition: none; +} +html.win-hoverable .win-listview.win-dragover .win-container:hover { + outline: none; +} +.win-listview .win-itembox { + transition: transform cubic-bezier(0.1, 0.9, 0.2, 1) 220ms; + -webkit-transition: -webkit-transform cubic-bezier(0.1, 0.9, 0.2, 1) 220ms; +} +.win-listview.win-groups > .win-vertical .win-surface.win-listlayout.win-headerpositionleft { + margin-left: 70px; +} +.win-listview.win-groups.win-rtl > .win-vertical .win-surface.win-listlayout.win-headerpositionleft { + margin-left: 0px; + margin-right: 70px; +} +.win-listview > .win-horizontal .win-surface.win-listlayout { + margin-left: 70px; +} +.win-listview.win-rtl > .win-horizontal .win-surface.win-listlayout { + margin-left: 0px; + margin-right: 70px; +} +.win-listview .win-vertical .win-gridlayout.win-surface { + margin-left: 20px; +} +.win-listview.win-rtl .win-vertical .win-gridlayout.win-surface { + margin-left: 0px; + margin-right: 20px; +} +.win-itemcontainer .win-itembox, +.win-itemcontainer.win-container { + position: relative; +} +.win-itemcontainer { + touch-action: pan-x pan-y pinch-zoom; +} +html.win-hoverable .win-listview .win-itembox:hover::before, +html.win-hoverable .win-itemcontainer .win-itembox:hover::before { + opacity: 0.4; +} +html.win-hoverable .win-listview .win-pressed .win-itembox:hover::before, +html.win-hoverable .win-itemcontainer .win-pressed .win-itembox:hover::before, +html.win-hoverable .win-listview .win-pressed.win-itembox:hover::before, +html.win-hoverable .win-itemcontainer .win-pressed.win-itembox:hover::before { + opacity: 0.6; +} +html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover, +html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover, +html.win-hoverable .win-selectionstylefilled .win-itemcontainer.win-container:hover { + outline: none; +} +.win-selectionstylefilled.win-itemcontainer .win-itembox, +.win-selectionstylefilled .win-itemcontainer .win-itembox, +.win-listview.win-selectionstylefilled .win-itembox { + background-color: transparent; +} +.win-listview.win-selectionstylefilled .win-container.win-selected .win-selectionborder, +.win-itemcontainer.win-selectionstylefilled.win-container.win-selected .win-selectionborder { + border-color: transparent; +} +.win-listview.win-selectionstylefilled .win-surface.win-selectionmode .win-itembox::after { + background-color: transparent; +} +.win-listview.win-selectionstylefilled .win-selectioncheckmarkbackground, +.win-itemcontainer.win-selectionstylefilled .win-selectioncheckmarkbackground { + border-color: transparent; +} +.win-listview.win-selectionstylefilled .win-selected a, +.win-listview.win-selectionstylefilled .win-selected progress, +.win-listview.win-selectionstylefilled .win-selected .win-rating .win-star.win-full, +.win-itemcontainer.win-selectionstylefilled.win-selected a, +.win-itemcontainer.win-selectionstylefilled.win-selected progress, +.win-itemcontainer.win-selectionstylefilled.win-selected .win-rating .win-star.win-full { + color: #ffffff; +} +.win-listview.win-selectionstylefilled .win-selected.win-selected a:hover:active, +.win-itemcontainer.win-selectionstylefilled.win-selected.win-selected a:hover:active { + color: rgba(255, 255, 255, 0.6); +} +html.win-hoverable .win-listview.win-selectionstylefilled .win-selected a:hover, +html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-selected a:hover { + color: rgba(255, 255, 255, 0.8); +} +.win-listview.win-selectionstylefilled .win-selected button, +.win-listview.win-selectionstylefilled .win-selected input[type=button], +.win-listview.win-selectionstylefilled .win-selected input[type=reset], +.win-listview.win-selectionstylefilled .win-selected input[type=text], +.win-listview.win-selectionstylefilled .win-selected input[type=password], +.win-listview.win-selectionstylefilled .win-selected input[type=email], +.win-listview.win-selectionstylefilled .win-selected input[type=number], +.win-listview.win-selectionstylefilled .win-selected input[type=tel], +.win-listview.win-selectionstylefilled .win-selected input[type=url], +.win-listview.win-selectionstylefilled .win-selected input[type=search], +.win-listview.win-selectionstylefilled .win-selected input::-ms-check, +.win-listview.win-selectionstylefilled .win-selected textarea, +.win-listview.win-selectionstylefilled .win-selected .win-textarea, +.win-listview.win-selectionstylefilled .win-selected select, +.win-itemcontainer.win-selectionstylefilled.win-selected button, +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=button], +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=reset], +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=text], +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=password], +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=email], +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=number], +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=tel], +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=url], +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=search], +.win-itemcontainer.win-selectionstylefilled.win-selected input::-ms-check, +.win-itemcontainer.win-selectionstylefilled.win-selected textarea, +.win-itemcontainer.win-selectionstylefilled.win-selected .win-textarea, +.win-itemcontainer.win-selectionstylefilled.win-selected select { + background-clip: border-box; + background-color: rgba(255, 255, 255, 0.8); + border-color: transparent; + color: #000000; +} +.win-listview.win-selectionstylefilled .win-selected button[type=submit], +.win-listview.win-selectionstylefilled .win-selected input[type=submit], +.win-itemcontainer.win-selectionstylefilled.win-selected button[type=submit], +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=submit] { + border-color: #ffffff; +} +.win-listview.win-selectionstylefilled .win-selected input[type=range]::-ms-fill-lower, +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=range]::-ms-fill-lower { + background-color: #ffffff; +} +.win-listview.win-selectionstylefilled .win-selected input[type=range]::-ms-thumb, +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=range]::-ms-thumb { + background-color: #000000; +} +.win-listview.win-selectionstylefilled .win-selected input[type=range]::-ms-fill-upper, +.win-listview.win-selectionstylefilled .win-selected progress, +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=range]::-ms-fill-upper, +.win-itemcontainer.win-selectionstylefilled.win-selected progress { + background-color: rgba(255, 255, 255, 0.16); +} +.win-listview.win-selectionstylefilled .win-selected progress:indeterminate, +.win-itemcontainer.win-selectionstylefilled.win-selected progress:indeterminate { + background-color: transparent; +} +.win-listview.win-selectionstylefilled .win-selected .win-rating .win-star.win-empty, +.win-itemcontainer.win-selectionstylefilled.win-selected .win-rating .win-star.win-empty { + color: rgba(255, 255, 255, 0.16); +} +.win-listview .win-viewport { + outline: none; +} +@media (-ms-high-contrast) { + .win-listview .win-groupheader { + color: WindowText; + } + .win-selectioncheckmark { + color: HighlightText; + } + .win-listview .win-focusedoutline, + .win-listview .win-groupheader, + .win-itemcontainer .win-focusedoutline { + outline-color: WindowText; + } + .win-listview.win-selectionstylefilled .win-itembox, + .win-itemcontainer.win-selectionstylefilled .win-itembox { + background-color: Window; + color: WindowText; + } + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover .win-itembox, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover .win-itembox { + background-color: Highlight; + color: HighlightText; + } + .win-listview.win-selectionstylefilled .win-container.win-selected .win-itembox, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container.win-selected:hover .win-itembox, + .win-itemcontainer.win-selectionstylefilled.win-container.win-selected .win-itembox, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container.win-selected:hover .win-itembox { + background-color: Highlight; + color: HighlightText; + } + .win-listview:not(.win-selectionstylefilled) .win-container.win-selected .win-selectionborder, + .win-itemcontainer:not(.win-selectionstylefilled).win-container.win-selected .win-selectionborder { + border-color: Highlight; + } + .win-listview.win-selectionstylefilled .win-container.win-selected .win-selectionborder, + .win-itemcontainer.win-selectionstylefilled.win-container.win-selected .win-selectionborder { + border-color: transparent; + } + html.win-hoverable .win-listview:not(.win-selectionstylefilled) .win-container.win-selected:hover .win-selectionborder, + html.win-hoverable .win-itemcontainer:not(.win-selectionstylefilled).win-container.win-selected:hover .win-selectionborder { + border-color: Highlight; + } + .win-listview.win-selectionstylefilled .win-selected .win-selectionbackground, + html.win-hoverable .win-listview.win-selectionstylefilled .win-selected:hover .win-selectionbackground, + .win-itemcontainer.win-selectionstylefilled.win-selected .win-selectionbackground, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-selected:hover .win-selectionbackground { + background-color: Highlight; + color: HighlightText; + } + .win-listview.win-selectionstylefilled .win-selectioncheckmarkbackground, + .win-itemcontainer.win-selectionstylefilled .win-selectioncheckmarkbackground { + border-color: transparent; + } + .win-listview.win-selectionstylefilled .win-selected a, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover a, + .win-listview.win-selectionstylefilled .win-selected progress, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover progress, + .win-listview.win-selectionstylefilled .win-selected .win-rating .win-star:after, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover .win-rating .win-star:after, + .win-itemcontainer.win-selectionstylefilled.win-selected a, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover a, + .win-itemcontainer.win-selectionstylefilled.win-selected progress, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover progress, + .win-itemcontainer.win-selectionstylefilled.win-selected .win-rating .win-star:after, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover .win-rating .win-star:after { + color: HighlightText; + } + .win-listview.win-selectionstylefilled .win-selected input, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover input, + .win-listview.win-selectionstylefilled .win-selected input::-ms-check, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover input::-ms-check, + .win-listview.win-selectionstylefilled .win-selected input::-ms-value, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover input::-ms-value, + .win-listview.win-selectionstylefilled .win-selected input::-ms-track, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover input::-ms-track, + .win-listview.win-selectionstylefilled .win-selected button, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover button, + .win-listview.win-selectionstylefilled .win-selected progress, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover progress, + .win-listview.win-selectionstylefilled .win-selected progress::-ms-fill, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover progress::-ms-fill, + .win-listview.win-selectionstylefilled .win-selected select, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover select, + .win-listview.win-selectionstylefilled .win-selected textarea, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover textarea, + .win-listview.win-selectionstylefilled.win-selected input, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover input, + .win-itemcontainer.win-selectionstylefilled.win-selected input::-ms-check, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover input::-ms-check, + .win-itemcontainer.win-selectionstylefilled.win-selected input::-ms-value, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover input::-ms-value, + .win-itemcontainer.win-selectionstylefilled.win-selected input::-ms-track, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover input::-ms-track, + .win-itemcontainer.win-selectionstylefilled.win-selected button, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover button, + .win-itemcontainer.win-selectionstylefilled.win-selected progress, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover progress, + .win-itemcontainer.win-selectionstylefilled.win-selected progress::-ms-fill, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover progress::-ms-fill, + .win-itemcontainer.win-selectionstylefilled.win-selected select, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover select, + .win-itemcontainer.win-selectionstylefilled.win-selected textarea, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover textarea { + border-color: HighlightText; + } + .win-listview.win-selectionstylefilled .win-selected input[type=range]::-ms-fill-lower, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover input[type=range]::-ms-fill-lower, + .win-listview.win-selectionstylefilled .win-selected progress::-ms-fill, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover progress::-ms-fill, + .win-itemcontainer.win-selectionstylefilled.win-selected input[type=range]::-ms-fill-lower, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover input[type=range]::-ms-fill-lower, + .win-itemcontainer.win-selectionstylefilled.win-selected progress::-ms-fill, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover progress::-ms-fill { + background-color: HighlightText; + } + .win-listview.win-selectionstylefilled .win-selected input[type=range]::-ms-fill-upper, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover input[type=range]::-ms-fill-upper, + .win-listview.win-selectionstylefilled .win-selected progress, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover progress, + .win-itemcontainer.win-selectionstylefilled.win-selected input[type=range]::-ms-fill-upper, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover input[type=range]::-ms-fill-upper, + .win-itemcontainer.win-selectionstylefilled.win-selected progress, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover progress { + background-color: Highlight; + } + .win-listview.win-selectionstylefilled .win-selected .win-rating .win-star.win-full:before, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover .win-rating .win-star.win-full:before, + .win-itemcontainer.win-selectionstylefilled.win-selected .win-rating .win-star.win-full:before, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover .win-rating .win-star.win-full:before { + color: ButtonFace; + } + .win-listview.win-selectionstylefilled .win-selected .win-rating .win-star.win-empty:before, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover .win-rating .win-star.win-empty:before, + .win-itemcontainer.win-selectionstylefilled.win-selected .win-rating .win-star.win-empty:before, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover .win-rating .win-star.win-empty:before { + color: Highlight; + } + html.win-hoverable .win-listview .win-container:hover, + html.win-hoverable .win-itemcontainer.win-container:hover { + outline: Highlight solid 3px; + } +} +.win-flipview { + overflow: hidden; + height: 400px; +} +.win-flipview .win-surface { + -ms-scroll-chaining: none; +} +.win-flipview .win-navleft { + left: 0%; + top: 50%; + margin-top: -19px; +} +.win-flipview .win-navright { + left: 100%; + top: 50%; + margin-left: -20px; + margin-top: -19px; +} +.win-flipview .win-navtop { + left: 50%; + top: 0%; + margin-left: -35px; +} +.win-flipview .win-navbottom { + left: 50%; + top: 100%; + margin-left: -35px; + margin-top: -36px; +} +.win-flipview .win-navbutton { + touch-action: manipulation; + border: none; + width: 20px; + height: 36px; + z-index: 1; + position: absolute; + font-family: "Segoe MDL2 Assets", "Symbols"; + font-size: 16px; + padding: 0; + min-width: 0; +} +.win-flipview .win-item, +.win-flipview .win-item > .win-template { + height: 100%; + width: 100%; + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -ms-flex-align: center; + -webkit-align-items: center; + align-items: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; +} +@media (-ms-high-contrast) { + .win-flipview .win-navbottom { + left: 50%; + top: 100%; + margin-left: -35px; + margin-top: -35px; + } + .win-flipview .win-navbutton { + background-color: ButtonFace; + color: ButtonText; + border: 2px solid ButtonText; + width: 65px; + height: 35px; + } + .win-flipview .win-navbutton.win-navbutton:hover:active, + .win-flipview .win-navbutton.win-navbutton:active { + background-color: ButtonText; + color: ButtonFace; + } + .win-flipview .win-navright { + margin-left: -65px; + } + html.win-hoverable .win-flipview .win-navbutton:hover { + background-color: Highlight; + color: HighlightText; + } +} +.win-datepicker { + display: -ms-inline-flexbox; + display: -webkit-inline-flex; + display: inline-flex; + height: auto; + width: auto; +} +.win-datepicker select { + min-width: 80px; + margin-top: 4px; + margin-bottom: 4px; +} +.win-datepicker .win-datepicker-month { + margin-right: 20px; +} +.win-datepicker .win-datepicker-date.win-order0, +.win-datepicker .win-datepicker-date.win-order1 { + margin-right: 20px; +} +.win-datepicker .win-datepicker-year.win-order0 { + margin-right: 20px; +} +.win-datepicker .win-datepicker-month:lang(ar), +.win-datepicker .win-datepicker-month:lang(dv), +.win-datepicker .win-datepicker-month:lang(fa), +.win-datepicker .win-datepicker-month:lang(he), +.win-datepicker .win-datepicker-month:lang(ku-Arab), +.win-datepicker .win-datepicker-month:lang(pa-Arab), +.win-datepicker .win-datepicker-month:lang(prs), +.win-datepicker .win-datepicker-month:lang(ps), +.win-datepicker .win-datepicker-month:lang(sd-Arab), +.win-datepicker .win-datepicker-month:lang(syr), +.win-datepicker .win-datepicker-month:lang(ug), +.win-datepicker .win-datepicker-month:lang(ur), +.win-datepicker .win-datepicker-month:lang(qps-plocm), +.win-datepicker .win-datepicker-date.win-order0:lang(ar), +.win-datepicker .win-datepicker-date.win-order0:lang(dv), +.win-datepicker .win-datepicker-date.win-order0:lang(fa), +.win-datepicker .win-datepicker-date.win-order0:lang(he), +.win-datepicker .win-datepicker-date.win-order0:lang(ku-Arab), +.win-datepicker .win-datepicker-date.win-order0:lang(pa-Arab), +.win-datepicker .win-datepicker-date.win-order0:lang(prs), +.win-datepicker .win-datepicker-date.win-order0:lang(ps), +.win-datepicker .win-datepicker-date.win-order0:lang(sd-Arab), +.win-datepicker .win-datepicker-date.win-order0:lang(syr), +.win-datepicker .win-datepicker-date.win-order0:lang(ug), +.win-datepicker .win-datepicker-date.win-order0:lang(ur), +.win-datepicker .win-datepicker-date.win-order0:lang(qps-plocm), +.win-datepicker .win-datepicker-date.win-order1:lang(ar), +.win-datepicker .win-datepicker-date.win-order1:lang(dv), +.win-datepicker .win-datepicker-date.win-order1:lang(fa), +.win-datepicker .win-datepicker-date.win-order1:lang(he), +.win-datepicker .win-datepicker-date.win-order1:lang(ku-Arab), +.win-datepicker .win-datepicker-date.win-order1:lang(pa-Arab), +.win-datepicker .win-datepicker-date.win-order1:lang(prs), +.win-datepicker .win-datepicker-date.win-order1:lang(ps), +.win-datepicker .win-datepicker-date.win-order1:lang(sd-Arab), +.win-datepicker .win-datepicker-date.win-order1:lang(syr), +.win-datepicker .win-datepicker-date.win-order1:lang(ug), +.win-datepicker .win-datepicker-date.win-order1:lang(ur), +.win-datepicker .win-datepicker-date.win-order1:lang(qps-plocm), +.win-datepicker .win-datepicker-year.win-order0:lang(ar), +.win-datepicker .win-datepicker-year.win-order0:lang(dv), +.win-datepicker .win-datepicker-year.win-order0:lang(fa), +.win-datepicker .win-datepicker-year.win-order0:lang(he), +.win-datepicker .win-datepicker-year.win-order0:lang(ku-Arab), +.win-datepicker .win-datepicker-year.win-order0:lang(pa-Arab), +.win-datepicker .win-datepicker-year.win-order0:lang(prs), +.win-datepicker .win-datepicker-year.win-order0:lang(ps), +.win-datepicker .win-datepicker-year.win-order0:lang(sd-Arab), +.win-datepicker .win-datepicker-year.win-order0:lang(syr), +.win-datepicker .win-datepicker-year.win-order0:lang(ug), +.win-datepicker .win-datepicker-year.win-order0:lang(ur), +.win-datepicker .win-datepicker-year.win-order0:lang(qps-plocm) { + margin-right: 0; + margin-left: 20px; +} +.win-timepicker { + display: -ms-inline-flexbox; + display: -webkit-inline-flex; + display: inline-flex; + height: auto; + width: auto; +} +.win-timepicker select { + min-width: 80px; + margin-top: 4px; + margin-bottom: 4px; +} +.win-timepicker .win-timepicker-hour { + margin-right: 20px; +} +.win-timepicker .win-timepicker-period.win-order0 { + margin-right: 20px; +} +.win-timepicker .win-timepicker-minute.win-order1 { + margin-right: 20px; +} +.win-timepicker .win-timepicker-period.win-order0:lang(ar), +.win-timepicker .win-timepicker-period.win-order0:lang(dv), +.win-timepicker .win-timepicker-period.win-order0:lang(fa), +.win-timepicker .win-timepicker-period.win-order0:lang(he), +.win-timepicker .win-timepicker-period.win-order0:lang(ku-Arab), +.win-timepicker .win-timepicker-period.win-order0:lang(pa-Arab), +.win-timepicker .win-timepicker-period.win-order0:lang(prs), +.win-timepicker .win-timepicker-period.win-order0:lang(ps), +.win-timepicker .win-timepicker-period.win-order0:lang(sd-Arab), +.win-timepicker .win-timepicker-period.win-order0:lang(syr), +.win-timepicker .win-timepicker-period.win-order0:lang(ug), +.win-timepicker .win-timepicker-period.win-order0:lang(ur), +.win-timepicker .win-timepicker-period.win-order0:lang(qps-plocm), +.win-timepicker .win-timepicker-hour:lang(ar), +.win-timepicker .win-timepicker-hour:lang(dv), +.win-timepicker .win-timepicker-hour:lang(fa), +.win-timepicker .win-timepicker-hour:lang(he), +.win-timepicker .win-timepicker-hour:lang(ku-Arab), +.win-timepicker .win-timepicker-hour:lang(pa-Arab), +.win-timepicker .win-timepicker-hour:lang(prs), +.win-timepicker .win-timepicker-hour:lang(ps), +.win-timepicker .win-timepicker-hour:lang(sd-Arab), +.win-timepicker .win-timepicker-hour:lang(syr), +.win-timepicker .win-timepicker-hour:lang(ug), +.win-timepicker .win-timepicker-hour:lang(ur), +.win-timepicker .win-timepicker-hour:lang(qps-plocm) { + margin-right: 0; + margin-left: 20px; +} +.win-timepicker .win-timepicker-minute.win-order1:lang(ar), +.win-timepicker .win-timepicker-minute.win-order1:lang(dv), +.win-timepicker .win-timepicker-minute.win-order1:lang(fa), +.win-timepicker .win-timepicker-minute.win-order1:lang(he), +.win-timepicker .win-timepicker-minute.win-order1:lang(ku-Arab), +.win-timepicker .win-timepicker-minute.win-order1:lang(pa-Arab), +.win-timepicker .win-timepicker-minute.win-order1:lang(prs), +.win-timepicker .win-timepicker-minute.win-order1:lang(ps), +.win-timepicker .win-timepicker-minute.win-order1:lang(sd-Arab), +.win-timepicker .win-timepicker-minute.win-order1:lang(syr), +.win-timepicker .win-timepicker-minute.win-order1:lang(ug), +.win-timepicker .win-timepicker-minute.win-order1:lang(ur), +.win-timepicker .win-timepicker-minute.win-order1:lang(qps-plocm), +.win-timepicker .win-timepicker-minute.win-order0:lang(ar), +.win-timepicker .win-timepicker-minute.win-order0:lang(dv), +.win-timepicker .win-timepicker-minute.win-order0:lang(fa), +.win-timepicker .win-timepicker-minute.win-order0:lang(he), +.win-timepicker .win-timepicker-minute.win-order0:lang(ku-Arab), +.win-timepicker .win-timepicker-minute.win-order0:lang(pa-Arab), +.win-timepicker .win-timepicker-minute.win-order0:lang(prs), +.win-timepicker .win-timepicker-minute.win-order0:lang(ps), +.win-timepicker .win-timepicker-minute.win-order0:lang(sd-Arab), +.win-timepicker .win-timepicker-minute.win-order0:lang(syr), +.win-timepicker .win-timepicker-minute.win-order0:lang(ug), +.win-timepicker .win-timepicker-minute.win-order0:lang(ur), +.win-timepicker .win-timepicker-minute.win-order0:lang(qps-plocm) { + margin-left: 20px; + margin-right: 0; +} +body > .win-navigation-backbutton { + position: absolute; + top: 50px; + left: 20px; +} +.win-backbutton, +.win-navigation-backbutton, +.win-back { + touch-action: manipulation; + display: inline-block; + min-width: 0; + min-height: 0; + padding: 0; + text-align: center; + width: 41px; + height: 41px; + font-size: 24px; + line-height: 41px; + vertical-align: baseline; +} +.win-backbutton::before, +.win-back::before { + font-family: "Segoe MDL2 Assets", "Symbols"; + font-weight: normal; + content: "\E0D5"; + vertical-align: 50%; +} +.win-backbutton:lang(ar)::before, +.win-backbutton:lang(dv)::before, +.win-backbutton:lang(fa)::before, +.win-backbutton:lang(he)::before, +.win-backbutton:lang(ku-Arab)::before, +.win-backbutton:lang(pa-Arab)::before, +.win-backbutton:lang(prs)::before, +.win-backbutton:lang(ps)::before, +.win-backbutton:lang(sd-Arab)::before, +.win-backbutton:lang(syr)::before, +.win-backbutton:lang(ug)::before, +.win-backbutton:lang(ur)::before, +.win-backbutton:lang(qps-plocm)::before, +.win-back:lang(ar)::before, +.win-back:lang(dv)::before, +.win-back:lang(fa)::before, +.win-back:lang(he)::before, +.win-back:lang(ku-Arab)::before, +.win-back:lang(pa-Arab)::before, +.win-back:lang(prs)::before, +.win-back:lang(ps)::before, +.win-back:lang(sd-Arab)::before, +.win-back:lang(syr)::before, +.win-back:lang(ug)::before, +.win-back:lang(ur)::before, +.win-back:lang(qps-plocm)::before { + content: "\E0AE"; +} +button.win-navigation-backbutton, +button.win-navigation-backbutton:active, +html.win-hoverable button.win-navigation-backbutton:enabled:hover, +button.win-navigation-backbutton:enabled:hover:active { + background-color: transparent; + border: none; +} +@media (-ms-high-contrast) { + button.win-navigation-backbutton, + button.win-navigation-backbutton:active, + html.win-hoverable button.win-navigation-backbutton:enabled:hover, + button.win-navigation-backbutton:enabled:hover:active { + /* Overwrite default background and border styles from BackButton control's ]]> + /// The BackButton control itself + /// The Back Arrow glyph + /// + /// + BackButton: _Base.Namespace._lazy(function () { + // Statics + var strings = { + get ariaLabel() { return _Resources._getWinJSString("ui/backbuttonarialabel").value; }, + get duplicateConstruction() { return "Invalid argument: Controls may only be instantiated one time for each DOM element"; }, + get badButtonElement() { return "Invalid argument: For a button, toggle, or flyout command, the element must be null or a button element"; } + }; + + var BackButton = _Base.Class.define(function BackButton_ctor(element, options) { + /// + /// + /// Creates a new BackButton control + /// + /// + /// The DOM element that will host the control. If this parameter is null, this constructor creates one for you. + /// + /// + /// An object that contains one or more property/value pairs to apply to the new control. Each property of the options object corresponds to + /// one of the control's properties or events. + /// + /// + /// A BackButton control. + /// + /// + /// + + // Check to make sure we weren't duplicated + if (element && element.winControl) { + throw new _ErrorFromName("WinJS.UI.BackButton.DuplicateConstruction", strings.duplicateConstruction); + } + + this._element = element || _Global.document.createElement("button"); + options = options || {}; + + this._initializeButton(); // This will also set the aria-label and tooltip + + this._disposed = false; + + // Remember ourselves + this._element.winControl = this; + + _Control.setOptions(this, options); + + // Add event handlers for this back button instance + this._buttonClickHandler = this._handleBackButtonClick.bind(this); + this._element.addEventListener('click', this._buttonClickHandler, false); + this._navigatedHandler = this._handleNavigatedEvent.bind(this); + Navigation.addEventListener('navigated', this._navigatedHandler, false); + + // Increment reference count / manage add global event handlers + singleton.addRef(); + }, { + + /// + element: { + get: function () { + return this._element; + } + }, + + dispose: function () { + /// + /// + /// Disposes this control. + /// + /// + /// + if (this._disposed) { + return; + } + this._disposed = true; // Mark this control as disposed. + + // Remove 'navigated' eventhandler for this BackButton + Navigation.removeEventListener('navigated', this._navigatedHandler, false); + + singleton.release(); // Decrement reference count. + + }, + + refresh: function () { + /// + /// + /// Sets the 'disabled' attribute to correct the value based on the current navigation history stack. + /// + /// + /// + if (Navigation.canGoBack) { + this._element.disabled = false; + } else { + this._element.disabled = true; + } + }, + + _initializeButton: function () { + //Final EN-US HTML should be: + // + //Button will automatically be disabled if WinJS.Navigation.history.canGoBack is false. + + // Verify the HTML is a button + if (this._element.tagName !== "BUTTON") { + throw new _ErrorFromName("WinJS.UI.BackButton.BadButtonElement", strings.badButtonElement); + } + + // Attach our css classes + _ElementUtilities.addClass(this._element, navigationBackButtonClass); + + // Attach disposable class. + _ElementUtilities.addClass(this._element, "win-disposable"); + + // Create inner glyph element + this._element.innerHTML = ''; + + // Set the 'disabled' property to the correct value based on the current navigation history stack. + this.refresh(); + + // Set Aria-label and native tooltip to the same localized string equivalent of "Back" + this._element.setAttribute("aria-label", strings.ariaLabel); + this._element.setAttribute("title", strings.ariaLabel); + + // Explicitly set type attribute to avoid the default '; + this._headerTabStopElement = this._headerElement.firstElementChild; + // The purpose of headerWrapperElement is to lay out its children in a flexbox. Ideally, this flexbox would + // be on headerTabStopElement. However, firefox lays out flexboxes with display:flex differently. + // Firefox bug 1014285 (Button with display:inline-flex doesn't layout properly) + // https://bugzilla.mozilla.org/show_bug.cgi?id=1014285 + this._headerWrapperElement = this._headerTabStopElement.firstElementChild; + this._headerContentElement = this._headerWrapperElement.firstElementChild; + this._headerChevronElement = this._headerWrapperElement.lastElementChild; + element.appendChild(this._headerElement); + + this._winKeyboard = new _KeyboardBehavior._WinKeyboard(this._headerElement); + + this._contentElement = _Global.document.createElement("DIV"); + this._contentElement.className = HubSection._ClassName.hubSectionContent; + this._contentElement.style.visibility = "hidden"; + element.appendChild(this._contentElement); + + // Reparent any existing elements inside the new hub section content element. + var elementToMove = this.element.firstChild; + while (elementToMove !== this._headerElement) { + var nextElement = elementToMove.nextSibling; + this._contentElement.appendChild(elementToMove); + elementToMove = nextElement; + } + + this._processors = [ControlProcessor.processAll]; + + _Control.setOptions(this, options); + }, { + /// + element: { + get: function () { + return this._element; + } + }, + /// + /// Gets or sets a value that specifies whether the header is static. Set this value to true to disable clicks and other interactions. + /// + /// + isHeaderStatic: { + get: function () { + return this._isHeaderStatic; + }, + set: function (value) { + this._isHeaderStatic = value; + if (!this._isHeaderStatic) { + this._headerTabStopElement.setAttribute("role", "link"); + _ElementUtilities.addClass(this._headerTabStopElement, HubSection._ClassName.hubSectionInteractive); + } else { + this._headerTabStopElement.setAttribute("role", "heading"); + _ElementUtilities.removeClass(this._headerTabStopElement, HubSection._ClassName.hubSectionInteractive); + } + } + }, + /// + /// Gets the DOM element that hosts the HubSection's content. + /// + /// + contentElement: { + get: function () { + return this._contentElement; + } + }, + /// + /// Get or set the HubSection's header. After you set this property, the Hub renders the header again. + /// + /// + header: { + get: function () { + return this._header; + }, + set: function (value) { + // Render again even if it is equal to itself. + this._header = value; + this._renderHeader(); + } + }, + _setHeaderTemplate: function HubSection_setHeaderTemplate(template) { + this._template = _ElementUtilities._syncRenderer(template); + this._renderHeader(); + }, + _renderHeader: function HubSection_renderHeader() { + if (this._template) { + _Dispose._disposeElement(this._headerContentElement); + _ElementUtilities.empty(this._headerContentElement); + this._template(this, this._headerContentElement); + } + }, + _process: function HubSection_process() { + var that = this; + + this._processed = (this._processors || []).reduce(function (promise, processor) { + return promise.then(function () { + return processor(that.contentElement); + }); + }, this._processed || Promise.as()); + this._processors = null; + + return this._processed; + }, + dispose: function HubSection_dispose() { + /// + /// + /// Disposes this control. + /// + /// + /// + if (this._disposed) { + return; + } + this._disposed = true; + this._processors = null; + + _Dispose._disposeElement(this._headerContentElement); + _Dispose.disposeSubTree(this.contentElement); + } + }, { + // Names of classes used by the HubSection. + _ClassName: { + hubSection: "win-hub-section", + hubSectionHeader: "win-hub-section-header", + hubSectionHeaderTabStop: "win-hub-section-header-tabstop", + hubSectionHeaderWrapper: "win-hub-section-header-wrapper", + hubSectionInteractive: "win-hub-section-header-interactive", + hubSectionHeaderContent: "win-hub-section-header-content", + hubSectionHeaderChevron: "win-hub-section-header-chevron", + hubSectionContent: "win-hub-section-content" + }, + isDeclarativeControlContainer: _BaseUtils.markSupportedForProcessing(function (section, callback) { + if (callback === ControlProcessor.processAll) { + return; + } + + section._processors = section._processors || []; + section._processors.push(callback); + + // Once processed the first time synchronously queue up new processors as they come in + if (section._processed) { + section._process(); + } + }) + }); + + return HubSection; + }) + }); + +}); + + +define('require-style!less/styles-hub',[],function(){}); + +define('require-style!less/colors-hub',[],function(){}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('WinJS/Controls/Hub',[ + '../Core/_Global', + '../Core/_Base', + '../Core/_BaseUtils', + '../Core/_ErrorFromName', + '../Core/_Events', + '../Core/_Log', + '../Core/_Resources', + '../Core/_WriteProfilerMark', + '../_Accents', + '../Animations', + '../Animations/_TransitionAnimation', + '../BindingList', + '../ControlProcessor', + '../Promise', + '../_Signal', + '../Scheduler', + '../Utilities/_Control', + '../Utilities/_ElementUtilities', + '../Utilities/_Hoverable', + '../Utilities/_UI', + './Hub/_Section', + 'require-style!less/styles-hub', + 'require-style!less/colors-hub' +], function hubInit(_Global, _Base, _BaseUtils, _ErrorFromName, _Events, _Log, _Resources, _WriteProfilerMark, _Accents, Animations, _TransitionAnimation, BindingList, ControlProcessor, Promise, _Signal, Scheduler, _Control, _ElementUtilities, _Hoverable, _UI, _Section) { + "use strict"; + + _Accents.createAccentRule( + ".win-semanticzoom-zoomedoutview .win-hub-section-header-interactive .win-hub-section-header-content,\ + .win-hub-section-header-interactive .win-hub-section-header-chevron", + [{ name: "color", value: _Accents.ColorTypes.accent }]); + + _Base.Namespace.define("WinJS.UI", { + /// + /// + /// Displays sections of content. + /// + /// + /// + /// + /// + /// + ///
HubSection Content
+ /// ]]>
+ /// Raised when the Hub is about to play an entrance or a transition animation. + /// Raised when a header is invoked. + /// Raised when the loading state changes. + /// The entire Hub control. + /// The progress indicator for the Hub. + /// The viewport of the Hub. + /// The scrollable region of the Hub. + /// + /// + Hub: _Base.Namespace._lazy(function () { + var Key = _ElementUtilities.Key; + + function hubDefaultHeaderTemplate(section) { + var element = _Global.document.createTextNode(typeof section.header === "object" ? JSON.stringify(section.header) : ('' + section.header)); + return element; + } + + var createEvent = _Events._createEventProperty; + var eventNames = { + contentAnimating: "contentanimating", + headerInvoked: "headerinvoked", + loadingStateChanged: "loadingstatechanged" + }; + + // Delay time before progress dots are shown when loading hub section(s) on screen. + var progressDelay = 500; + + var verticalNames = { + scrollPos: "scrollTop", + scrollSize: "scrollHeight", + offsetPos: "offsetTop", + offsetSize: "offsetHeight", + oppositeOffsetSize: "offsetWidth", + marginStart: "marginTop", + marginEnd: "marginBottom", + borderStart: "borderTopWidth", + borderEnd: "borderBottomWidth", + paddingStart: "paddingTop", + paddingEnd: "paddingBottom" + }; + var rtlHorizontalNames = { + scrollPos: "scrollLeft", + scrollSize: "scrollWidth", + offsetPos: "offsetLeft", + offsetSize: "offsetWidth", + oppositeOffsetSize: "offsetHeight", + marginStart: "marginRight", + marginEnd: "marginLeft", + borderStart: "borderRightWidth", + borderEnd: "borderLeftWidth", + paddingStart: "paddingRight", + paddingEnd: "paddingLeft" + }; + var ltrHorizontalNames = { + scrollPos: "scrollLeft", + scrollSize: "scrollWidth", + offsetPos: "offsetLeft", + offsetSize: "offsetWidth", + oppositeOffsetSize: "offsetHeight", + marginStart: "marginLeft", + marginEnd: "marginRight", + borderStart: "borderLeftWidth", + borderEnd: "borderRightWidth", + paddingStart: "paddingLeft", + paddingEnd: "paddingRight" + }; + + var Hub = _Base.Class.define(function Hub_ctor(element, options) { + /// + /// + /// Creates a new Hub control. + /// + /// + /// The DOM element that hosts the Hub control. + /// + /// + /// An object that contains one or more property/value pairs to apply to the new control. + /// Each property of the options object corresponds to one of the control's properties or events. + /// Event names must begin with "on". For example, to provide a handler for the contentanimating event, + /// add a property named "oncontentanimating" to the options object and set its value to the event handler. + /// + /// + /// The new Hub. + /// + /// + /// + element = element || _Global.document.createElement("DIV"); + options = options || {}; + + if (element.winControl) { + throw new _ErrorFromName("WinJS.UI.Hub.DuplicateConstruction", strings.duplicateConstruction); + } + + this._id = element.id || _ElementUtilities._uniqueID(element); + this._writeProfilerMark("constructor,StartTM"); + + this._windowKeyDownHandlerBound = this._windowKeyDownHandler.bind(this); + _Global.addEventListener('keydown', this._windowKeyDownHandlerBound); + + // Attaching JS control to DOM element + element.winControl = this; + this._element = element; + _ElementUtilities.addClass(this.element, Hub._ClassName.hub); + _ElementUtilities.addClass(this.element, "win-disposable"); + + this._viewportElement = _Global.document.createElement("DIV"); + this._viewportElement.className = Hub._ClassName.hubViewport; + this._element.appendChild(this._viewportElement); + this._viewportElement.setAttribute("role", "group"); + this._viewportElement.setAttribute("aria-label", strings.hubViewportAriaLabel); + + this._surfaceElement = _Global.document.createElement("DIV"); + this._surfaceElement.className = Hub._ClassName.hubSurface; + this._viewportElement.appendChild(this._surfaceElement); + + // Start invisible so that you do not see the content loading until the sections are ready. + this._visible = false; + this._viewportElement.style.opacity = 0; + + if (!options.orientation) { + this._orientation = _UI.Orientation.horizontal; + _ElementUtilities.addClass(this.element, Hub._ClassName.hubHorizontal); + } + + this._fireEntrance = true; + this._animateEntrance = true; + this._loadId = 0; + this.runningAnimations = new Promise.wrap(); + this._currentIndexForSezo = 0; + + // This internally assigns this.sections which causes section to be used (even from options) before + // scrollPosition or sectionOnScreen. + this._parse(); + + _Control.setOptions(this, options); + + _ElementUtilities._addEventListener(this.element, "focusin", this._focusin.bind(this), false); + this.element.addEventListener("keydown", this._keyDownHandler.bind(this)); + this.element.addEventListener("click", this._clickHandler.bind(this)); + this._resizeHandlerBound = this._resizeHandler.bind(this); + this.element.addEventListener("mselementresize", this._resizeHandlerBound); + _ElementUtilities._resizeNotifier.subscribe(this.element, this._resizeHandlerBound); + this._viewportElement.addEventListener("scroll", this._scrollHandler.bind(this)); + this._surfaceElement.addEventListener("mselementresize", this._contentResizeHandler.bind(this)); + + this._handleSectionChangedBind = this._handleSectionChanged.bind(this); + this._handleSectionInsertedBind = this._handleSectionInserted.bind(this); + this._handleSectionMovedBind = this._handleSectionMoved.bind(this); + this._handleSectionRemovedBind = this._handleSectionRemoved.bind(this); + this._handleSectionReloadBind = this._handleSectionReload.bind(this); + + this._refresh(); + + this._writeProfilerMark("constructor,StopTM"); + }, { + /// + element: { + get: function () { + return this._element; + } + }, + /// + /// Gets or sets the orientation of sections within the Hub. + /// + /// + orientation: { + get: function () { + return this._orientation; + }, + set: function (value) { + if (value === this._orientation) { + return; + } + this._measured = false; + // clear existing scroll before we switch orientation + if (this._names) { // handle setting orientation before we measure + var newScrollPos = {}; + newScrollPos[this._names.scrollPos] = 0; + _ElementUtilities.setScrollPosition(this._viewportElement, newScrollPos); + } + if (value === _UI.Orientation.vertical) { + _ElementUtilities.removeClass(this.element, Hub._ClassName.hubHorizontal); + _ElementUtilities.addClass(this.element, Hub._ClassName.hubVertical); + } else { + value = _UI.Orientation.horizontal; + _ElementUtilities.removeClass(this.element, Hub._ClassName.hubVertical); + _ElementUtilities.addClass(this.element, Hub._ClassName.hubHorizontal); + } + this._orientation = value; + Scheduler.schedule(this._updateSnapList.bind(this), Scheduler.Priority.idle); + } + }, + /// + /// Gets or sets the WinJS.Binding.List of HubSection objects that belong to this Hub. + /// + /// + sections: { + get: function () { + if (this._pendingSections) { + return this._pendingSections; + } + return this._sections; + }, + set: function (value) { + var resetScrollPosition = !this._pendingSections; + this._pendingSections = value; + this._refresh(); + if (resetScrollPosition) { + this.scrollPosition = 0; + } + } + }, + /// + /// Gets or sets the WinJS.Binding.Template or template function that creates the DOM elements + /// which represent the header for each HubSection. Each header can + /// contain multiple DOM elements, but we recommend that it have a single + /// root element. + /// + /// + headerTemplate: { + get: function () { + if (this._pendingHeaderTemplate) { + return this._pendingHeaderTemplate; + } + + if (!this._headerTemplate) { + this._headerTemplate = hubDefaultHeaderTemplate; + } + + return this._headerTemplate; + }, + set: function (value) { + this._pendingHeaderTemplate = value || hubDefaultHeaderTemplate; + this._refresh(); + } + }, + /// + /// Gets or sets the position of the Hub's scrollbar. + /// + /// + scrollPosition: { + get: function () { + if (+this._pendingScrollLocation === this._pendingScrollLocation) { + return this._pendingScrollLocation; + } + + this._measure(); + return this._scrollPosition; + }, + set: function (value) { + value = Math.max(0, value); + if (this._pendingRefresh) { + // Unable to constrain length because sections may have changed. + this._pendingScrollLocation = value; + this._pendingSectionOnScreen = null; + } else { + this._measure(); + var targetScrollPos = Math.max(0, Math.min(this._scrollLength - this._viewportSize, value)); + this._scrollPosition = targetScrollPos; + var newScrollPos = {}; + newScrollPos[this._names.scrollPos] = targetScrollPos; + _ElementUtilities.setScrollPosition(this._viewportElement, newScrollPos); + } + } + }, + + /// + /// Gets or sets the index of first section in view. This property is useful for restoring a previous view when your app launches or resumes. + /// + /// + sectionOnScreen: { + get: function () { + if (+this._pendingSectionOnScreen === this._pendingSectionOnScreen) { + return this._pendingSectionOnScreen; + } + + this._measure(); + for (var i = 0; i < this._sectionSizes.length; i++) { + var sectionSize = this._sectionSizes[i]; + if ((sectionSize.offset + sectionSize.size - sectionSize.borderEnd - sectionSize.paddingEnd) > (this._scrollPosition + this._startSpacer + sectionSize.borderStart + sectionSize.paddingStart)) { + return i; + } + } + return -1; + }, + set: function (value) { + value = Math.max(0, value); + if (this._pendingRefresh) { + this._pendingSectionOnScreen = value; + this._pendingScrollLocation = null; + } else { + this._measure(); + if (value >= 0 && value < this._sectionSizes.length) { + this._scrollToSection(value); + } + } + } + }, + /// + /// Gets or sets the index of first section at least partially in view. Use for animations. + /// + /// + indexOfFirstVisible: { + get: function () { + this._measure(); + for (var i = 0; i < this._sectionSizes.length; i++) { + var sectionSize = this._sectionSizes[i]; + if ((sectionSize.offset + sectionSize.size - sectionSize.borderEnd - sectionSize.paddingEnd) > this._scrollPosition) { + return i; + } + } + return -1; + } + }, + /// + /// Gets or sets the index of last section at least partially in view. Use for animations. + /// + /// + indexOfLastVisible: { + get: function () { + this._measure(); + for (var i = this._sectionSizes.length - 1; i >= 0; i--) { + var sectionSize = this._sectionSizes[i]; + if ((sectionSize.offset + sectionSize.paddingStart + sectionSize.borderStart) < (this._scrollPosition + this._viewportSize)) { + return i; + } + } + return -1; + } + }, + + /// + /// Raised when the user clicks on an interactive header. + /// + /// + onheaderinvoked: createEvent(eventNames.headerInvoked), + + /// + /// Raised when the loadingState of the Hub changes. + /// + /// + onloadingstatechanged: createEvent(eventNames.loadingStateChanged), + + /// + /// Raised when Hub is about to play entrance, contentTransition, insert, or remove animations. + /// + /// + oncontentanimating: createEvent(eventNames.contentAnimating), + + _refresh: function hub_refresh() { + if (this._pendingRefresh) { + return; + } + + this._loadId++; + this._setState(Hub.LoadingState.loading); + // This is to coalesce property setting operations such as sections and scrollPosition. + this._pendingRefresh = true; + + Scheduler.schedule(this._refreshImpl.bind(this), Scheduler.Priority.high); + }, + _refreshImpl: function hub_refreshImpl() { + if (this._disposed) { + return; + } + + var fadeOutAnimation = Promise.wrap(); + if (this._pendingSections) { + this._animateEntrance = true; + this._fireEntrance = !this._visible; + if (!this._fireEntrance) { + this._visible = false; + this._viewportElement.style.opacity = 0; + + if (_TransitionAnimation.isAnimationEnabled()) { + var animateTransition = this._fireEvent(Hub._EventName.contentAnimating, { + type: Hub.AnimationType.contentTransition + }); + + if (animateTransition) { + this._viewportElement.style["-ms-overflow-style"] = "none"; + fadeOutAnimation = Animations.fadeOut(this._viewportElement).then(function () { + this._viewportElement.style["-ms-overflow-style"] = ""; + }.bind(this)); + } + this._animateEntrance = animateTransition; + } + } + } + + fadeOutAnimation.done(this._applyProperties.bind(this)); + }, + _applyProperties: function hub_applyProperties() { + if (this._disposed) { + return; + } + + this._pendingRefresh = false; + + var needsToLoadSections = false; + if (this._pendingSections) { + needsToLoadSections = true; + this._updateEvents(this._sections, this._pendingSections); + this._sections = this._pendingSections; + this._pendingSections = null; + // Remove any declaratively specified hub sections before attachSections. + while (this.element.firstElementChild !== this._viewportElement) { + var toRemove = this.element.firstElementChild; + toRemove.parentNode.removeChild(toRemove); + } + _ElementUtilities.empty(this._surfaceElement); + } + + if (this._pendingHeaderTemplate) { + this._headerTemplate = this._pendingHeaderTemplate; + this._pendingHeaderTemplate = null; + } + + this._assignHeaderTemplate(); + + if (needsToLoadSections) { + this._attachSections(); + } + + // Scroll after headers are rendered and sections are attached so the scroll thumb is correct. + if (+this._pendingSectionOnScreen === this._pendingSectionOnScreen) { + // If there are both pending section on screen and scroll location use section on screen. + this.sectionOnScreen = this._pendingSectionOnScreen; + } else if (+this._pendingScrollLocation === this._pendingScrollLocation) { + this.scrollPosition = this._pendingScrollLocation; + } else { + // Sections reset without sectionOnScreen or scrollPosition APIs. + this.scrollPosition = 0; + } + + this._pendingSectionOnScreen = null; + this._pendingScrollLocation = null; + + // Using current (or new) scroll location load the sections + this._setState(Hub.LoadingState.loading); + this._loadSections(); + }, + _handleSectionChanged: function hub_handleSectionChanged(ev) { + // Change is triggered by binding list setAt() API. + if (this._pendingSections) { + return; + } + + var newSection = ev.detail.newValue; + var oldSection = ev.detail.oldValue; + newSection._setHeaderTemplate(this.headerTemplate); + if (newSection.element !== oldSection.element) { + if (newSection.element.parentNode === this._surfaceElement) { + throw new _ErrorFromName("WinJS.UI.Hub.DuplicateSection", strings.duplicateSection); + } + + this._surfaceElement.insertBefore(newSection.element, oldSection.element); + this._surfaceElement.removeChild(oldSection.element); + this._measured = false; + + this._setState(Hub.LoadingState.loading); + this._loadSections(); + } + }, + _handleSectionInserted: function hub_handleSectionInserted(ev) { + // Insert is triggered by binding list insert APIs such as splice(), push(), and unshift(). + if (this._pendingSections) { + return; + } + + var index = ev.detail.index; + var section = ev.detail.value; + + if (section._animation) { + section._animation.cancel(); + } + + var animation; + var result = this._fireEvent(Hub._EventName.contentAnimating, { + type: Hub.AnimationType.insert, + index: index, + section: section + }); + + if (result) { + + var affectedElements = []; + + for (var i = index + 1; i < this.sections.length; i++) { + affectedElements.push(this.sections.getAt(i).element); + } + + animation = new Animations._createUpdateListAnimation([section.element], [], affectedElements); + } + + if (section.element.parentNode === this._surfaceElement) { + throw new _ErrorFromName("WinJS.UI.Hub.DuplicateSection", strings.duplicateSection); + } + + section._setHeaderTemplate(this.headerTemplate); + if (index < this.sections.length - 1) { + this._surfaceElement.insertBefore(section.element, this.sections.getAt(index + 1).element); + } else { + this._surfaceElement.appendChild(section.element); + } + this._measured = false; + + if (animation) { + var insertAnimation = animation.execute(); + this.runningAnimations = Promise.join([this.runningAnimations, insertAnimation]); + } + + this._setState(Hub.LoadingState.loading); + this._loadSections(); + }, + _handleSectionMoved: function hub_handleSectionMoved(ev) { + // Move is triggered by binding list move() API. + if (this._pendingSections) { + return; + } + + var newIndex = ev.detail.newIndex; + var section = ev.detail.value; + + if (newIndex < this.sections.length - 1) { + this._surfaceElement.insertBefore(section.element, this.sections.getAt(newIndex + 1).element); + } else { + this._surfaceElement.appendChild(section.element); + } + this._measured = false; + + this._setState(Hub.LoadingState.loading); + this._loadSections(); + }, + _handleSectionRemoved: function hub_handleSectionRemoved(ev) { + // Removed is triggered by binding list removal APIs such as splice(), pop(), and shift(). + if (this._pendingSections) { + return; + } + + var section = ev.detail.value; + var index = ev.detail.index; + + var animationPromise = Promise.wrap(); + var result = this._fireEvent(Hub._EventName.contentAnimating, { + type: Hub.AnimationType.remove, + index: index, + section: section + }); + + if (result) { + var affectedElements = []; + + for (var i = index; i < this.sections.length; i++) { + affectedElements.push(this.sections.getAt(i).element); + } + + var animation = new Animations._createUpdateListAnimation([], [section.element], affectedElements); + + this._measure(); + var offsetTop = section.element.offsetTop; + var offsetLeft = section.element.offsetLeft; + section.element.style.position = "absolute"; + section.element.style.top = offsetTop; + section.element.style.left = offsetLeft; + section.element.style.opacity = 0; + this._measured = false; + + animationPromise = animation.execute().then(function () { + section.element.style.position = ""; + section.element.style.top = ""; + section.element.style.left = ""; + section.element.style.opacity = 1; + }.bind(this)); + } + + animationPromise.done(function () { + if (!this._disposed) { + this._surfaceElement.removeChild(section.element); + this._measured = false; + } + }.bind(this)); + + // Store animation promise in case it is inserted before remove animation finishes. + section._animation = animationPromise; + this.runningAnimations = Promise.join([this.runningAnimations, animationPromise]); + + this._setState(Hub.LoadingState.loading); + this._loadSections(); + }, + _handleSectionReload: function hub_handleSectionReload() { + // Reload is triggered by large operations on the binding list such as reverse(). This causes + // _pendingSections to be true which ignores future insert/remove/modified/moved events until the new + // sections list is applied. + this.sections = this.sections; + }, + _updateEvents: function hub_updateEvents(oldSections, newSections) { + if (oldSections) { + oldSections.removeEventListener("itemchanged", this._handleSectionChangedBind); + oldSections.removeEventListener("iteminserted", this._handleSectionInsertedBind); + oldSections.removeEventListener("itemmoved", this._handleSectionMovedBind); + oldSections.removeEventListener("itemremoved", this._handleSectionRemovedBind); + oldSections.removeEventListener("reload", this._handleSectionReloadBind); + } + + if (newSections) { + newSections.addEventListener("itemchanged", this._handleSectionChangedBind); + newSections.addEventListener("iteminserted", this._handleSectionInsertedBind); + newSections.addEventListener("itemmoved", this._handleSectionMovedBind); + newSections.addEventListener("itemremoved", this._handleSectionRemovedBind); + newSections.addEventListener("reload", this._handleSectionReloadBind); + } + }, + _attachSections: function hub_attachSections() { + this._measured = false; + for (var i = 0; i < this.sections.length; i++) { + var section = this._sections.getAt(i); + if (section._animation) { + section._animation.cancel(); + } + if (section.element.parentNode === this._surfaceElement) { + throw new _ErrorFromName("WinJS.UI.Hub.DuplicateSection", strings.duplicateSection); + } + this._surfaceElement.appendChild(section.element); + } + }, + _assignHeaderTemplate: function hub_assignHeaderTemplate() { + this._measured = false; + for (var i = 0; i < this.sections.length; i++) { + var section = this._sections.getAt(i); + section._setHeaderTemplate(this.headerTemplate); + } + }, + _loadSection: function hub_loadSection(index) { + var section = this._sections.getAt(index); + return section._process().then(function resetVisibility() { + var style = section.contentElement.style; + if (style.visibility !== "") { + style.visibility = ""; + } + }); + }, + _loadSections: function hub_loadSections() { + // Used to know if another load has interrupted this one. + this._loadId++; + var loadId = this._loadId; + var that = this; + var onScreenItemsAnimatedPromise = Promise.wrap(); + var sectionIndicesToLoad = []; + var allSectionsLoadedPromise = Promise.wrap(); + + function loadNextSectionAfterPromise(promise) { + promise.then(function () { + Scheduler.schedule(loadNextSection, Scheduler.Priority.idle); + }); + } + + function loadNextSection() { + if (loadId === that._loadId && !that._disposed) { + if (sectionIndicesToLoad.length) { + var index = sectionIndicesToLoad.shift(); + var loadedPromise = that._loadSection(index); + loadNextSectionAfterPromise(loadedPromise); + } else { + allSectionsLoadedSignal.complete(); + } + } + } + + if (!this._showProgressPromise) { + this._showProgressPromise = Promise.timeout(progressDelay).then(function () { + if (this._disposed) { + return; + } + + if (!this._progressBar) { + this._progressBar = _Global.document.createElement("progress"); + _ElementUtilities.addClass(this._progressBar, Hub._ClassName.hubProgress); + this._progressBar.max = 100; + } + if (!this._progressBar.parentNode) { + this.element.insertBefore(this._progressBar, this._viewportElement); + } + this._showProgressPromise = null; + }.bind(this), function () { + this._showProgressPromise = null; + }.bind(this)); + } + + if (this.sections.length) { + var allSectionsLoadedSignal = new _Signal(); + allSectionsLoadedPromise = allSectionsLoadedSignal.promise; + // Synchronously load the sections on screen. + var synchronousProcessPromises = []; + var start = Math.max(0, this.indexOfFirstVisible); + var end = Math.max(0, this.indexOfLastVisible); + for (var i = start; i <= end; i++) { + synchronousProcessPromises.push(this._loadSection(i)); + } + + // Determine the order to load the rest of the sections. + start--; + end++; + while (start >= 0 || end < this.sections.length) { + if (end < this.sections.length) { + sectionIndicesToLoad.push(end); + end++; + } + if (start >= 0) { + sectionIndicesToLoad.push(start); + start--; + } + } + + var onScreenSectionsLoadedPromise = Promise.join(synchronousProcessPromises); + + // In case there are overlapping load calls + onScreenSectionsLoadedPromise.done(function () { + if (loadId === this._loadId && !that._disposed) { + if (this._showProgressPromise) { + this._showProgressPromise.cancel(); + } + + if (this._progressBar && this._progressBar.parentNode) { + this._progressBar.parentNode.removeChild(this._progressBar); + } + + Scheduler.schedule(function Hub_entranceAnimation() { + if (loadId === this._loadId && !that._disposed) { + if (!this._visible) { + this._visible = true; + this._viewportElement.style.opacity = 1; + + if (this._animateEntrance && _TransitionAnimation.isAnimationEnabled()) { + var eventDetail = { + type: Hub.AnimationType.entrance + }; + + if (!this._fireEntrance || this._fireEvent(Hub._EventName.contentAnimating, eventDetail)) { + this._viewportElement.style["-ms-overflow-style"] = "none"; + onScreenItemsAnimatedPromise = Animations.enterContent(this._viewportElement).then(function () { + this._viewportElement.style["-ms-overflow-style"] = ""; + }.bind(this)); + } + } + if (this._element === _Global.document.activeElement) { + this._moveFocusIn(this.sectionOnScreen); + } + } + } + }, Scheduler.Priority.high, this, "WinJS.UI.Hub.entranceAnimation"); + } + }.bind(this)); + + loadNextSectionAfterPromise(onScreenSectionsLoadedPromise); + } else { + if (this._showProgressPromise) { + this._showProgressPromise.cancel(); + } + + if (this._progressBar && this._progressBar.parentNode) { + this._progressBar.parentNode.removeChild(this._progressBar); + } + } + + Promise.join([this.runningAnimations, onScreenItemsAnimatedPromise, allSectionsLoadedPromise]).done(function () { + if (loadId === this._loadId && !that._disposed) { + this.runningAnimations = Promise.wrap(); + if (this._measured && this._scrollLength !== this._viewportElement[this._names.scrollSize]) { + // A section changed size during processing. Invalidate the Hub's measurements so that its + // API's work correctly within the loadingState=complete handler. + this._measured = false; + } + this._setState(Hub.LoadingState.complete); + Scheduler.schedule(this._updateSnapList.bind(this), Scheduler.Priority.idle); + } + }.bind(this)); + }, + /// + loadingState: { + get: function () { + return this._loadingState; + } + }, + _setState: function Hub_setState(state) { + if (state !== this._loadingState) { + this._writeProfilerMark("loadingStateChanged:" + state + ",info"); + this._loadingState = state; + var eventObject = _Global.document.createEvent("CustomEvent"); + eventObject.initCustomEvent(Hub._EventName.loadingStateChanged, true, false, { loadingState: state }); + this._element.dispatchEvent(eventObject); + } + }, + _parse: function hub_parse() { + var hubSections = []; + var hubSectionEl = this.element.firstElementChild; + + while (hubSectionEl !== this._viewportElement) { + ControlProcessor.processAll(hubSectionEl); + + var hubSectionContent = hubSectionEl.winControl; + if (hubSectionContent) { + hubSections.push(hubSectionContent); + } else { + throw new _ErrorFromName("WinJS.UI.Hub.InvalidContent", strings.invalidContent); + } + + var nextSectionEl = hubSectionEl.nextElementSibling; + hubSectionEl = nextSectionEl; + } + + this.sections = new BindingList.List(hubSections); + }, + _fireEvent: function hub_fireEvent(type, detail) { + // Returns true if ev.preventDefault() was not called + var event = _Global.document.createEvent("CustomEvent"); + event.initCustomEvent(type, true, true, detail); + return this.element.dispatchEvent(event); + }, + + _findHeaderTabStop: function hub_findHeaderTabStop(element) { + if (element.parentNode) { + if (_ElementUtilities._matchesSelector(element, ".win-hub-section-header-tabstop, .win-hub-section-header-tabstop *")) { + while (!_ElementUtilities.hasClass(element, "win-hub-section-header-tabstop")) { + element = element.parentElement; + } + return element; + } + } + return null; + }, + _isInteractive: function hub_isInteractive(element) { + // Helper method to skip keyboarding and clicks + + while (element && element !== _Global.document.body) { + if (element.classList.contains("win-interactive")) { + return true; + } + element = element.parentElement; + } + return false; + }, + _clickHandler: function hub_clickHandler(ev) { + var headerTabStopElement = this._findHeaderTabStop(ev.target); + if (headerTabStopElement && !this._isInteractive(ev.target)) { + var section = headerTabStopElement.parentElement.parentElement.winControl; + if (!section.isHeaderStatic) { + var sectionIndex = this.sections.indexOf(section); + this._fireEvent(Hub._EventName.headerInvoked, { + index: sectionIndex, + section: section + }); + } + } + }, + _resizeHandler: function hub_resizeHandler() { + // Viewport needs to be measured + this._measured = false; + Scheduler.schedule(this._updateSnapList.bind(this), Scheduler.Priority.idle); + }, + _contentResizeHandler: function hub_contentResizeHandler() { + // Sections and scroll length need to be measured + this._measured = false; + Scheduler.schedule(this._updateSnapList.bind(this), Scheduler.Priority.idle); + }, + _scrollHandler: function hub_scrollHandler() { + // Scroll location needs to be retrieved + this._measured = false; + + if (this._pendingSections) { + return; + } + + // Scroll events caused by users overwrite pending API modifications to scrollposition. + this._pendingScrollLocation = null; + this._pendingSectionOnScreen = null; + + if (!this._pendingScrollHandler) { + this._pendingScrollHandler = _BaseUtils._requestAnimationFrame(function () { + this._pendingScrollHandler = null; + + if (this._pendingSections) { + return; + } + + if (this.loadingState !== Hub.LoadingState.complete) { + this._loadSections(); + } + }.bind(this)); + } + }, + _measure: function hub_measure() { + // Any time a size changes (section growing, window resizing, etc) cachedSizes should be set to false + // and any time the variables need to be read again we should measure the variables. To avoid a lot of + // seperate layouts we measure the variables in a single batch. + if (!this._measured || this._scrollLength === 0) { + this._writeProfilerMark("measure,StartTM"); + this._measured = true; + + this._rtl = _Global.getComputedStyle(this._element, null).direction === "rtl"; + + if (this.orientation === _UI.Orientation.vertical) { + this._names = verticalNames; + } else { + if (this._rtl) { + this._names = rtlHorizontalNames; + } else { + this._names = ltrHorizontalNames; + } + } + + this._viewportSize = this._viewportElement[this._names.offsetSize]; + this._viewportOppositeSize = this._viewportElement[this._names.oppositeOffsetSize]; + this._scrollPosition = _ElementUtilities.getScrollPosition(this._viewportElement)[this._names.scrollPos]; + this._scrollLength = this._viewportElement[this._names.scrollSize]; + + var surfaceElementComputedStyle = _Global.getComputedStyle(this._surfaceElement); + this._startSpacer = parseFloat(surfaceElementComputedStyle[this._names.marginStart]) + parseFloat(surfaceElementComputedStyle[this._names.borderStart]) + parseFloat(surfaceElementComputedStyle[this._names.paddingStart]); + this._endSpacer = parseFloat(surfaceElementComputedStyle[this._names.marginEnd]) + parseFloat(surfaceElementComputedStyle[this._names.borderEnd]) + parseFloat(surfaceElementComputedStyle[this._names.paddingEnd]); + + this._sectionSizes = []; + for (var i = 0; i < this.sections.length; i++) { + var section = this.sections.getAt(i); + var computedSectionStyle = _Global.getComputedStyle(section.element); + this._sectionSizes[i] = { + offset: section.element[this._names.offsetPos], + // Reminder: offsetWidth doesn't include margins and also rounds. + size: section.element[this._names.offsetSize], + marginStart: parseFloat(computedSectionStyle[this._names.marginStart]), + marginEnd: parseFloat(computedSectionStyle[this._names.marginEnd]), + borderStart: parseFloat(computedSectionStyle[this._names.borderStart]), + borderEnd: parseFloat(computedSectionStyle[this._names.borderEnd]), + paddingStart: parseFloat(computedSectionStyle[this._names.paddingStart]), + paddingEnd: parseFloat(computedSectionStyle[this._names.paddingEnd]) + }; + + if (this._rtl && this.orientation === _UI.Orientation.horizontal) { + this._sectionSizes[i].offset = this._viewportSize - (this._sectionSizes[i].offset + this._sectionSizes[i].size); + } + } + + this._writeProfilerMark("measure,StopTM"); + } + }, + _updateSnapList: function hub_updateSnapList() { + this._writeProfilerMark("updateSnapList,StartTM"); + this._measure(); + + var snapList = "snapList("; + for (var i = 0; i < this._sectionSizes.length; i++) { + if (i > 0) { + snapList += ","; + } + var sectionSize = this._sectionSizes[i]; + snapList += (sectionSize.offset - sectionSize.marginStart - this._startSpacer) + "px"; + } + snapList += ")"; + + var snapListY = ""; + var snapListX = ""; + if (this.orientation === _UI.Orientation.vertical) { + snapListY = snapList; + } else { + snapListX = snapList; + } + + if (this._lastSnapPointY !== snapListY) { + this._lastSnapPointY = snapListY; + this._viewportElement.style['-ms-scroll-snap-points-y'] = snapListY; + } + + if (this._lastSnapPointX !== snapListX) { + this._lastSnapPointX = snapListX; + this._viewportElement.style['-ms-scroll-snap-points-x'] = snapListX; + } + + this._writeProfilerMark("updateSnapList,StopTM"); + }, + _scrollToSection: function Hub_scrollToSection(index, withAnimation) { + this._measure(); + var sectionSize = this._sectionSizes[index]; + var scrollPositionToShowStartMargin = Math.min(this._scrollLength - this._viewportSize, sectionSize.offset - sectionSize.marginStart - this._startSpacer); + + this._scrollTo(scrollPositionToShowStartMargin, withAnimation); + }, + _ensureVisible: function hub_ensureVisible(index, withAnimation) { + this._measure(); + var targetScrollPos = this._ensureVisibleMath(index, this._scrollPosition); + this._scrollTo(targetScrollPos, withAnimation); + }, + _ensureVisibleMath: function hub_ensureVisibleMath(index, targetScrollPos) { + this._measure(); + var sectionSize = this._sectionSizes[index]; + + var scrollPositionToShowStartMargin = Math.min(this._scrollLength - this._viewportSize, sectionSize.offset - sectionSize.marginStart - this._startSpacer); + var scrollPositionToShowEndMargin = Math.max(0, sectionSize.offset + sectionSize.size + sectionSize.marginEnd + this._endSpacer - this._viewportSize + 1); + if (targetScrollPos > scrollPositionToShowStartMargin) { + targetScrollPos = scrollPositionToShowStartMargin; + } else if (targetScrollPos < scrollPositionToShowEndMargin) { + targetScrollPos = Math.min(scrollPositionToShowStartMargin, scrollPositionToShowEndMargin); + } + + return targetScrollPos; + }, + _scrollTo: function hub_scrollTo(scrollPos, withAnimation) { + this._scrollPosition = scrollPos; + if (withAnimation) { + if (this.orientation === _UI.Orientation.vertical) { + _ElementUtilities._zoomTo(this._viewportElement, { contentX: 0, contentY: this._scrollPosition, viewportX: 0, viewportY: 0 }); + } else { + _ElementUtilities._zoomTo(this._viewportElement, { contentX: this._scrollPosition, contentY: 0, viewportX: 0, viewportY: 0 }); + } + } else { + var newScrollPos = {}; + newScrollPos[this._names.scrollPos] = this._scrollPosition; + _ElementUtilities.setScrollPosition(this._viewportElement, newScrollPos); + } + }, + _windowKeyDownHandler: function hub_windowKeyDownHandler(ev) { + // Include tab and shift tab. Note: Alt Key + Tab and Windows Key + Tab do not fire keydown with ev.key === "Tab". + if (ev.keyCode === Key.tab) { + this._tabSeenLast = true; + + var that = this; + _BaseUtils._yieldForEvents(function () { + that._tabSeenLast = false; + }); + } + }, + _focusin: function hub_focusin(ev) { + // On focus we call ensureVisible to handle the tab or shift/tab to header. However if the + // focus was caused by a pointer down event we skip the focus. + if (this._tabSeenLast) { + var headerTabStopElement = this._findHeaderTabStop(ev.target); + if (headerTabStopElement && !this._isInteractive(ev.target)) { + var sectionIndex = this.sections.indexOf(headerTabStopElement.parentElement.parentElement.winControl); + if (sectionIndex > -1) { + this._ensureVisible(sectionIndex, true); + } + } + } + + // Always remember the focused section for SemanticZoom. + var sectionElement = ev.target; + while (sectionElement && !_ElementUtilities.hasClass(sectionElement, _Section.HubSection._ClassName.hubSection)) { + sectionElement = sectionElement.parentElement; + } + if (sectionElement) { + var sectionIndex = this.sections.indexOf(sectionElement.winControl); + if (sectionIndex > -1) { + this._currentIndexForSezo = sectionIndex; + } + } + + if (ev.target === this.element) { + var indexToFocus; + if (+this._sectionToFocus === this._sectionToFocus && this._sectionToFocus >= 0 && this._sectionToFocus < this.sections.length) { + indexToFocus = this._sectionToFocus; + this._sectionToFocus = null; + } else { + indexToFocus = this.sectionOnScreen; + } + + this._moveFocusIn(indexToFocus); + } + }, + _moveFocusIn: function hub_moveFocusIn(indexToFocus) { + if (indexToFocus >= 0) { + for (var i = indexToFocus; i < this.sections.length; i++) { + var section = this.sections.getAt(i); + + var focusAttempt = _ElementUtilities._trySetActive(section._headerTabStopElement, this._viewportElement); + + if (focusAttempt) { + return; + } + + if (_ElementUtilities._setActiveFirstFocusableElement(section.contentElement, this._viewportElement)) { + return; + } + } + + for (var i = indexToFocus - 1; i >= 0; i--) { + var section = this.sections.getAt(i); + + if (_ElementUtilities._setActiveFirstFocusableElement(section.contentElement, this._viewportElement)) { + return; + } + + var focusAttempt = _ElementUtilities._trySetActive(section._headerTabStopElement, this._viewportElement); + + if (focusAttempt) { + return; + } + } + } + }, + _keyDownHandler: function hub_keyDownHandler(ev) { + if (this._isInteractive(ev.target) || _ElementUtilities._hasCursorKeysBehaviors(ev.target)) { + return; + } + + var leftKey = this._rtl ? Key.rightArrow : Key.leftArrow; + var rightKey = this._rtl ? Key.leftArrow : Key.rightArrow; + + if (ev.keyCode === Key.upArrow || ev.keyCode === Key.downArrow || ev.keyCode === Key.leftArrow || ev.keyCode === Key.rightArrow || ev.keyCode === Key.pageUp || ev.keyCode === Key.pageDown) { + var headerTabStopElement = this._findHeaderTabStop(ev.target); + if (headerTabStopElement) { + var currentSection = this.sections.indexOf(headerTabStopElement.parentElement.parentElement.winControl); + var targetSectionIndex; + var useEnsureVisible = false; + // Page up/down go to the next/previous header and line it up with the app header. Up/Right/Down/Left + // move focus to the next/previous header and move it on screen (app header distance from either edge). + if (ev.keyCode === Key.pageDown || + (this.orientation === _UI.Orientation.horizontal && ev.keyCode === rightKey) || + (this.orientation === _UI.Orientation.vertical && ev.keyCode === Key.downArrow)) { + // Do not include hidden headers. + for (var i = currentSection + 1; i < this.sections.length; i++) { + if (this._tryFocus(i)) { + targetSectionIndex = i; + break; + } + } + } else if (ev.keyCode === Key.pageUp || + (this.orientation === _UI.Orientation.horizontal && ev.keyCode === leftKey) || + (this.orientation === _UI.Orientation.vertical && ev.keyCode === Key.upArrow)) { + // Do not include hidden headers. + for (var i = currentSection - 1; i >= 0; i--) { + if (this._tryFocus(i)) { + targetSectionIndex = i; + break; + } + } + } + if (ev.keyCode === Key.upArrow || ev.keyCode === Key.downArrow || ev.keyCode === Key.leftArrow || ev.keyCode === Key.rightArrow) { + useEnsureVisible = true; + } + + if (+targetSectionIndex === targetSectionIndex) { + if (useEnsureVisible) { + this._ensureVisible(targetSectionIndex, true); + } else { + this._scrollToSection(targetSectionIndex, true); + } + ev.preventDefault(); + } + } + } else if (ev.keyCode === Key.home || ev.keyCode === Key.end) { + // Home/End scroll to start/end and leave focus where it is. + this._measure(); + var maxScrollPos = Math.max(0, this._scrollLength - this._viewportSize); + this._scrollTo(ev.keyCode === Key.home ? 0 : maxScrollPos, true); + ev.preventDefault(); + } + }, + _tryFocus: function hub_tryFocus(index) { + var targetSection = this.sections.getAt(index); + + _ElementUtilities._setActive(targetSection._headerTabStopElement, this._viewportElement); + + return _Global.document.activeElement === targetSection._headerTabStopElement; + }, + /// + /// Gets a ZoomableView. This API supports the SemanticZoom infrastructure + /// and is not intended to be used directly from your code. + /// + /// + zoomableView: { + get: function zoomableView_get() { + if (!this._zoomableView) { + this._zoomableView = new ZoomableView(this); + } + + return this._zoomableView; + } + }, + _getPanAxis: function hub_getPanAxis() { + return this.orientation === _UI.Orientation.horizontal ? "horizontal" : "vertical"; + }, + _configureForZoom: function hub_configureForZoom() { + // Nothing to configure. + }, + _setCurrentItem: function hub_setCurrentItem(x, y) { + var offset; + if (this.orientation === _UI.Orientation.horizontal) { + offset = x; + } else { + offset = y; + } + + this._measure(); + offset = offset + this._scrollPosition; + this._currentIndexForSezo = this._sectionSizes.length - 1; + for (var i = 1; i < this._sectionSizes.length; i++) { + var sectionSize = this._sectionSizes[i]; + if (sectionSize.offset - sectionSize.marginStart > offset) { + this._currentIndexForSezo = i - 1; + break; + } + } + }, + _getCurrentItem: function hub_getCurrentItem() { + var itemPosition; + if (this._sectionSizes.length > 0) { + this._measure(); + var index = Math.max(0, Math.min(this._currentIndexForSezo, this._sectionSizes.length)); + var sectionSize = this._sectionSizes[index]; + if (this.orientation === _UI.Orientation.horizontal) { + itemPosition = { + left: Math.max(0, sectionSize.offset - sectionSize.marginStart - this._scrollPosition), + top: 0, + width: sectionSize.size, + height: this._viewportOppositeSize + }; + } else { + itemPosition = { + left: 0, + top: Math.max(0, sectionSize.offset - sectionSize.marginStart - this._scrollPosition), + width: this._viewportOppositeSize, + height: sectionSize.size, + }; + } + + var section = this.sections.getAt(index); + // BUGBUG: 53301 ListView and Hub should document what they expect to be returned from the + // getCurrentItem so that positionItem apis line up. ListView zoomed out expects an object with + // groupIndexHint, groupKey, or groupDescription. Hub expects an object with index. + return Promise.wrap({ item: { data: section, index: index, groupIndexHint: index }, position: itemPosition }); + } + }, + _beginZoom: function hub_beginZoom() { + // Hide scroll thumb. + this._viewportElement.style["-ms-overflow-style"] = "none"; + }, + _positionItem: function hub_positionItem(item, position) { + if (item.index >= 0 && item.index < this._sectionSizes.length) { + this._measure(); + var sectionSize = this._sectionSizes[item.index]; + + var offsetFromViewport; + if (this.orientation === _UI.Orientation.horizontal) { + offsetFromViewport = position.left; + } else { + offsetFromViewport = position.top; + } + + this._sectionToFocus = item.index; + + var targetScrollPosition = sectionSize.offset - offsetFromViewport; + // clamp section: + var targetScrollPosition = this._ensureVisibleMath(item.index, targetScrollPosition); + + this._scrollPosition = targetScrollPosition; + var newScrollPos = {}; + newScrollPos[this._names.scrollPos] = this._scrollPosition; + _ElementUtilities.setScrollPosition(this._viewportElement, newScrollPos); + } + }, + _endZoom: function hub_endZoom() { + // Show scroll thumb. + this._viewportElement.style["-ms-overflow-style"] = ""; + }, + _writeProfilerMark: function hub_writeProfilerMark(text) { + var message = "WinJS.UI.Hub:" + this._id + ":" + text; + _WriteProfilerMark(message); + _Log.log && _Log.log(message, null, "hubprofiler"); + }, + dispose: function hub_dispose() { + /// + /// + /// Disposes this control. + /// + /// + /// + if (this._disposed) { + return; + } + this._disposed = true; + + _Global.removeEventListener('keydown', this._windowKeyDownHandlerBound); + _ElementUtilities._resizeNotifier.unsubscribe(this.element, this._resizeHandlerBound); + + this._updateEvents(this._sections); + + for (var i = 0; i < this.sections.length; i++) { + this.sections.getAt(i).dispose(); + } + } + }, { + /// + /// Specifies whether the Hub animation is an entrance animation or a transition animation. + /// + /// + AnimationType: { + /// + /// The animation plays when the Hub is first displayed. + /// + /// + entrance: "entrance", + /// + /// The animation plays when the Hub is changing its content. + /// + /// + contentTransition: "contentTransition", + /// + /// The animation plays when a section is inserted into the Hub. + /// + /// + insert: "insert", + /// + /// The animation plays when a section is removed into the Hub. + /// + /// + remove: "remove", + }, + /// + /// Gets the current loading state of the Hub. + /// + /// + LoadingState: { + /// + /// The Hub is loading sections. + /// + /// + loading: "loading", + /// + /// All sections are loaded and animations are complete. + /// + /// + complete: "complete" + }, + // Names of classes used by the Hub. + _ClassName: { + hub: "win-hub", + hubSurface: "win-hub-surface", + hubProgress: "win-hub-progress", + hubViewport: "win-hub-viewport", + hubVertical: "win-hub-vertical", + hubHorizontal: "win-hub-horizontal", + }, + // Names of events fired by the Hub. + _EventName: { + contentAnimating: eventNames.contentAnimating, + headerInvoked: eventNames.headerInvoked, + loadingStateChanged: eventNames.loadingStateChanged + }, + }); + + _Base.Class.mix(Hub, _Control.DOMEventMixin); + + var ZoomableView = _Base.Class.define(function ZoomableView_ctor(hub) { + this._hub = hub; + }, { + getPanAxis: function () { + return this._hub._getPanAxis(); + }, + configureForZoom: function (isZoomedOut, isCurrentView, triggerZoom, prefetchedPages) { + this._hub._configureForZoom(isZoomedOut, isCurrentView, triggerZoom, prefetchedPages); + }, + setCurrentItem: function (x, y) { + this._hub._setCurrentItem(x, y); + }, + getCurrentItem: function () { + return this._hub._getCurrentItem(); + }, + beginZoom: function () { + this._hub._beginZoom(); + }, + positionItem: function (item, position) { + return this._hub._positionItem(item, position); + }, + endZoom: function (isCurrentView) { + this._hub._endZoom(isCurrentView); + } + }); + + var strings = { + get duplicateConstruction() { return "Invalid argument: Controls may only be instantiated one time for each DOM element"; }, + get duplicateSection() { return "Hub duplicate sections: Each HubSection must be unique"; }, + get invalidContent() { return "Invalid content: Hub content must be made up of HubSections."; }, + get hubViewportAriaLabel() { return _Resources._getWinJSString("ui/hubViewportAriaLabel").value; } + }; + + return Hub; + }) + }); + +}); + +define('require-style!less/styles-lightdismissservice',[],function(){}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +define('WinJS/_LightDismissService',["require", "exports", './Application', './Core/_Base', './Core/_BaseUtils', './Utilities/_ElementUtilities', './Core/_Global', './Utilities/_KeyboardBehavior', './Core/_Log', './Core/_Resources'], function (require, exports, Application, _Base, _BaseUtils, _ElementUtilities, _Global, _KeyboardBehavior, _Log, _Resources) { + require(["require-style!less/styles-lightdismissservice"]); + "use strict"; + var baseZIndex = 1000; + var Strings = { + get closeOverlay() { + return _Resources._getWinJSString("ui/closeOverlay").value; + } + }; + exports._ClassNames = { + _clickEater: "win-clickeater" + }; + var EventNames = { + requestingFocusOnKeyboardInput: "requestingfocusonkeyboardinput" + }; + exports.LightDismissalReasons = { + tap: "tap", + lostFocus: "lostFocus", + escape: "escape", + hardwareBackButton: "hardwareBackButton", + windowResize: "windowResize", + windowBlur: "windowBlur" + }; + // Built-in implementations of ILightDismissable's onShouldLightDismiss. + exports.DismissalPolicies = { + light: function LightDismissalPolicies_light_onShouldLightDismiss(info) { + switch (info.reason) { + case exports.LightDismissalReasons.tap: + case exports.LightDismissalReasons.escape: + if (info.active) { + return true; + } + else { + info.stopPropagation(); + return false; + } + break; + case exports.LightDismissalReasons.hardwareBackButton: + if (info.active) { + info.preventDefault(); // prevent backwards navigation in the app + return true; + } + else { + info.stopPropagation(); + return false; + } + break; + case exports.LightDismissalReasons.lostFocus: + case exports.LightDismissalReasons.windowResize: + case exports.LightDismissalReasons.windowBlur: + return true; + } + }, + modal: function LightDismissalPolicies_modal_onShouldLightDismiss(info) { + // Light dismiss cues should not be seen by dismissables behind the modal + info.stopPropagation(); + switch (info.reason) { + case exports.LightDismissalReasons.tap: + case exports.LightDismissalReasons.lostFocus: + case exports.LightDismissalReasons.windowResize: + case exports.LightDismissalReasons.windowBlur: + return false; + break; + case exports.LightDismissalReasons.escape: + return info.active; + break; + case exports.LightDismissalReasons.hardwareBackButton: + info.preventDefault(); // prevent backwards navigation in the app + return info.active; + break; + } + }, + sticky: function LightDismissalPolicies_sticky_onShouldLightDismiss(info) { + info.stopPropagation(); + return false; + } + }; + var KeyboardInfoType = { + keyDown: "keyDown", + keyUp: "keyUp", + keyPress: "keyPress" + }; + var AbstractDismissableElement = (function () { + function AbstractDismissableElement(args) { + this.element = args.element; + this.element.tabIndex = args.tabIndex; + this.onLightDismiss = args.onLightDismiss; + // Allow the caller to override the default implementations of our ILightDismissable methods. + if (args.onTakeFocus) { + this.onTakeFocus = args.onTakeFocus; + } + if (args.onShouldLightDismiss) { + this.onShouldLightDismiss = args.onShouldLightDismiss; + } + this._ldeOnKeyDownBound = this._ldeOnKeyDown.bind(this); + this._ldeOnKeyUpBound = this._ldeOnKeyUp.bind(this); + this._ldeOnKeyPressBound = this._ldeOnKeyPress.bind(this); + } + AbstractDismissableElement.prototype.restoreFocus = function () { + var activeElement = _Global.document.activeElement; + if (activeElement && this.containsElement(activeElement)) { + this._ldeCurrentFocus = activeElement; + return true; + } + else { + // If the last input type was keyboard, use focus() so a keyboard focus visual is drawn. + // Otherwise, use setActive() so no focus visual is drawn. + var useSetActive = !_KeyboardBehavior._keyboardSeenLast; + return this._ldeCurrentFocus && this.containsElement(this._ldeCurrentFocus) && _ElementUtilities._tryFocusOnAnyElement(this._ldeCurrentFocus, useSetActive); + } + }; + AbstractDismissableElement.prototype._ldeOnKeyDown = function (eventObject) { + this._ldeService.keyDown(this, eventObject); + }; + AbstractDismissableElement.prototype._ldeOnKeyUp = function (eventObject) { + this._ldeService.keyUp(this, eventObject); + }; + AbstractDismissableElement.prototype._ldeOnKeyPress = function (eventObject) { + this._ldeService.keyPress(this, eventObject); + }; + // ILightDismissable + // + AbstractDismissableElement.prototype.setZIndex = function (zIndex) { + this.element.style.zIndex = zIndex; + }; + AbstractDismissableElement.prototype.getZIndexCount = function () { + return 1; + }; + AbstractDismissableElement.prototype.containsElement = function (element) { + return this.element.contains(element); + }; + AbstractDismissableElement.prototype.onTakeFocus = function (useSetActive) { + this.restoreFocus() || _ElementUtilities._focusFirstFocusableElement(this.element, useSetActive) || _ElementUtilities._tryFocusOnAnyElement(this.element, useSetActive); + }; + AbstractDismissableElement.prototype.onFocus = function (element) { + this._ldeCurrentFocus = element; + }; + AbstractDismissableElement.prototype.onShow = function (service) { + this._ldeService = service; + this.element.addEventListener("keydown", this._ldeOnKeyDownBound); + this.element.addEventListener("keyup", this._ldeOnKeyUpBound); + this.element.addEventListener("keypress", this._ldeOnKeyPressBound); + }; + AbstractDismissableElement.prototype.onHide = function () { + this._ldeCurrentFocus = null; + this._ldeService = null; + this.element.removeEventListener("keydown", this._ldeOnKeyDownBound); + this.element.removeEventListener("keyup", this._ldeOnKeyUpBound); + this.element.removeEventListener("keypress", this._ldeOnKeyPressBound); + }; + // Concrete subclasses are expected to implement these. + AbstractDismissableElement.prototype.onKeyInStack = function (info) { + }; + AbstractDismissableElement.prototype.onShouldLightDismiss = function (info) { + return false; + }; + // Consumers of concrete subclasses of AbstractDismissableElement are expected to + // provide these as parameters to the constructor. + AbstractDismissableElement.prototype.onLightDismiss = function (info) { + }; + return AbstractDismissableElement; + })(); + var LightDismissableElement = (function (_super) { + __extends(LightDismissableElement, _super); + function LightDismissableElement() { + _super.apply(this, arguments); + } + LightDismissableElement.prototype.onKeyInStack = function (info) { + }; + LightDismissableElement.prototype.onShouldLightDismiss = function (info) { + return exports.DismissalPolicies.light(info); + }; + return LightDismissableElement; + })(AbstractDismissableElement); + exports.LightDismissableElement = LightDismissableElement; + var ModalElement = (function (_super) { + __extends(ModalElement, _super); + function ModalElement() { + _super.apply(this, arguments); + } + ModalElement.prototype.onKeyInStack = function (info) { + // stopPropagation so that none of the app's other event handlers will see the event. + // Don't preventDefault so that the browser's hotkeys will still work. + info.stopPropagation(); + }; + ModalElement.prototype.onShouldLightDismiss = function (info) { + return exports.DismissalPolicies.modal(info); + }; + return ModalElement; + })(AbstractDismissableElement); + exports.ModalElement = ModalElement; + // An implementation of ILightDismissable that represents the HTML body element. It can never be dismissed. The + // service should instantiate one of these to act as the bottommost light dismissable at all times (it isn't expected + // for anybody else to instantiate one). It takes care of restoring focus when the last dismissable is dismissed. + var LightDismissableBody = (function () { + function LightDismissableBody() { + } + LightDismissableBody.prototype.setZIndex = function (zIndex) { + }; + LightDismissableBody.prototype.getZIndexCount = function () { + return 1; + }; + LightDismissableBody.prototype.containsElement = function (element) { + return _Global.document.body.contains(element); + }; + LightDismissableBody.prototype.onTakeFocus = function (useSetActive) { + this.currentFocus && this.containsElement(this.currentFocus) && _ElementUtilities._tryFocusOnAnyElement(this.currentFocus, useSetActive); + }; + LightDismissableBody.prototype.onFocus = function (element) { + this.currentFocus = element; + }; + LightDismissableBody.prototype.onShow = function (service) { + }; + LightDismissableBody.prototype.onHide = function () { + this.currentFocus = null; + }; + LightDismissableBody.prototype.onKeyInStack = function (info) { + }; + LightDismissableBody.prototype.onShouldLightDismiss = function (info) { + return false; + }; + LightDismissableBody.prototype.onLightDismiss = function (info) { + }; + return LightDismissableBody; + })(); + ; + var LightDismissService = (function () { + function LightDismissService() { + this._debug = false; // Disables dismiss due to window blur. Useful during debugging. + this._clients = []; + this._notifying = false; + this._bodyClient = new LightDismissableBody(); + // State private to _updateDom. No other method should make use of it. + this._updateDom_rendered = { + serviceActive: false + }; + this._clickEaterEl = this._createClickEater(); + this._onBeforeRequestingFocusOnKeyboardInputBound = this._onBeforeRequestingFocusOnKeyboardInput.bind(this); + this._onFocusInBound = this._onFocusIn.bind(this); + this._onKeyDownBound = this._onKeyDown.bind(this); + this._onWindowResizeBound = this._onWindowResize.bind(this); + this._onClickEaterPointerUpBound = this._onClickEaterPointerUp.bind(this); + this._onClickEaterPointerCancelBound = this._onClickEaterPointerCancel.bind(this); + // Register for infrequent events. + Application.addEventListener("backclick", this._onBackClick.bind(this)); + // Focus handlers generally use _ElementUtilities._addEventListener with focusout/focusin. This + // uses the browser's blur event directly beacuse _addEventListener doesn't support focusout/focusin + // on window. + _Global.window.addEventListener("blur", this._onWindowBlur.bind(this)); + this.shown(this._bodyClient); + } + // Dismissables should call this as soon as they are ready to be shown. More specifically, they should call this: + // - After they are in the DOM and ready to receive focus (e.g. style.display cannot = "none") + // - Before their entrance animation is played + LightDismissService.prototype.shown = function (client) { + var index = this._clients.indexOf(client); + if (index === -1) { + this._clients.push(client); + client.onShow(this); + this._updateDom(); + } + }; + // Dismissables should call this when they are done being dismissed (i.e. after their exit animation has finished) + LightDismissService.prototype.hidden = function (client) { + var index = this._clients.indexOf(client); + if (index !== -1) { + this._clients.splice(index, 1); + client.setZIndex(""); + client.onHide(); + this._updateDom(); + } + }; + // Dismissables should call this when their state has changed such that it'll affect the behavior of some method + // in its ILightDismissable interface. For example, if the dismissable was altered such that getZIndexCount will + // now return 2 instead of 1, that dismissable should call *updated* so the LightDismissService can find out about + // this change. + LightDismissService.prototype.updated = function (client) { + this._updateDom(); + }; + LightDismissService.prototype.keyDown = function (client, eventObject) { + if (eventObject.keyCode === _ElementUtilities.Key.escape) { + this._escapePressed(eventObject); + } + else { + this._dispatchKeyboardEvent(client, KeyboardInfoType.keyDown, eventObject); + } + }; + LightDismissService.prototype.keyUp = function (client, eventObject) { + this._dispatchKeyboardEvent(client, KeyboardInfoType.keyUp, eventObject); + }; + LightDismissService.prototype.keyPress = function (client, eventObject) { + this._dispatchKeyboardEvent(client, KeyboardInfoType.keyPress, eventObject); + }; + LightDismissService.prototype.isShown = function (client) { + return this._clients.indexOf(client) !== -1; + }; + LightDismissService.prototype.isTopmost = function (client) { + return client === this._clients[this._clients.length - 1]; + }; + // Disables dismiss due to window blur. Useful during debugging. + LightDismissService.prototype._setDebug = function (debug) { + this._debug = debug; + }; + LightDismissService.prototype._updateDom = function (options) { + options = options || {}; + var activeDismissableNeedsFocus = !!options.activeDismissableNeedsFocus; + var rendered = this._updateDom_rendered; + if (this._notifying) { + return; + } + var serviceActive = this._clients.length > 1; + if (serviceActive !== rendered.serviceActive) { + // Unregister/register for events that occur frequently. + if (serviceActive) { + Application.addEventListener("beforerequestingfocusonkeyboardinput", this._onBeforeRequestingFocusOnKeyboardInputBound); + _ElementUtilities._addEventListener(_Global.document.documentElement, "focusin", this._onFocusInBound); + _Global.document.documentElement.addEventListener("keydown", this._onKeyDownBound); + _Global.window.addEventListener("resize", this._onWindowResizeBound); + this._bodyClient.currentFocus = _Global.document.activeElement; + _Global.document.body.appendChild(this._clickEaterEl); + } + else { + Application.removeEventListener("beforerequestingfocusonkeyboardinput", this._onBeforeRequestingFocusOnKeyboardInputBound); + _ElementUtilities._removeEventListener(_Global.document.documentElement, "focusin", this._onFocusInBound); + _Global.document.documentElement.removeEventListener("keydown", this._onKeyDownBound); + _Global.window.removeEventListener("resize", this._onWindowResizeBound); + var parent = this._clickEaterEl.parentNode; + parent && parent.removeChild(this._clickEaterEl); + } + rendered.serviceActive = serviceActive; + } + var zIndexGap = 0; + var lastUsedZIndex = baseZIndex + 1; + this._clients.forEach(function (c, i) { + var currentZIndex = lastUsedZIndex + zIndexGap; + c.setZIndex("" + currentZIndex); + lastUsedZIndex = currentZIndex; + // count + 1 so that there's an unused zIndex between each pair of + // dismissables that can be used by the click eater. + zIndexGap = c.getZIndexCount() + 1; + }); + if (serviceActive) { + this._clickEaterEl.style.zIndex = "" + (lastUsedZIndex - 1); + } + var activeDismissable = this._clients.length > 0 ? this._clients[this._clients.length - 1] : null; + if (this._activeDismissable !== activeDismissable) { + this._activeDismissable = activeDismissable; + activeDismissableNeedsFocus = true; + } + if (activeDismissableNeedsFocus) { + // If the last input type was keyboard, use focus() so a keyboard focus visual is drawn. + // Otherwise, use setActive() so no focus visual is drawn. + var useSetActive = !_KeyboardBehavior._keyboardSeenLast; + this._activeDismissable && this._activeDismissable.onTakeFocus(useSetActive); + } + }; + LightDismissService.prototype._dispatchKeyboardEvent = function (client, keyboardInfoType, eventObject) { + var index = this._clients.indexOf(client); + if (index !== -1) { + var info = { + type: keyboardInfoType, + keyCode: eventObject.keyCode, + propagationStopped: false, + stopPropagation: function () { + this.propagationStopped = true; + eventObject.stopPropagation(); + } + }; + var clients = this._clients.slice(0, index + 1); + for (var i = clients.length - 1; i >= 0 && !info.propagationStopped; i--) { + clients[i].onKeyInStack(info); + } + } + }; + LightDismissService.prototype._dispatchLightDismiss = function (reason, clients, options) { + if (this._notifying) { + _Log.log && _Log.log('_LightDismissService ignored dismiss trigger to avoid re-entrancy: "' + reason + '"', "winjs _LightDismissService", "warning"); + return; + } + clients = clients || this._clients.slice(0); + if (clients.length === 0) { + return; + } + this._notifying = true; + var lightDismissInfo = { + // Which of the LightDismissalReasons caused this event to fire? + reason: reason, + // Is this dismissable currently the active dismissable? + active: false, + _stop: false, + stopPropagation: function () { + this._stop = true; + }, + _doDefault: true, + preventDefault: function () { + this._doDefault = false; + } + }; + for (var i = clients.length - 1; i >= 0 && !lightDismissInfo._stop; i--) { + lightDismissInfo.active = this._activeDismissable === clients[i]; + if (clients[i].onShouldLightDismiss(lightDismissInfo)) { + clients[i].onLightDismiss(lightDismissInfo); + } + } + this._notifying = false; + this._updateDom(options); + return lightDismissInfo._doDefault; + }; + LightDismissService.prototype._onBeforeRequestingFocusOnKeyboardInput = function (eventObject) { + // Suppress the requestingFocusOnKeyboardInput event. + return true; + }; + // + // Light dismiss triggers + // + // Called by tests. + LightDismissService.prototype._clickEaterTapped = function () { + this._dispatchLightDismiss(exports.LightDismissalReasons.tap); + }; + LightDismissService.prototype._onFocusIn = function (eventObject) { + var target = eventObject.target; + for (var i = this._clients.length - 1; i >= 0; i--) { + if (this._clients[i].containsElement(target)) { + break; + } + } + if (i !== -1) { + this._clients[i].onFocus(target); + } + if (i + 1 < this._clients.length) { + this._dispatchLightDismiss(exports.LightDismissalReasons.lostFocus, this._clients.slice(i + 1), { + activeDismissableNeedsFocus: true + }); + } + }; + LightDismissService.prototype._onKeyDown = function (eventObject) { + if (eventObject.keyCode === _ElementUtilities.Key.escape) { + this._escapePressed(eventObject); + } + }; + LightDismissService.prototype._escapePressed = function (eventObject) { + eventObject.preventDefault(); + eventObject.stopPropagation(); + this._dispatchLightDismiss(exports.LightDismissalReasons.escape); + }; + // Called by tests. + LightDismissService.prototype._onBackClick = function (eventObject) { + var doDefault = this._dispatchLightDismiss(exports.LightDismissalReasons.hardwareBackButton); + return !doDefault; // Returns whether or not the event was handled. + }; + LightDismissService.prototype._onWindowResize = function (eventObject) { + this._dispatchLightDismiss(exports.LightDismissalReasons.windowResize); + }; + LightDismissService.prototype._onWindowBlur = function (eventObject) { + if (this._debug) { + return; + } + // Want to trigger a light dismiss on window blur. + // We get blur if we click off the window, including into an iframe within our window. + // Both blurs call this function, but fortunately document.hasFocus is true if either + // the document window or our iframe window has focus. + if (!_Global.document.hasFocus()) { + // The document doesn't have focus, so they clicked off the app, so light dismiss. + this._dispatchLightDismiss(exports.LightDismissalReasons.windowBlur); + } + else { + // We were trying to unfocus the window, but document still has focus, + // so make sure the iframe that took the focus will check for blur next time. + var active = _Global.document.activeElement; + if (active && active.tagName === "IFRAME" && !active["msLightDismissBlur"]) { + // - This will go away when the IFRAME goes away, and we only create one. + // - This only works in IE because other browsers don't fire focus events on iframe elements. + // - Can't use _ElementUtilities._addEventListener's focusout because it doesn't fire when an + // iframe loses focus due to changing windows. + active.addEventListener("blur", this._onWindowBlur.bind(this), false); + active["msLightDismissBlur"] = true; + } + } + }; + LightDismissService.prototype._createClickEater = function () { + var clickEater = _Global.document.createElement("section"); + clickEater.className = exports._ClassNames._clickEater; + _ElementUtilities._addEventListener(clickEater, "pointerdown", this._onClickEaterPointerDown.bind(this), true); + clickEater.addEventListener("click", this._onClickEaterClick.bind(this), true); + // Tell Aria that it's clickable + clickEater.setAttribute("role", "menuitem"); + clickEater.setAttribute("aria-label", Strings.closeOverlay); + // Prevent CED from removing any current selection + clickEater.setAttribute("unselectable", "on"); + return clickEater; + }; + LightDismissService.prototype._onClickEaterPointerDown = function (eventObject) { + eventObject.stopPropagation(); + eventObject.preventDefault(); + this._clickEaterPointerId = eventObject.pointerId; + if (!this._registeredClickEaterCleanUp) { + _ElementUtilities._addEventListener(_Global.window, "pointerup", this._onClickEaterPointerUpBound); + _ElementUtilities._addEventListener(_Global.window, "pointercancel", this._onClickEaterPointerCancelBound); + this._registeredClickEaterCleanUp = true; + } + }; + LightDismissService.prototype._onClickEaterPointerUp = function (eventObject) { + var _this = this; + eventObject.stopPropagation(); + eventObject.preventDefault(); + if (eventObject.pointerId === this._clickEaterPointerId) { + this._resetClickEaterPointerState(); + var element = _Global.document.elementFromPoint(eventObject.clientX, eventObject.clientY); + if (element === this._clickEaterEl) { + this._skipClickEaterClick = true; + _BaseUtils._yieldForEvents(function () { + _this._skipClickEaterClick = false; + }); + this._clickEaterTapped(); + } + } + }; + LightDismissService.prototype._onClickEaterClick = function (eventObject) { + eventObject.stopPropagation(); + eventObject.preventDefault(); + if (!this._skipClickEaterClick) { + // Handle the UIA invoke action on the click eater. this._skipClickEaterClick is false which tells + // us that we received a click event without an associated PointerUp event. This means that the click + // event was triggered thru UIA rather than thru the GUI. + this._clickEaterTapped(); + } + }; + LightDismissService.prototype._onClickEaterPointerCancel = function (eventObject) { + if (eventObject.pointerId === this._clickEaterPointerId) { + this._resetClickEaterPointerState(); + } + }; + LightDismissService.prototype._resetClickEaterPointerState = function () { + if (this._registeredClickEaterCleanUp) { + _ElementUtilities._removeEventListener(_Global.window, "pointerup", this._onClickEaterPointerUpBound); + _ElementUtilities._removeEventListener(_Global.window, "pointercancel", this._onClickEaterPointerCancelBound); + } + this._clickEaterPointerId = null; + this._registeredClickEaterCleanUp = false; + }; + return LightDismissService; + })(); + var service = new LightDismissService(); + exports.shown = service.shown.bind(service); + exports.hidden = service.hidden.bind(service); + exports.updated = service.updated.bind(service); + exports.isShown = service.isShown.bind(service); + exports.isTopmost = service.isTopmost.bind(service); + exports.keyDown = service.keyDown.bind(service); + exports.keyUp = service.keyUp.bind(service); + exports.keyPress = service.keyPress.bind(service); + exports._clickEaterTapped = service._clickEaterTapped.bind(service); + exports._onBackClick = service._onBackClick.bind(service); + exports._setDebug = service._setDebug.bind(service); + _Base.Namespace.define("WinJS.UI._LightDismissService", { + shown: exports.shown, + hidden: exports.hidden, + updated: exports.updated, + isShown: exports.isShown, + isTopmost: exports.isTopmost, + keyDown: exports.keyDown, + keyUp: exports.keyUp, + keyPress: exports.keyPress, + _clickEaterTapped: exports._clickEaterTapped, + _onBackClick: exports._onBackClick, + _setDebug: exports._setDebug, + LightDismissableElement: LightDismissableElement, + DismissalPolicies: exports.DismissalPolicies, + LightDismissalReasons: exports.LightDismissalReasons, + _ClassNames: exports._ClassNames, + _service: service + }); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('WinJS/Controls/_LegacyAppBar/_Constants',[ + 'exports', + '../../Core/_Base', +], function appBarConstantsInit(exports, _Base) { + "use strict"; + + _Base.Namespace._moduleDefine(exports, null, { + // AppBar class names. + appBarClass: "win-navbar", + firstDivClass: "win-firstdiv", + finalDivClass: "win-finaldiv", + invokeButtonClass: "win-navbar-invokebutton", + ellipsisClass: "win-navbar-ellipsis", + primaryCommandsClass: "win-primarygroup", + secondaryCommandsClass: "win-secondarygroup", + commandLayoutClass: "win-commandlayout", + menuLayoutClass: "win-menulayout", + topClass: "win-top", + bottomClass: "win-bottom", + showingClass : "win-navbar-opening", + shownClass : "win-navbar-opened", + hidingClass : "win-navbar-closing", + hiddenClass: "win-navbar-closed", + compactClass: "win-navbar-compact", + minimalClass: "win-navbar-minimal", + menuContainerClass: "win-navbar-menu", + + // Constants for AppBar placement + appBarPlacementTop: "top", + appBarPlacementBottom: "bottom", + + // Constants for AppBar layouts + appBarLayoutCustom: "custom", + appBarLayoutCommands: "commands", + appBarLayoutMenu: "menu", + + // Constant for AppBar invokebutton width + appBarInvokeButtonWidth: 32, + + // Constants for Commands + typeSeparator: "separator", + typeContent: "content", + typeButton: "button", + typeToggle: "toggle", + typeFlyout: "flyout", + appBarCommandClass: "win-command", + appBarCommandGlobalClass: "win-global", + appBarCommandSelectionClass: "win-selection", + sectionSelection: "selection", /* deprecated, use sectionSecondary */ + sectionGlobal: "global", /* deprecated, use sectionPrimary */ + sectionPrimary: "primary", + sectionSecondary: "secondary", + + // Constants for Menus + menuCommandClass: "win-command", + menuCommandButtonClass: "win-command-button", + menuCommandToggleClass: "win-command-toggle", + menuCommandFlyoutClass: "win-command-flyout", + menuCommandFlyoutActivatedClass: "win-command-flyout-activated", + menuCommandSeparatorClass: "win-command-separator", + _menuCommandInvokedEvent: "_invoked", // Private event + menuClass: "win-menu", + menuContainsToggleCommandClass: "win-menu-containstogglecommand", + menuContainsFlyoutCommandClass: "win-menu-containsflyoutcommand", + menuMouseSpacingClass: "win-menu-mousespacing", + menuTouchSpacingClass: "win-menu-touchspacing", + menuCommandHoverDelay: 400, + + // Other class names + overlayClass: "win-overlay", + flyoutClass: "win-flyout", + flyoutLightClass: "win-ui-light", + settingsFlyoutClass: "win-settingsflyout", + scrollsClass: "win-scrolls", + pinToRightEdge: -1, + pinToBottomEdge: -1, + + // Constants for AppBarCommand full-size widths. + separatorWidth: 34, + buttonWidth: 68, + + narrowClass: "win-narrow", + wideClass: "win-wide", + _visualViewportClass: "win-visualviewport-space", + + // Event names + commandPropertyMutated: "_commandpropertymutated", + commandVisibilityChanged: "commandvisibilitychanged", + }); +}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// +define('WinJS/Utilities/_KeyboardInfo',["require", "exports", '../Core/_BaseCoreUtils', '../Core/_Global', '../Core/_WinRT'], function (require, exports, _BaseCoreUtils, _Global, _WinRT) { + "use strict"; + var _Constants = { + visualViewportClass: "win-visualviewport-space", + scrollTimeout: 150, + }; + // This private module provides accurate metrics for the Visual Viewport and WWA's IHM offsets in Win10 WWA + // where "-ms-device-fixed" CSS positioning is supported. WinJS controls will also use this module for + // positoning themselves relative to the viewport in a web browser outside of WWA. Their preference is still + // to rely on "-ms-device-fixed" positioning, but currently fallback to "fixed" positioning in enviornments where + // "-ms-device-fixed" is not supported. + exports._KeyboardInfo; + // WWA Soft Keyboard offsets + exports._KeyboardInfo = { + // Determine if the keyboard is visible or not. + get _visible() { + try { + return (_WinRT.Windows.UI.ViewManagement.InputPane && _WinRT.Windows.UI.ViewManagement.InputPane.getForCurrentView().occludedRect.height > 0); + } + catch (e) { + return false; + } + }, + // See if we have to reserve extra space for the IHM + get _extraOccluded() { + var occluded = 0; + // Controls using -ms-device-fixed positioning only need to reposition themselves to remain visible + // If the IHM has not resized the viewport. + if (!exports._KeyboardInfo._isResized && _WinRT.Windows.UI.ViewManagement.InputPane) { + occluded = _WinRT.Windows.UI.ViewManagement.InputPane.getForCurrentView().occludedRect.height; + } + return occluded; + }, + // See if the view has been resized to fit a keyboard + get _isResized() { + // Compare ratios. Very different includes IHM space. + var heightRatio = _Global.document.documentElement.clientHeight / _Global.innerHeight, widthRatio = _Global.document.documentElement.clientWidth / _Global.innerWidth; + // If they're nearly identical, then the view hasn't been resized for the IHM + // Only check one bound because we know the IHM will make it shorter, not skinnier. + return (widthRatio / heightRatio < 0.99); + }, + // Get the bottom of the visible area, relative to the top edge of the visible area. + get _visibleDocBottom() { + return exports._KeyboardInfo._visibleDocTop + exports._KeyboardInfo._visibleDocHeight; + }, + // Get the height of the visible area, e.g. the height of the visual viewport minus any IHM occlusion. + get _visibleDocHeight() { + return exports._KeyboardInfo._visualViewportHeight - exports._KeyboardInfo._extraOccluded; + }, + // Get the top offset of our visible area, aka the top of the visual viewport. + // This is always 0 when elements use -ms-device-fixed positioning. + get _visibleDocTop() { + return 0; + }, + // Get the offset for, and relative to, the bottom edge of the visual viewport plus any IHM occlusion. + get _visibleDocBottomOffset() { + // For -ms-device-fixed positioned elements, the bottom is just 0 when there's no IHM. + // When the IHM appears, the text input that invoked it may be in a position on the page that is occluded by the IHM. + // In that instance, the default browser behavior is to resize the visual viewport and scroll the input back into view. + // However, if the viewport resize is prevented by an IHM event listener, the keyboard will still occlude + // -ms-device-fixed elements, so we adjust the bottom offset of the appbar by the height of the occluded rect of the IHM. + return exports._KeyboardInfo._extraOccluded; + }, + // Get the visual viewport height. window.innerHeight doesn't return floating point values which are present with high DPI. + get _visualViewportHeight() { + var boundingRect = exports._KeyboardInfo._visualViewportSpace; + return boundingRect.height; + }, + // Get the visual viewport width. window.innerWidth doesn't return floating point values which are present with high DPI. + get _visualViewportWidth() { + var boundingRect = exports._KeyboardInfo._visualViewportSpace; + return boundingRect.width; + }, + // The visual viewport space element is hidden given -ms-device-fixed positioning and used to calculate + // the 4 edges of the visual viewport with floating point precision. + get _visualViewportSpace() { + var visualViewportSpace = _Global.document.body.querySelector("." + _Constants.visualViewportClass); + if (!visualViewportSpace) { + visualViewportSpace = _Global.document.createElement("DIV"); + visualViewportSpace.className = _Constants.visualViewportClass; + _Global.document.body.appendChild(visualViewportSpace); + } + return visualViewportSpace.getBoundingClientRect(); + }, + // Get total length of the IHM showPanel animation + get _animationShowLength() { + if (_BaseCoreUtils.hasWinRT) { + if (_WinRT.Windows.UI.Core.AnimationMetrics) { + // Desktop exposes the AnimationMetrics API that allows us to look up the relevant IHM animation metrics. + var a = _WinRT.Windows.UI.Core.AnimationMetrics, animationDescription = new a.AnimationDescription(a.AnimationEffect.showPanel, a.AnimationEffectTarget.primary); + var animations = animationDescription.animations; + var max = 0; + for (var i = 0; i < animations.size; i++) { + var animation = animations[i]; + max = Math.max(max, animation.delay + animation.duration); + } + return max; + } + else { + // Phone platform does not yet expose the Animation Metrics API. + // Hard code the correct values for the time being. + // https://github.com/winjs/winjs/issues/1060 + var animationDuration = 300; + var animationDelay = 50; + return animationDelay + animationDuration; + } + } + else { + return 0; + } + }, + // Padding for IHM timer to allow for first scroll event. Tpyically used in conjunction with the + // _animationShowLength to determine the length of time in which a showing IHM would have triggered + // a window resize to occur. + get _scrollTimeout() { + return _Constants.scrollTimeout; + }, + // _layoutViewportCoords is used with elements that use position:fixed instead of position:-ms-device-fixed + get _layoutViewportCoords() { + var topOffset = _Global.window.pageYOffset - _Global.document.documentElement.scrollTop; + var bottomOffset = _Global.document.documentElement.clientHeight - (topOffset + this._visibleDocHeight); + return { + visibleDocTop: topOffset, + visibleDocBottom: bottomOffset + }; + } + }; +}); + + +define('require-style!less/styles-overlay',[],function(){}); + +define('require-style!less/colors-overlay',[],function(){}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// animatable,appbar,appbars,divs,Flyout,Flyouts,iframe,Statics,unfocus,unselectable +define('WinJS/Controls/Flyout/_Overlay',[ + 'exports', + '../../Core/_Global', + '../../Core/_WinRT', + '../../Core/_Base', + '../../Core/_BaseUtils', + '../../Core/_ErrorFromName', + '../../Core/_Events', + '../../Core/_Resources', + '../../Core/_WriteProfilerMark', + '../../_Accents', + '../../Animations', + '../../Application', + '../../ControlProcessor', + '../../Promise', + '../../Scheduler', + '../../Utilities/_Control', + '../../Utilities/_ElementUtilities', + '../../Utilities/_KeyboardInfo', + '../_LegacyAppBar/_Constants', + 'require-style!less/styles-overlay', + 'require-style!less/colors-overlay' +], function overlayInit(exports, _Global, _WinRT, _Base, _BaseUtils, _ErrorFromName, _Events, _Resources, _WriteProfilerMark, _Accents, Animations, Application, ControlProcessor, Promise, Scheduler, _Control, _ElementUtilities, _KeyboardInfo, _Constants) { + "use strict"; + + _Accents.createAccentRule( + "button[aria-checked=true].win-command:before,\ + .win-menu-containsflyoutcommand button.win-command-flyout-activated:before", [ + { name: "background-color", value: _Accents.ColorTypes.accent }, + { name: "border-color", value: _Accents.ColorTypes.accent }, + ]); + + _Accents.createAccentRule(".win-flyout, .win-settingsflyout", [{ name: "border-color", value: _Accents.ColorTypes.accent }]); + + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + _Overlay: _Base.Namespace._lazy(function () { + + // Helper for Global Event listeners. Invokes the specified callback member function on each _Overlay in the DOM. + function _allOverlaysCallback(event, nameOfFunctionCall, stopImmediatePropagationWhenHandled) { + var elements = _Global.document.querySelectorAll("." + _Constants.overlayClass); + if (elements) { + var len = elements.length; + for (var i = 0; i < len; i++) { + var element = elements[i]; + var overlay = element.winControl; + if (!overlay._disposed) { + if (overlay) { + var handled = overlay[nameOfFunctionCall](event); + if (stopImmediatePropagationWhenHandled && handled) { + // The caller has indicated we should exit as soon as the event is handled. + return handled; + } + } + } + } + } + } + + // _Overlay Global Events Listener Class. We hang a singleton instance of this class off of a static _Overlay property. + var _GlobalListener = _Base.Class.define(function _GlobalListener_ctor() { + this._currentState = _GlobalListener.states.off; + + this._inputPaneShowing = this._inputPaneShowing.bind(this); + this._inputPaneHiding = this._inputPaneHiding.bind(this); + this._documentScroll = this._documentScroll.bind(this); + this._windowResized = this._windowResized.bind(this); + }, { + initialize: function _GlobalListener_initialize() { + this._toggleListeners(_GlobalListener.states.on); + }, + // Expose this for unit tests. + reset: function _GlobalListener_reset() { + this._toggleListeners(_GlobalListener.states.off); + this._toggleListeners(_GlobalListener.states.on); + }, + _inputPaneShowing: function _GlobalListener_inputePaneShowing(event) { + _WriteProfilerMark(_GlobalListener.profilerString + "_showingKeyboard,StartTM"); + _allOverlaysCallback(event, "_showingKeyboard"); + _WriteProfilerMark(_GlobalListener.profilerString + "_showingKeyboard,StopTM"); + }, + _inputPaneHiding: function _GlobalListener_inputPaneHiding(event) { + _WriteProfilerMark(_GlobalListener.profilerString + "_hidingKeyboard,StartTM"); + _allOverlaysCallback(event, "_hidingKeyboard"); + _WriteProfilerMark(_GlobalListener.profilerString + "_hidingKeyboard,StopTM"); + }, + _documentScroll: function _GlobalListener_documentScroll(event) { + _WriteProfilerMark(_GlobalListener.profilerString + "_checkScrollPosition,StartTM"); + _allOverlaysCallback(event, "_checkScrollPosition"); + _WriteProfilerMark(_GlobalListener.profilerString + "_checkScrollPosition,StopTM"); + }, + _windowResized: function _GlobalListener_windowResized(event) { + _WriteProfilerMark(_GlobalListener.profilerString + "_baseResize,StartTM"); + _allOverlaysCallback(event, "_baseResize"); + _WriteProfilerMark(_GlobalListener.profilerString + "_baseResize,StopTM"); + }, + _toggleListeners: function _GlobalListener_toggleListeners(newState) { + // Add/Remove global event listeners for all _Overlays + var listenerOperation; + if (this._currentState !== newState) { + if (newState === _GlobalListener.states.on) { + listenerOperation = "addEventListener"; + } else if (newState === _GlobalListener.states.off) { + listenerOperation = "removeEventListener"; + } + + if (_WinRT.Windows.UI.ViewManagement.InputPane) { + // React to Soft Keyboard events + var inputPane = _WinRT.Windows.UI.ViewManagement.InputPane.getForCurrentView(); + inputPane[listenerOperation]("showing", this._inputPaneShowing, false); + inputPane[listenerOperation]("hiding", this._inputPaneHiding, false); + + _Global.document[listenerOperation]("scroll", this._documentScroll, false); + } + + // Window resize event + _Global.addEventListener("resize", this._windowResized, false); + + this._currentState = newState; + } + }, + }, { + // Statics + profilerString: { + get: function () { + return "WinJS.UI._Overlay Global Listener:"; + } + }, + states: { + get: function () { + return { + off: 0, + on: 1, + }; + }, + }, + }); + + // Helper to get DOM elements from input single object or array or IDs/toolkit/dom elements + function _resolveElements(elements) { + // No input is just an empty array + if (!elements) { + return []; + } + + // Make sure it's in array form. + if (typeof elements === "string" || !elements || !elements.length) { + elements = [elements]; + } + + // Make sure we have a DOM element for each one, (could be string id name or toolkit object) + var i, + realElements = []; + for (i = 0; i < elements.length; i++) { + if (elements[i]) { + if (typeof elements[i] === "string") { + var element = _Global.document.getElementById(elements[i]); + if (element) { + realElements.push(element); + } + } else if (elements[i].element) { + realElements.push(elements[i].element); + } else { + realElements.push(elements[i]); + } + } + } + + return realElements; + } + + var strings = { + get duplicateConstruction() { return "Invalid argument: Controls may only be instantiated one time for each DOM element"; }, + get mustContainCommands() { return "Invalid HTML: AppBars/Menus must contain only AppBarCommands/MenuCommands"; }, + get closeOverlay() { return _Resources._getWinJSString("ui/closeOverlay").value; }, + }; + + var _Overlay = _Base.Class.define(function _Overlay_ctor(element, options) { + /// + /// + /// Constructs the Overlay control and associates it with the underlying DOM element. + /// + /// + /// The DOM element to be associated with the Overlay control. + /// + /// + /// The set of options to be applied initially to the Overlay control. + /// + /// A fully constructed Overlay control. + /// + this._baseOverlayConstructor(element, options); + }, { + // Functions/properties + _baseOverlayConstructor: function _Overlay_baseOverlayConstructor(element, options) { + + this._disposed = false; + + // Make sure there's an input element + if (!element) { + element = _Global.document.createElement("div"); + } + + // Check to make sure we weren't duplicated + var overlay = element.winControl; + if (overlay) { + throw new _ErrorFromName("WinJS.UI._Overlay.DuplicateConstruction", strings.duplicateConstruction); + } + + if (!this._element) { + this._element = element; + } + + if (!this._element.hasAttribute("tabIndex")) { + this._element.tabIndex = -1; + } + + this._sticky = false; + this._doNext = ""; + + this._element.style.visibility = "hidden"; + this._element.style.opacity = 0; + + // Remember ourselves + element.winControl = this; + + // Attach our css class + _ElementUtilities.addClass(this._element, _Constants.overlayClass); + _ElementUtilities.addClass(this._element, "win-disposable"); + + // We don't want to be selectable, set UNSELECTABLE + var unselectable = this._element.getAttribute("unselectable"); + if (unselectable === null || unselectable === undefined) { + this._element.setAttribute("unselectable", "on"); + } + + // Base animation is popIn/popOut + this._currentAnimateIn = this._baseAnimateIn; + this._currentAnimateOut = this._baseAnimateOut; + this._animationPromise = Promise.as(); + + // Command Animations to Queue + this._queuedToShow = []; + this._queuedToHide = []; + this._queuedCommandAnimation = false; + + if (options) { + _Control.setOptions(this, options); + } + + // Make sure _Overlay event handlers are hooked up (this aids light dismiss) + _Overlay._globalEventListeners.initialize(); + }, + + /// + element: { + get: function () { + return this._element; + } + }, + + dispose: function () { + /// + /// + /// Disposes this Overlay. + /// + /// + if (this._disposed) { + return; + } + + this._disposed = true; + this._dispose(); + }, + + _dispose: function _Overlay_dispose() { + // To be overridden by subclasses + }, + + _show: function _Overlay_show() { + // We call our base _baseShow because AppBar may need to override show + this._baseShow(); + }, + + _hide: function _Overlay_hide() { + // We call our base _baseHide because AppBar may need to override hide + this._baseHide(); + }, + + // Is the overlay "hidden"? + /// + hidden: { + get: function () { + return (this._element.style.visibility === "hidden" || + this._element.winAnimating === "hiding" || + this._doNext === "hide"); + }, + set: function (hidden) { + var currentlyHidden = this.hidden; + if (!hidden && currentlyHidden) { + this._show(); + } else if (hidden && !currentlyHidden) { + this._hide(); + } + } + }, + + addEventListener: function (type, listener, useCapture) { + /// + /// + /// Add an event listener to the DOM element for this Overlay + /// + /// Required. Event type to add, "beforehide", "afterhide", "beforeshow", or "aftershow" + /// Required. The event handler function to associate with this event. + /// Optional. True, register for the event capturing phase. False for the event bubbling phase. + /// + return this._element.addEventListener(type, listener, useCapture); + }, + + removeEventListener: function (type, listener, useCapture) { + /// + /// + /// Remove an event listener to the DOM element for this Overlay + /// + /// Required. Event type to remove, "beforehide", "afterhide", "beforeshow", or "aftershow" + /// Required. The event handler function to associate with this event. + /// Optional. True, register for the event capturing phase. False for the event bubbling phase. + /// + return this._element.removeEventListener(type, listener, useCapture); + }, + + _baseShow: function _Overlay_baseShow() { + // If we are already animating, just remember this for later + if (this._animating || this._needToHandleHidingKeyboard) { + this._doNext = "show"; + return false; + } + + if (this._element.style.visibility !== "visible") { + // Let us know we're showing. + this._element.winAnimating = "showing"; + + // Hiding, but not none + this._element.style.display = ""; + this._element.style.visibility = "hidden"; + + // In case their event is going to manipulate commands, see if there are + // any queued command animations we can handle while we're still hidden. + if (this._queuedCommandAnimation) { + this._showAndHideFast(this._queuedToShow, this._queuedToHide); + this._queuedToShow = []; + this._queuedToHide = []; + } + + // Send our "beforeShow" event + this._sendEvent(_Overlay.beforeShow); + + // Need to measure + this._findPosition(); + + // Make sure it's visible, and fully opaque. + // Do the popup thing, sending event afterward. + var that = this; + this._animationPromise = this._currentAnimateIn(). + then(function () { + that._baseEndShow(); + }, function () { + that._baseEndShow(); + }); + return true; + } + return false; + }, + + // Flyout in particular will need to measure our positioning. + _findPosition: function _Overlay_findPosition() { + }, + + _baseEndShow: function _Overlay_baseEndShow() { + if (this._disposed) { + return; + } + + // Make sure it's visible after showing + this._element.setAttribute("aria-hidden", "false"); + + this._element.winAnimating = ""; + + // Do our derived classes show stuff + this._endShow(); + + // We're shown now + if (this._doNext === "show") { + this._doNext = ""; + } + + // After showing, send the after showing event + this._sendEvent(_Overlay.afterShow); + this._writeProfilerMark("show,StopTM"); // Overlay writes the stop profiler mark for all of its derived classes. + + // If we had something queued, do that + Scheduler.schedule(this._checkDoNext, Scheduler.Priority.normal, this, "WinJS.UI._Overlay._checkDoNext"); + + }, + + _endShow: function _Overlay_endShow() { + // Nothing by default + }, + + _baseHide: function _Overlay_baseHide() { + // If we are already animating, just remember this for later + if (this._animating) { + this._doNext = "hide"; + return false; + } + + // In the unlikely event we're between the hiding keyboard and the resize events, just snap it away: + if (this._needToHandleHidingKeyboard) { + // use the "uninitialized" flag + this._element.style.visibility = ""; + } + + if (this._element.style.visibility !== "hidden") { + // Let us know we're hiding, accessibility as well. + this._element.winAnimating = "hiding"; + this._element.setAttribute("aria-hidden", "true"); + + // Send our "beforeHide" event + this._sendEvent(_Overlay.beforeHide); + + // If our visibility is empty, then this is the first time, just hide it + if (this._element.style.visibility === "") { + // Initial hiding, just hide it + this._element.style.opacity = 0; + this._baseEndHide(); + } else { + // Make sure it's hidden, and fully transparent. + var that = this; + this._animationPromise = this._currentAnimateOut(). + then(function () { + that._baseEndHide(); + }, function () { + that._baseEndHide(); + }); + } + return true; + } + + return false; + }, + + _baseEndHide: function _Overlay_baseEndHide() { + if (this._disposed) { + return; + } + + // Do our derived classes hide stuff + this._beforeEndHide(); + + // Make sure animation is finished. + this._element.style.visibility = "hidden"; + this._element.style.display = "none"; + this._element.winAnimating = ""; + + // In case their event is going to manipulate commands, see if there + // are any queued command animations we can handle now we're hidden. + if (this._queuedCommandAnimation) { + this._showAndHideFast(this._queuedToShow, this._queuedToHide); + this._queuedToShow = []; + this._queuedToHide = []; + } + + // We're hidden now + if (this._doNext === "hide") { + this._doNext = ""; + } + + // After hiding, send our "afterHide" event + this._sendEvent(_Overlay.afterHide); + this._writeProfilerMark("hide,StopTM"); // Overlay writes the stop profiler mark for all of its derived classes. + + + // If we had something queued, do that. This has to be after + // the afterHide event in case it triggers a show() and they + // have something to do in beforeShow that requires afterHide first. + Scheduler.schedule(this._checkDoNext, Scheduler.Priority.normal, this, "WinJS.UI._Overlay._checkDoNext"); + }, + + // Called after the animation but while the Overlay is still visible. It's + // important that this runs while the Overlay is visible because hiding + // a DOM element (e.g. visibility="hidden", display="none") while it contains + // focus has the side effect of moving focus to the body or null and triggering + // focus move events. _beforeEndHide is a good hook for the Overlay to move focus + // elsewhere before its DOM element gets hidden. + _beforeEndHide: function _Overlay_beforeEndHide() { + // Nothing by default + }, + + _checkDoNext: function _Overlay_checkDoNext() { + // Do nothing if we're still animating + if (this._animating || this._needToHandleHidingKeyboard || this._disposed) { + return; + } + + if (this._doNext === "hide") { + // Do hide first because animating commands would be easier + this._hide(); + this._doNext = ""; + } else if (this._queuedCommandAnimation) { + // Do queued commands before showing if possible + this._showAndHideQueue(); + } else if (this._doNext === "show") { + // Show last so that we don't unnecessarily animate commands + this._show(); + this._doNext = ""; + } + }, + + // Default animations + _baseAnimateIn: function _Overlay_baseAnimateIn() { + this._element.style.opacity = 0; + this._element.style.visibility = "visible"; + // touch opacity so that IE fades from the 0 we just set to 1 + _Global.getComputedStyle(this._element, null).opacity; + return Animations.fadeIn(this._element); + }, + + _baseAnimateOut: function _Overlay_baseAnimateOut() { + this._element.style.opacity = 1; + // touch opacity so that IE fades from the 1 we just set to 0 + _Global.getComputedStyle(this._element, null).opacity; + return Animations.fadeOut(this._element); + }, + + _animating: { + get: function _Overlay_animating_get() { + // Ensure it's a boolean because we're using the DOM element to keep in-sync + return !!this._element.winAnimating; + } + }, + + // Send one of our events + _sendEvent: function _Overlay_sendEvent(eventName, detail) { + if (this._disposed) { + return; + } + var event = _Global.document.createEvent("CustomEvent"); + event.initEvent(eventName, true, true, (detail || {})); + this._element.dispatchEvent(event); + }, + + // Show commands + _showCommands: function _Overlay_showCommands(commands, immediate) { + var showHide = this._resolveCommands(commands); + this._showAndHideCommands(showHide.commands, [], immediate); + }, + + // Hide commands + _hideCommands: function _Overlay_hideCommands(commands, immediate) { + var showHide = this._resolveCommands(commands); + this._showAndHideCommands([], showHide.commands, immediate); + }, + + // Hide commands + _showOnlyCommands: function _Overlay_showOnlyCommands(commands, immediate) { + var showHide = this._resolveCommands(commands); + this._showAndHideCommands(showHide.commands, showHide.others, immediate); + }, + + _showAndHideCommands: function _Overlay_showAndHideCommands(showCommands, hideCommands, immediate) { + // Immediate is "easy" + if (immediate || (this.hidden && !this._animating)) { + // Immediate mode (not animated) + this._showAndHideFast(showCommands, hideCommands); + // Need to remove them from queues, but others could be queued + this._removeFromQueue(showCommands, this._queuedToShow); + this._removeFromQueue(hideCommands, this._queuedToHide); + } else { + + // Queue Commands + this._updateAnimateQueue(showCommands, this._queuedToShow, this._queuedToHide); + this._updateAnimateQueue(hideCommands, this._queuedToHide, this._queuedToShow); + } + }, + + _removeFromQueue: function _Overlay_removeFromQueue(commands, queue) { + // remove commands from queue. + var count; + for (count = 0; count < commands.length; count++) { + // Remove if it was in queue + var countQ; + for (countQ = 0; countQ < queue.length; countQ++) { + if (queue[countQ] === commands[count]) { + queue.splice(countQ, 1); + break; + } + } + } + }, + + _updateAnimateQueue: function _Overlay_updateAnimateQueue(addCommands, toQueue, fromQueue) { + if (this._disposed) { + return; + } + + // Add addCommands to toQueue and remove addCommands from fromQueue. + var count; + for (count = 0; count < addCommands.length; count++) { + // See if it's already in toQueue + var countQ; + for (countQ = 0; countQ < toQueue.length; countQ++) { + if (toQueue[countQ] === addCommands[count]) { + break; + } + } + if (countQ === toQueue.length) { + // Not found, add it + toQueue[countQ] = addCommands[count]; + } + // Remove if it was in fromQueue + for (countQ = 0; countQ < fromQueue.length; countQ++) { + if (fromQueue[countQ] === addCommands[count]) { + fromQueue.splice(countQ, 1); + break; + } + } + } + // If we haven't queued the actual animation + if (!this._queuedCommandAnimation) { + // If not already animating, we'll need to call _checkDoNext + if (!this._animating) { + Scheduler.schedule(this._checkDoNext, Scheduler.Priority.normal, this, "WinJS.UI._Overlay._checkDoNext"); + } + this._queuedCommandAnimation = true; + } + }, + + // show/hide commands without doing any animation. + _showAndHideFast: function _Overlay_showAndHideFast(showCommands, hideCommands) { + var count; + var command; + for (count = 0; count < showCommands.length; count++) { + command = showCommands[count]; + if (command && command.style) { + command.style.visibility = ""; + command.style.display = ""; + } + } + for (count = 0; count < hideCommands.length; count++) { + command = hideCommands[count]; + if (command && command.style) { + command.style.visibility = "hidden"; + command.style.display = "none"; + } + } + + this._commandsUpdated(); + + }, + + // show and hide the queued commands, perhaps animating if overlay isn't hidden. + _showAndHideQueue: function _Overlay_showAndHideQueue() { + // Only called if not currently animating. + // We'll be done with the queued stuff when we return. + this._queuedCommandAnimation = false; + + // Shortcut if hidden + if (this.hidden) { + this._showAndHideFast(this._queuedToShow, this._queuedToHide); + // Might be something else to do + Scheduler.schedule(this._checkDoNext, Scheduler.Priority.normal, this, "WinJS.UI._Overlay._checkDoNext"); + } else { + // Animation has 3 parts: "hiding", "showing", and "moving" + // PVL has "addToList" and "deleteFromList", both of which allow moving parts. + // So we'll set up "add" for showing, and use "delete" for "hiding" + moving, + // then trigger both at the same time. + var showCommands = this._queuedToShow; + var hideCommands = this._queuedToHide; + var siblings = this._findSiblings(showCommands.concat(hideCommands)); + + // Filter out the commands queued for animation that don't need to be animated. + var count; + for (count = 0; count < showCommands.length; count++) { + // If this one's not real or not attached, skip it + if (!showCommands[count] || + !showCommands[count].style || + !_Global.document.body.contains(showCommands[count])) { + // Not real, skip it + showCommands.splice(count, 1); + count--; + } else if (showCommands[count].style.visibility !== "hidden" && showCommands[count].style.opacity !== "0") { + // Don't need to animate showing this one, already visible, so now it's a sibling + siblings.push(showCommands[count]); + showCommands.splice(count, 1); + count--; + } + } + for (count = 0; count < hideCommands.length; count++) { + // If this one's not real or not attached, skip it + if (!hideCommands[count] || + !hideCommands[count].style || + !_Global.document.body.contains(hideCommands[count]) || + hideCommands[count].style.visibility === "hidden" || + hideCommands[count].style.opacity === "0") { + // Don't need to animate hiding this one, not real, or it's hidden, + // so don't even need it as a sibling. + hideCommands.splice(count, 1); + count--; + } + } + + // Start command animations. + var commandsAnimationPromise = this._baseBeginAnimateCommands(showCommands, hideCommands, siblings); + + // Hook end animations + var that = this; + if (commandsAnimationPromise) { + // Needed to animate + commandsAnimationPromise.done( + function () { that._baseEndAnimateCommands(hideCommands); }, + function () { that._baseEndAnimateCommands(hideCommands); } + ); + } else { + // Already positioned correctly + Scheduler.schedule(function Overlay_async_baseEndAnimationCommands() { that._baseEndAnimateCommands([]); }, + Scheduler.Priority.normal, null, + "WinJS.UI._Overlay._endAnimateCommandsWithoutAnimation"); + } + } + + // Done, clear queues + this._queuedToShow = []; + this._queuedToHide = []; + }, + + _baseBeginAnimateCommands: function _Overlay_baseBeginAnimateCommands(showCommands, hideCommands, siblings) { + // The parameters are 3 mutually exclusive arrays of win-command elements contained in this Overlay. + // 1) showCommands[]: All of the HIDDEN win-command elements that ARE scheduled to show. + // 2) hideCommands[]: All of the VISIBLE win-command elements that ARE shceduled to hide. + // 3) siblings[]: i. All VISIBLE win-command elements that ARE NOT scheduled to hide. + // ii. All HIDDEN win-command elements that ARE NOT scheduled to hide OR show. + this._beginAnimateCommands(showCommands, hideCommands, this._getVisibleCommands(siblings)); + + var showAnimated = null, + hideAnimated = null; + + // Hide commands first, with siblings if necessary, + // so that the showing commands don't disrupt the hiding commands position. + if (hideCommands.length > 0) { + hideAnimated = Animations.createDeleteFromListAnimation(hideCommands, showCommands.length === 0 ? siblings : undefined); + } + if (showCommands.length > 0) { + showAnimated = Animations.createAddToListAnimation(showCommands, siblings); + } + + // Update hiding commands + for (var count = 0, len = hideCommands.length; count < len; count++) { + // Need to fix our position + var rectangle = hideCommands[count].getBoundingClientRect(), + style = _Global.getComputedStyle(hideCommands[count]); + + // Use the bounding box, adjusting for margins + hideCommands[count].style.top = (rectangle.top - parseFloat(style.marginTop)) + "px"; + hideCommands[count].style.left = (rectangle.left - parseFloat(style.marginLeft)) + "px"; + hideCommands[count].style.opacity = 0; + hideCommands[count].style.position = "fixed"; + } + + // Mark as animating + this._element.winAnimating = "rearranging"; + + // Start hiding animations + // Hide needs extra cleanup when done + var promise = null; + if (hideAnimated) { + promise = hideAnimated.execute(); + } + + // Update showing commands, + // After hiding commands so that the hiding ones fade in the right place. + for (count = 0; count < showCommands.length; count++) { + showCommands[count].style.visibility = ""; + showCommands[count].style.display = ""; + showCommands[count].style.opacity = 1; + } + + // Start showing animations + if (showAnimated) { + var newPromise = showAnimated.execute(); + if (promise) { + promise = Promise.join([promise, newPromise]); + } else { + promise = newPromise; + } + } + + return promise; + }, + + _beginAnimateCommands: function _Overlay_beginAnimateCommands() { + // Nothing by default + }, + + _getVisibleCommands: function _Overlay_getVisibleCommands(commandSubSet) { + var command, + commands = commandSubSet, + visibleCommands = []; + + if (!commands) { + // Crawl the inner HTML for the commands. + commands = this.element.querySelectorAll(".win-command"); + } + + for (var i = 0, len = commands.length; i < len; i++) { + command = commands[i].winControl || commands[i]; + if (!command.hidden) { + visibleCommands.push(command); + } + } + + return visibleCommands; + }, + + // Once animation is complete, ensure that the commands are display:none + // and check if there's another animation to start. + _baseEndAnimateCommands: function _Overlay_baseEndAnimateCommands(hideCommands) { + if (this._disposed) { + return; + } + + // Update us + var count; + for (count = 0; count < hideCommands.length; count++) { + // Force us back into our appbar so that we can show again correctly + hideCommands[count].style.position = ""; + hideCommands[count].style.top = ""; + hideCommands[count].style.left = ""; + hideCommands[count].getBoundingClientRect(); + // Now make us really hidden + hideCommands[count].style.visibility = "hidden"; + hideCommands[count].style.display = "none"; + hideCommands[count].style.opacity = 1; + } + // Done animating + this._element.winAnimating = ""; + + this._endAnimateCommands(); + + // Might be something else to do + this._checkDoNext(); + }, + + _endAnimateCommands: function _Overlay_endAnimateCommands() { + // Nothing by default + }, + + // Resolves our commands + _resolveCommands: function _Overlay_resolveCommands(commands) { + // First make sure they're all DOM elements. + commands = _resolveElements(commands); + + // Now make sure they're all in this container + var result = {}; + result.commands = []; + result.others = []; + var allCommands = this.element.querySelectorAll(".win-command"); + var countAll, countIn; + for (countAll = 0; countAll < allCommands.length; countAll++) { + var found = false; + for (countIn = 0; countIn < commands.length; countIn++) { + if (commands[countIn] === allCommands[countAll]) { + result.commands.push(allCommands[countAll]); + commands.splice(countIn, 1); + found = true; + break; + } + } + if (!found) { + result.others.push(allCommands[countAll]); + } + } + return result; + }, + + // Find siblings, all DOM elements now. + // Returns all .win-commands in this Overlay that are NOT in the passed in 'commands' array. + _findSiblings: function _Overlay_findSiblings(commands) { + // Now make sure they're all in this container + var siblings = []; + var allCommands = this.element.querySelectorAll(".win-command"); + var countAll, countIn; + for (countAll = 0; countAll < allCommands.length; countAll++) { + var found = false; + for (countIn = 0; countIn < commands.length; countIn++) { + if (commands[countIn] === allCommands[countAll]) { + commands.splice(countIn, 1); + found = true; + break; + } + } + if (!found) { + siblings.push(allCommands[countAll]); + } + } + return siblings; + }, + + _baseResize: function _Overlay_baseResize(event) { + // Call specific resize + this._resize(event); + }, + + _hideOrDismiss: function _Overlay_hideOrDismiss() { + var element = this._element; + if (element && _ElementUtilities.hasClass(element, _Constants.settingsFlyoutClass)) { + this._dismiss(); + } else if (element && _ElementUtilities.hasClass(element, _Constants.appBarClass)) { + this.close(); + } else { + this.hide(); + } + }, + + _resize: function _Overlay_resize() { + // Nothing by default + }, + + _commandsUpdated: function _Overlay_commandsUpdated() { + // Nothing by default + }, + + _checkScrollPosition: function _Overlay_checkScrollPosition() { + // Nothing by default + }, + + _showingKeyboard: function _Overlay_showingKeyboard() { + // Nothing by default + }, + + _hidingKeyboard: function _Overlay_hidingKeyboard() { + // Nothing by default + }, + + // Verify that this HTML AppBar only has AppBar/MenuCommands. + _verifyCommandsOnly: function _Overlay_verifyCommandsOnly(element, type) { + var children = element.children; + var commands = new Array(children.length); + for (var i = 0; i < children.length; i++) { + // If constructed they have win-command class, otherwise they have data-win-control + if (!_ElementUtilities.hasClass(children[i], "win-command") && + children[i].getAttribute("data-win-control") !== type) { + // Wasn't tagged with class or AppBar/MenuCommand, not an AppBar/MenuCommand + throw new _ErrorFromName("WinJS.UI._Overlay.MustContainCommands", strings.mustContainCommands); + } else { + // Instantiate the commands. + ControlProcessor.processAll(children[i]); + commands[i] = children[i].winControl; + } + } + return commands; + }, + + // Sets focus on what we think is the last tab stop. If nothing is focusable will + // try to set focus on itself. + _focusOnLastFocusableElementOrThis: function _Overlay_focusOnLastFocusableElementOrThis() { + if (!this._focusOnLastFocusableElement()) { + // Nothing is focusable. Set focus to this. + _Overlay._trySetActive(this._element); + } + }, + + // Sets focus to what we think is the last tab stop. This element must have + // a firstDiv with tabIndex equal to the lowest tabIndex in the element + // and a finalDiv with tabIndex equal to the highest tabIndex in the element. + // Also the firstDiv must be its first child and finalDiv be its last child. + // Returns true if successful, false otherwise. + _focusOnLastFocusableElement: function _Overlay_focusOnLastFocusableElement() { + if (this._element.firstElementChild) { + var oldFirstTabIndex = this._element.firstElementChild.tabIndex; + var oldLastTabIndex = this._element.lastElementChild.tabIndex; + this._element.firstElementChild.tabIndex = -1; + this._element.lastElementChild.tabIndex = -1; + + var tabResult = _ElementUtilities._focusLastFocusableElement(this._element); + + if (tabResult) { + _Overlay._trySelect(_Global.document.activeElement); + } + + this._element.firstElementChild.tabIndex = oldFirstTabIndex; + this._element.lastElementChild.tabIndex = oldLastTabIndex; + + return tabResult; + } else { + return false; + } + }, + + + // Sets focus on what we think is the first tab stop. If nothing is focusable will + // try to set focus on itself. + _focusOnFirstFocusableElementOrThis: function _Overlay_focusOnFirstFocusableElementOrThis() { + if (!this._focusOnFirstFocusableElement()) { + // Nothing is focusable. Set focus to this. + _Overlay._trySetActive(this._element); + } + }, + + // Sets focus to what we think is the first tab stop. This element must have + // a firstDiv with tabIndex equal to the lowest tabIndex in the element + // and a finalDiv with tabIndex equal to the highest tabIndex in the element. + // Also the firstDiv must be its first child and finalDiv be its last child. + // Returns true if successful, false otherwise. + _focusOnFirstFocusableElement: function _Overlay__focusOnFirstFocusableElement(useSetActive, scroller) { + if (this._element.firstElementChild) { + var oldFirstTabIndex = this._element.firstElementChild.tabIndex; + var oldLastTabIndex = this._element.lastElementChild.tabIndex; + this._element.firstElementChild.tabIndex = -1; + this._element.lastElementChild.tabIndex = -1; + + var tabResult = _ElementUtilities._focusFirstFocusableElement(this._element, useSetActive, scroller); + + if (tabResult) { + _Overlay._trySelect(_Global.document.activeElement); + } + + this._element.firstElementChild.tabIndex = oldFirstTabIndex; + this._element.lastElementChild.tabIndex = oldLastTabIndex; + + return tabResult; + } else { + return false; + } + }, + + _writeProfilerMark: function _Overlay_writeProfilerMark(text) { + _WriteProfilerMark("WinJS.UI._Overlay:" + this._id + ":" + text); + } + }, + { + // Statics + + _isFlyoutVisible: function () { + var flyouts = _Global.document.querySelectorAll("." + _Constants.flyoutClass); + for (var i = 0; i < flyouts.length; i++) { + var flyoutControl = flyouts[i].winControl; + if (flyoutControl && !flyoutControl.hidden) { + return true; + } + } + + return false; + }, + + // Try to set us as active + _trySetActive: function (element, scroller) { + if (!element || !_Global.document.body || !_Global.document.body.contains(element)) { + return false; + } + if (!_ElementUtilities._setActive(element, scroller)) { + return false; + } + return (element === _Global.document.activeElement); + }, + + // Try to select the text so keyboard can be used. + _trySelect: function (element) { + try { + if (element && element.select) { + element.select(); + } + } catch (e) { } + }, + + _sizeOfDocument: function () { + return { + width: _Global.document.documentElement.offsetWidth, + height: _Global.document.documentElement.offsetHeight, + }; + }, + + _getParentControlUsingClassName: function (element, className) { + while (element && element !== _Global.document.body) { + if (_ElementUtilities.hasClass(element, className)) { + return element.winControl; + } + element = element.parentNode; + } + return null; + }, + + // Static controller for _Overlay global events registering/unregistering. + _globalEventListeners: new _GlobalListener(), + + // Show/Hide all bars + _hideAppBars: function _Overlay_hideAppBars(bars, keyboardInvoked) { + var allBarsAnimationPromises = bars.map(function (bar) { + bar.close(); + return bar._animationPromise; + }); + return Promise.join(allBarsAnimationPromises); + }, + + _showAppBars: function _Overlay_showAppBars(bars, keyboardInvoked) { + var allBarsAnimationPromises = bars.map(function (bar) { + bar._show(); + return bar._animationPromise; + }); + return Promise.join(allBarsAnimationPromises); + }, + + // WWA Soft Keyboard offsets + _keyboardInfo: _KeyboardInfo._KeyboardInfo, + + // Padding for IHM timer to allow for first scroll event + _scrollTimeout: _KeyboardInfo._KeyboardInfo._scrollTimeout, + + // Events + beforeShow: "beforeshow", + beforeHide: "beforehide", + afterShow: "aftershow", + afterHide: "afterhide", + + commonstrings: { + get cannotChangeCommandsWhenVisible() { return "Invalid argument: You must call hide() before changing {0} commands"; }, + get cannotChangeHiddenProperty() { return "Unable to set hidden property while parent {0} is visible."; } + }, + }); + + _Base.Class.mix(_Overlay, _Control.DOMEventMixin); + + return _Overlay; + }) + }); + +}); + + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// appbar,Flyout,Flyouts,Statics +define('WinJS/Controls/Flyout',[ + 'exports', + '../Core/_Global', + '../Core/_Base', + '../Core/_BaseUtils', + '../Core/_ErrorFromName', + '../Core/_Events', + '../Core/_Log', + '../Core/_Resources', + '../Core/_WriteProfilerMark', + '../Animations', + '../_Signal', + '../_LightDismissService', + '../Utilities/_Dispose', + '../Utilities/_ElementUtilities', + '../Utilities/_KeyboardBehavior', + '../Utilities/_Hoverable', + './_LegacyAppBar/_Constants', + './Flyout/_Overlay' +], function flyoutInit(exports, _Global, _Base, _BaseUtils, _ErrorFromName, _Events, _Log, _Resources, _WriteProfilerMark, Animations, _Signal, _LightDismissService, _Dispose, _ElementUtilities, _KeyboardBehavior, _Hoverable, _Constants, _Overlay) { + "use strict"; + + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + /// + /// + /// Displays lightweight UI that is either informational, or requires user interaction. + /// Unlike a dialog, a Flyout can be light dismissed by clicking or tapping off of it. + /// + /// + /// + /// Flyout + /// + /// + /// ]]> + /// Raised just before showing a flyout. + /// Raised immediately after a flyout is fully shown. + /// Raised just before hiding a flyout. + /// Raised immediately after a flyout is fully hidden. + /// The Flyout control itself. + /// + /// + Flyout: _Base.Namespace._lazy(function () { + var Key = _ElementUtilities.Key; + + function getDimension(element, property) { + return _ElementUtilities.convertToPixels(element, _Global.getComputedStyle(element, null)[property]); + } + + var strings = { + get ariaLabel() { return _Resources._getWinJSString("ui/flyoutAriaLabel").value; }, + get noAnchor() { return "Invalid argument: Flyout anchor element not found in DOM."; }, + get badPlacement() { return "Invalid argument: Flyout placement should be 'top' (default), 'bottom', 'left', 'right', 'auto', 'autohorizontal', or 'autovertical'."; }, + get badAlignment() { return "Invalid argument: Flyout alignment should be 'center' (default), 'left', or 'right'."; } + }; + + var createEvent = _Events._createEventProperty; + + // _LightDismissableLayer is an ILightDismissable which manages a set of ILightDismissables. + // It acts as a proxy between the LightDismissService and the light dismissables it manages. + // It enables multiple dismissables to be above the click eater at the same time. + var _LightDismissableLayer = _Base.Class.define(function _LightDismissableLayer_ctor(onLightDismiss) { + this._onLightDismiss = onLightDismiss; + this._currentlyFocusedClient = null; + this._clients = []; // Array of ILightDismissables + }, { + // Dismissables should call this as soon as they are ready to be shown. More specifically, they should call this: + // - After they are in the DOM and ready to receive focus (e.g. style.display cannot be "none") + // - Before their entrance animation is played + shown: function _LightDismissableLayer_shown(client /*: ILightDismissable */) { + client._focusable = true; + var index = this._clients.indexOf(client); + if (index === -1) { + this._clients.push(client); + client.onShow(this); + if (!_LightDismissService.isShown(this)) { + _LightDismissService.shown(this); + } else { + _LightDismissService.updated(this); + this._activateTopFocusableClientIfNeeded(); + } + } + }, + + // Dismissables should call this at the start of their exit animation. A "hiding", + // dismissable will still be rendered with the proper z-index but it will no + // longer be given focus. Also, focus is synchronously moved out of this dismissable. + hiding: function _LightDismissableLayer_hiding(client /*: ILightDismissable */) { + var index = this._clients.indexOf(client); + if (index !== -1) { + this._clients[index]._focusable = false; + this._activateTopFocusableClientIfNeeded(); + } + }, + + // Dismissables should call this when they are done being dismissed (i.e. after their exit animation has finished) + hidden: function _LightDismissableLayer_hidden(client /*: ILightDismissable */) { + var index = this._clients.indexOf(client); + if (index !== -1) { + this._clients.splice(index, 1); + client.setZIndex(""); + client.onHide(); + if (this._clients.length === 0) { + _LightDismissService.hidden(this); + } else { + _LightDismissService.updated(this); + this._activateTopFocusableClientIfNeeded(); + } + } + }, + + keyDown: function _LightDismissableLayer_keyDown(client /*: ILightDismissable */, eventObject) { + _LightDismissService.keyDown(this, eventObject); + }, + keyUp: function _LightDismissableLayer_keyUp(client /*: ILightDismissable */, eventObject) { + _LightDismissService.keyUp(this, eventObject); + }, + keyPress: function _LightDismissableLayer_keyPress(client /*: ILightDismissable */, eventObject) { + _LightDismissService.keyPress(this, eventObject); + }, + + // Used by tests. + clients: { + get: function _LightDismissableLayer_clients_get() { + return this._clients; + } + }, + + _clientForElement: function _LightDismissableLayer_clientForElement(element) { + for (var i = this._clients.length - 1; i >= 0; i--) { + if (this._clients[i].containsElement(element)) { + return this._clients[i]; + } + } + return null; + }, + + _focusableClientForElement: function _LightDismissableLayer_focusableClientForElement(element) { + for (var i = this._clients.length - 1; i >= 0; i--) { + if (this._clients[i]._focusable && this._clients[i].containsElement(element)) { + return this._clients[i]; + } + } + return null; + }, + + _getTopmostFocusableClient: function _LightDismissableLayer_getTopmostFocusableClient() { + for (var i = this._clients.length - 1; i >= 0; i--) { + var client = this._clients[i]; + if (client && client._focusable) { + return client; + } + } + return null; + }, + + _activateTopFocusableClientIfNeeded: function _LightDismissableLayer_activateTopFocusableClientIfNeeded() { + var topClient = this._getTopmostFocusableClient(); + if (topClient && _LightDismissService.isTopmost(this)) { + // If the last input type was keyboard, use focus() so a keyboard focus visual is drawn. + // Otherwise, use setActive() so no focus visual is drawn. + var useSetActive = !_KeyboardBehavior._keyboardSeenLast; + topClient.onTakeFocus(useSetActive); + } + }, + + // ILightDismissable + // + + setZIndex: function _LightDismissableLayer_setZIndex(zIndex) { + this._clients.forEach(function (client, index) { + client.setZIndex(zIndex + index); + }, this); + }, + getZIndexCount: function _LightDismissableLayer_getZIndexCount() { + return this._clients.length; + }, + containsElement: function _LightDismissableLayer_containsElement(element) { + return !!this._clientForElement(element); + }, + onTakeFocus: function _LightDismissableLayer_onTakeFocus(useSetActive) { + // Prefer the client that has focus + var client = this._focusableClientForElement(_Global.document.activeElement); + + if (!client && this._clients.indexOf(this._currentlyFocusedClient) !== -1 && this._currentlyFocusedClient._focusable) { + // Next try the client that had focus most recently + client = this._currentlyFocusedClient; + } + + if (!client) { + // Finally try the client at the top of the stack + client = this._getTopmostFocusableClient(); + } + + this._currentlyFocusedClient = client; + client && client.onTakeFocus(useSetActive); + }, + onFocus: function _LightDismissableLayer_onFocus(element) { + this._currentlyFocusedClient = this._clientForElement(element); + this._currentlyFocusedClient && this._currentlyFocusedClient.onFocus(element); + }, + onShow: function _LightDismissableLayer_onShow(service /*: ILightDismissService */) { }, + onHide: function _LightDismissableLayer_onHide() { + this._currentlyFocusedClient = null; + }, + onKeyInStack: function _LightDismissableLayer_onKeyInStack(info /*: IKeyboardInfo*/) { + // A keyboard event occurred in the light dismiss stack. Notify the flyouts to + // give them the opportunity to handle this evnet. + var index = this._clients.indexOf(this._currentlyFocusedClient); + if (index !== -1) { + var clients = this._clients.slice(0, index + 1); + for (var i = clients.length - 1; i >= 0 && !info.propagationStopped; i--) { + if (clients[i]._focusable) { + clients[i].onKeyInStack(info); + } + } + } + }, + onShouldLightDismiss: function _LightDismissableLayer_onShouldLightDismiss(info) { + return _LightDismissService.DismissalPolicies.light(info); + }, + onLightDismiss: function _LightDismissableLayer_onLightDismiss(info) { + this._onLightDismiss(info); + } + }); + + // Singleton class for managing cascading flyouts + var _CascadeManager = _Base.Class.define(function _CascadeManager_ctor() { + var that = this; + this._dismissableLayer = new _LightDismissableLayer(function _CascadeManager_onLightDismiss(info) { + if (info.reason === _LightDismissService.LightDismissalReasons.escape) { + that.collapseFlyout(that.getAt(that.length - 1)); + } else { + that.collapseAll(); + } + }); + this._cascadingStack = []; + this._handleKeyDownInCascade_bound = this._handleKeyDownInCascade.bind(this); + this._inputType = null; + }, + { + appendFlyout: function _CascadeManager_appendFlyout(flyoutToAdd) { + // PRECONDITION: flyoutToAdd must not already be in the cascade. + _Log.log && this.indexOf(flyoutToAdd) >= 0 && _Log.log('_CascadeManager is attempting to append a Flyout that is already in the cascade.', "winjs _CascadeManager", "error"); + // PRECONDITION: this.reentrancyLock must be false. appendFlyout should only be called from baseFlyoutShow() which is the function responsible for preventing reentrancy. + _Log.log && this.reentrancyLock && _Log.log('_CascadeManager is attempting to append a Flyout through reentrancy.', "winjs _CascadeManager", "error"); + + // IF the anchor element for flyoutToAdd is contained within another flyout, + // && that flyout is currently in the cascadingStack, consider that flyout to be the parent of flyoutToAdd: + // Remove from the cascadingStack, any subflyout descendants of the parent flyout. + // ELSE flyoutToAdd isn't anchored to any of the Flyouts in the existing cascade + // Collapse the entire cascadingStack to start a new cascade. + // FINALLY: + // add flyoutToAdd to the end of the cascading stack. Monitor it for events. + var indexOfParentFlyout = this.indexOfElement(flyoutToAdd._currentAnchor); + if (indexOfParentFlyout >= 0) { + this.collapseFlyout(this.getAt(indexOfParentFlyout + 1)); + } else { + this.collapseAll(); + } + + flyoutToAdd.element.addEventListener("keydown", this._handleKeyDownInCascade_bound, false); + this._cascadingStack.push(flyoutToAdd); + this._dismissableLayer.shown(flyoutToAdd._dismissable); + }, + collapseFlyout: function _CascadeManager_collapseFlyout(flyout) { + // Removes flyout param and its subflyout descendants from the _cascadingStack. + if (!this.reentrancyLock && flyout && this.indexOf(flyout) >= 0) { + this.reentrancyLock = true; + var signal = new _Signal(); + this.unlocked = signal.promise; + + var subFlyout; + while (this.length && flyout !== subFlyout) { + subFlyout = this._cascadingStack.pop(); + subFlyout.element.removeEventListener("keydown", this._handleKeyDownInCascade_bound, false); + subFlyout._hide(); // We use the reentrancyLock to prevent reentrancy here. + } + + if (this._cascadingStack.length === 0) { + // The cascade is empty so clear the input type. This gives us the opportunity + // to recalculate the input type when the next cascade starts. + this._inputType = null; + } + + this.reentrancyLock = false; + this.unlocked = null; + signal.complete(); + } + }, + flyoutHiding: function _CascadeManager_flyoutHiding(flyout) { + this._dismissableLayer.hiding(flyout._dismissable); + }, + flyoutHidden: function _CascadeManager_flyoutHidden(flyout) { + this._dismissableLayer.hidden(flyout._dismissable); + }, + collapseAll: function _CascadeManager_collapseAll() { + // Empties the _cascadingStack and hides all flyouts. + var headFlyout = this.getAt(0); + if (headFlyout) { + this.collapseFlyout(headFlyout); + } + }, + indexOf: function _CascadeManager_indexOf(flyout) { + return this._cascadingStack.indexOf(flyout); + }, + indexOfElement: function _CascadeManager_indexOfElement(el) { + // Returns an index cooresponding to the Flyout in the cascade whose element contains the element in question. + // Returns -1 if the element is not contained by any Flyouts in the cascade. + var indexOfAssociatedFlyout = -1; + for (var i = 0, len = this.length; i < len; i++) { + var currentFlyout = this.getAt(i); + if (currentFlyout.element.contains(el)) { + indexOfAssociatedFlyout = i; + break; + } + } + return indexOfAssociatedFlyout; + }, + length: { + get: function _CascadeManager_getLength() { + return this._cascadingStack.length; + } + }, + getAt: function _CascadeManager_getAt(index) { + return this._cascadingStack[index]; + }, + handleFocusIntoFlyout: function _CascadeManager_handleFocusIntoFlyout(event) { + // When a flyout in the cascade recieves focus, we close all subflyouts beneath it. + var index = this.indexOfElement(event.target); + if (index >= 0) { + var subFlyout = this.getAt(index + 1); + this.collapseFlyout(subFlyout); + } + }, + // Compute the input type that is associated with the cascading stack on demand. Allows + // each Flyout in the cascade to adjust its sizing based on the current input type + // and to do it in a way that is consistent with the rest of the Flyouts in the cascade. + inputType: { + get: function _CascadeManager_inputType_get() { + if (!this._inputType) { + this._inputType = _KeyboardBehavior._lastInputType; + } + return this._inputType; + } + }, + // Used by tests. + dismissableLayer: { + get: function _CascadeManager_dismissableLayer_get() { + return this._dismissableLayer; + } + }, + _handleKeyDownInCascade: function _CascadeManager_handleKeyDownInCascade(event) { + var rtl = _Global.getComputedStyle(event.target).direction === "rtl", + leftKey = rtl ? Key.rightArrow : Key.leftArrow, + target = event.target; + + if (event.keyCode === leftKey) { + // Left key press in a SubFlyout will close that subFlyout and any subFlyouts cascading from it. + var index = this.indexOfElement(target); + if (index >= 1) { + var subFlyout = this.getAt(index); + this.collapseFlyout(subFlyout); + // Prevent document scrolling + event.preventDefault(); + } + } else if (event.keyCode === Key.alt || event.keyCode === Key.F10) { + this.collapseAll(); + } + } + }); + + var AnimationOffsets = { + top: { top: "50px", left: "0px", keyframe: "WinJS-showFlyoutTop" }, + bottom: { top: "-50px", left: "0px", keyframe: "WinJS-showFlyoutBottom" }, + left: { top: "0px", left: "50px", keyframe: "WinJS-showFlyoutLeft" }, + right: { top: "0px", left: "-50px", keyframe: "WinJS-showFlyoutRight" }, + }; + + var Flyout = _Base.Class.derive(_Overlay._Overlay, function Flyout_ctor(element, options) { + /// + /// + /// Creates a new Flyout control. + /// + /// + /// The DOM element that hosts the control. + /// + /// + /// The set of properties and values to apply to the new Flyout. + /// + /// The new Flyout control. + /// + /// + + // Simplify checking later + options = options || {}; + + // Make sure there's an input element + this._element = element || _Global.document.createElement("div"); + this._id = this._element.id || _ElementUtilities._uniqueID(this._element); + this._writeProfilerMark("constructor,StartTM"); + + this._baseFlyoutConstructor(this._element, options); + + var _elms = this._element.getElementsByTagName("*"); + var firstDiv = this._addFirstDiv(); + firstDiv.tabIndex = _ElementUtilities._getLowestTabIndexInList(_elms); + var finalDiv = this._addFinalDiv(); + finalDiv.tabIndex = _ElementUtilities._getHighestTabIndexInList(_elms); + + // Handle "esc" & "tab" key presses + this._element.addEventListener("keydown", this._handleKeyDown, true); + + this._writeProfilerMark("constructor,StopTM"); + return this; + }, { + _lastMaxHeight: null, + + _baseFlyoutConstructor: function Flyout_baseFlyoutContstructor(element, options) { + // Flyout constructor + + // We have some options with defaults + this._placement = "auto"; + this._alignment = "center"; + + // Call the base overlay constructor helper + this._baseOverlayConstructor(element, options); + + // Start flyouts hidden + this._element.style.visibilty = "hidden"; + this._element.style.display = "none"; + + // Attach our css class + _ElementUtilities.addClass(this._element, _Constants.flyoutClass); + + var that = this; + // Each flyout has an ILightDismissable that is managed through the + // CascasdeManager rather than by the _LightDismissService directly. + this._dismissable = new _LightDismissService.LightDismissableElement({ + element: this._element, + tabIndex: this._element.hasAttribute("tabIndex") ? this._element.tabIndex : -1, + onLightDismiss: function () { + that.hide(); + }, + onTakeFocus: function (useSetActive) { + if (!that._dismissable.restoreFocus()) { + if (!_ElementUtilities.hasClass(that.element, _Constants.menuClass)) { + // Put focus on the first child in the Flyout + that._focusOnFirstFocusableElementOrThis(); + } else { + // Make sure the menu has focus, but don't show a focus rect + _Overlay._Overlay._trySetActive(that._element); + } + } + } + }); + + // Make sure we have an ARIA role + var role = this._element.getAttribute("role"); + if (role === null || role === "" || role === undefined) { + if (_ElementUtilities.hasClass(this._element, _Constants.menuClass)) { + this._element.setAttribute("role", "menu"); + } else { + this._element.setAttribute("role", "dialog"); + } + } + var label = this._element.getAttribute("aria-label"); + if (label === null || label === "" || label === undefined) { + this._element.setAttribute("aria-label", strings.ariaLabel); + } + + // Base animation is popIn, but our flyout has different arguments + this._currentAnimateIn = this._flyoutAnimateIn; + this._currentAnimateOut = this._flyoutAnimateOut; + + _ElementUtilities._addEventListener(this.element, "focusin", this._handleFocusIn.bind(this), false); + }, + + /// + /// Gets or sets the Flyout control's anchor. The anchor element is the HTML element which the Flyout originates from and is positioned relative to. + /// (This setting can be overridden when you call the show method.) + /// + /// + anchor: { + get: function () { + return this._anchor; + }, + set: function (value) { + this._anchor = value; + } + }, + + /// + /// Gets or sets the default placement of this Flyout. (This setting can be overridden when you call the show method.) + /// + /// + placement: { + get: function () { + return this._placement; + }, + set: function (value) { + if (value !== "top" && value !== "bottom" && value !== "left" && value !== "right" && value !== "auto" && value !== "autohorizontal" && value !== "autovertical") { + // Not a legal placement value + throw new _ErrorFromName("WinJS.UI.Flyout.BadPlacement", strings.badPlacement); + } + this._placement = value; + } + }, + + /// + /// Gets or sets the default alignment for this Flyout. (This setting can be overridden when you call the show method.) + /// + /// + alignment: { + get: function () { + return this._alignment; + }, + set: function (value) { + if (value !== "right" && value !== "left" && value !== "center") { + // Not a legal alignment value + throw new _ErrorFromName("WinJS.UI.Flyout.BadAlignment", strings.badAlignment); + } + this._alignment = value; + } + }, + + /// Disable a Flyout, setting or getting the HTML disabled attribute. When disabled the Flyout will no longer display with show(), and will hide if currently visible. + disabled: { + get: function () { + // Ensure it's a boolean because we're using the DOM element to keep in-sync + return !!this._element.disabled; + }, + set: function (value) { + // Force this check into a boolean because our current state could be a bit confused since we tie to the DOM element + value = !!value; + var oldValue = !!this._element.disabled; + if (oldValue !== value) { + this._element.disabled = value; + if (!this.hidden && this._element.disabled) { + this.hide(); + } + } + } + }, + + /// + /// Occurs immediately before the control is shown. + /// + onbeforeshow: createEvent(_Overlay._Overlay.beforeShow), + + /// + /// Occurs immediately after the control is shown. + /// + onaftershow: createEvent(_Overlay._Overlay.afterShow), + + /// + /// Occurs immediately before the control is hidden. + /// + onbeforehide: createEvent(_Overlay._Overlay.beforeHide), + + /// + /// Occurs immediately after the control is hidden. + /// + onafterhide: createEvent(_Overlay._Overlay.afterHide), + + _dispose: function Flyout_dispose() { + _Dispose.disposeSubTree(this.element); + this._hide(); + Flyout._cascadeManager.flyoutHidden(this); + this.anchor = null; + }, + + show: function (anchor, placement, alignment) { + /// + /// + /// Shows the Flyout, if hidden, regardless of other states. + /// + /// + /// The DOM element, or ID of a DOM element to anchor the Flyout, overriding the anchor property for this time only. + /// + /// + /// The placement of the Flyout to the anchor: 'auto' (default), 'top', 'bottom', 'left', or 'right'. This parameter overrides the placement property for this show only. + /// + /// + /// For 'top' or 'bottom' placement, the alignment of the Flyout to the anchor's edge: 'center' (default), 'left', or 'right'. + /// This parameter overrides the alignment property for this show only. + /// + /// + /// + this._writeProfilerMark("show,StartTM"); // The corresponding "stop" profiler mark is handled in _Overlay._baseEndShow(). + this._show(anchor, placement, alignment); + }, + + _show: function Flyout_show(anchor, placement, alignment) { + this._baseFlyoutShow(anchor, placement, alignment); + }, + + hide: function () { + /// + /// + /// Hides the Flyout, if visible, regardless of other states. + /// + /// + /// + // Just wrap the private one, turning off keyboard invoked flag + this._writeProfilerMark("hide,StartTM"); // The corresponding "stop" profiler mark is handled in _Overlay._baseEndHide(). + this._hide(); + }, + + _hide: function Flyout_hide() { + + // First close all subflyout descendants in the cascade. + // Any calls to collapseFlyout through reentrancy should nop. + Flyout._cascadeManager.collapseFlyout(this); + + if (this._baseHide()) { + Flyout._cascadeManager.flyoutHiding(this); + } + }, + + _beforeEndHide: function Flyout_beforeEndHide() { + Flyout._cascadeManager.flyoutHidden(this); + }, + + _baseFlyoutShow: function Flyout_baseFlyoutShow(anchor, placement, alignment) { + if (this.disabled || this._disposed) { + // Don't do anything. + return; + } + + // Pick up defaults + if (!anchor) { + anchor = this._anchor; + } + if (!placement) { + placement = this._placement; + } + if (!alignment) { + alignment = this._alignment; + } + + // Dereference the anchor if necessary + if (typeof anchor === "string") { + anchor = _Global.document.getElementById(anchor); + } else if (anchor && anchor.element) { + anchor = anchor.element; + } + + // We expect an anchor + if (!anchor) { + // If we have _nextLeft, etc., then we were continuing an old animation, so that's OK + if (!this._reuseCurrent) { + throw new _ErrorFromName("WinJS.UI.Flyout.NoAnchor", strings.noAnchor); + } + // Last call was incomplete, so reuse the previous _current values. + this._reuseCurrent = null; + } else { + // Remember the anchor so that if we lose focus we can go back + this._currentAnchor = anchor; + // Remember current values + this._currentPlacement = placement; + this._currentAlignment = alignment; + } + + // If we're animating (eg baseShow is going to fail), or the cascadeManager is in the middle of a updating the cascade, + // then don't mess up our current state. + if (this._element.winAnimating) { + this._reuseCurrent = true; + // Queue us up to wait for the current animation to finish. + // _checkDoNext() is always scheduled after the current animation completes. + this._doNext = "show"; + } else if (Flyout._cascadeManager.reentrancyLock) { + this._reuseCurrent = true; + // Queue us up to wait for the current animation to finish. + // Schedule a call to _checkDoNext() for when the cascadeManager unlocks. + this._doNext = "show"; + var that = this; + Flyout._cascadeManager.unlocked.then(function () { that._checkDoNext(); }); + } else { + // We call our base _baseShow to handle the actual animation + if (this._baseShow()) { + // (_baseShow shouldn't ever fail because we tested winAnimating above). + if (!_ElementUtilities.hasClass(this.element, "win-menu")) { + // Verify that the firstDiv is in the correct location. + // Move it to the correct location or add it if not. + var _elms = this._element.getElementsByTagName("*"); + var firstDiv = this.element.querySelectorAll(".win-first"); + if (this.element.children.length && !_ElementUtilities.hasClass(this.element.children[0], _Constants.firstDivClass)) { + if (firstDiv && firstDiv.length > 0) { + firstDiv.item(0).parentNode.removeChild(firstDiv.item(0)); + } + + firstDiv = this._addFirstDiv(); + } + firstDiv.tabIndex = _ElementUtilities._getLowestTabIndexInList(_elms); + + // Verify that the finalDiv is in the correct location. + // Move it to the correct location or add it if not. + var finalDiv = this.element.querySelectorAll(".win-final"); + if (!_ElementUtilities.hasClass(this.element.children[this.element.children.length - 1], _Constants.finalDivClass)) { + if (finalDiv && finalDiv.length > 0) { + finalDiv.item(0).parentNode.removeChild(finalDiv.item(0)); + } + + finalDiv = this._addFinalDiv(); + } + finalDiv.tabIndex = _ElementUtilities._getHighestTabIndexInList(_elms); + } + + Flyout._cascadeManager.appendFlyout(this); + } + } + }, + + _lightDismiss: function Flyout_lightDismiss() { + Flyout._cascadeManager.collapseAll(); + }, + + // Find our new flyout position. + _findPosition: function Flyout_findPosition() { + this._adjustedHeight = 0; + this._nextTop = 0; + this._nextLeft = 0; + this._keyboardMovedUs = false; + this._doesScroll = false; + + // Make sure menu commands display correctly + if (this._checkMenuCommands) { + this._checkMenuCommands(); + } + + // Remove old height restrictions and scrolling. + this._clearAdjustedStyles(); + + this._setAlignment(this._currentAlignment); + + // Set up the new position, and prep the offset for showPopup. + this._getTopLeft(); + + // Adjust position + if (this._nextTop < 0) { + // Overran bottom, attach to bottom. + this._element.style.bottom = _Overlay._Overlay._keyboardInfo._visibleDocBottomOffset + "px"; + this._element.style.top = "auto"; + } else { + // Normal, set top + this._element.style.top = this._nextTop + "px"; + this._element.style.bottom = "auto"; + } + if (this._nextLeft < 0) { + // Overran right, attach to right + this._element.style.right = "0px"; + this._element.style.left = "auto"; + } else { + // Normal, set left + this._element.style.left = this._nextLeft + "px"; + this._element.style.right = "auto"; + } + + // Adjust height/scrollbar + if (this._doesScroll) { + _ElementUtilities.addClass(this._element, _Constants.scrollsClass); + this._lastMaxHeight = this._element.style.maxHeight; + this._element.style.maxHeight = this._adjustedHeight + "px"; + } + + // May need to adjust if the IHM is showing. + if (_Overlay._Overlay._keyboardInfo._visible) { + // Use keyboard logic + this._checkKeyboardFit(); + + if (this._keyboardMovedUs) { + this._adjustForKeyboard(); + } + } + }, + + // This determines our positioning. We have 8 modes, the 1st four are explicit, the last 4 are automatic: + // * top - position explicitly on the top of the anchor, shrinking and adding scrollbar as needed. + // * bottom - position explicitly below the anchor, shrinking and adding scrollbar as needed. + // * left - position left of the anchor, shrinking and adding a vertical scrollbar as needed. + // * right - position right of the anchor, shrinking and adding a vertical scroolbar as needed. + // * auto - Automatic placement. + // * autohorizontal - Automatic placement (only left or right). + // * autovertical - Automatic placement (only top or bottom). + // * _cascasde - Private placement used by MenuCommand._activateFlyoutCommand + // Auto tests the height of the anchor and the flyout. For consistency in orientation, we imagine + // that the anchor is placed in the vertical center of the display. If the flyout would fit above + // that centered anchor, then we will place the flyout vertically in relation to the anchor, otherwise + // placement will be horizontal. + // Vertical auto or autovertical placement will be positioned on top of the anchor if room, otherwise below the anchor. + // - this is because touch users would be more likely to obscure flyouts below the anchor. + // Horizontal auto or autohorizontal placement will be positioned to the left of the anchor if room, otherwise to the right. + // - this is because right handed users would be more likely to obscure a flyout on the right of the anchor. + // All three auto placements will add a vertical scrollbar if necessary. + // + _getTopLeft: function Flyout_getTopLeft() { + + var that = this; + + function configureVerticalWithScroll(anchor) { + // Won't fit top or bottom. Pick the one with the most space and add a scrollbar. + if (topHasMoreRoom(anchor)) { + // Top + that._adjustedHeight = spaceAbove(anchor) - that._verticalMarginBorderPadding; + that._nextTop = _Overlay._Overlay._keyboardInfo._visibleDocTop; + that._nextAnimOffset = AnimationOffsets.top; + } else { + // Bottom + that._adjustedHeight = spaceBelow(anchor) - that._verticalMarginBorderPadding; + that._nextTop = _Constants.pinToBottomEdge; + that._nextAnimOffset = AnimationOffsets.bottom; + } + that._doesScroll = true; + } + + // If the anchor is centered vertically, would the flyout fit above it? + function fitsVerticallyWithCenteredAnchor(anchor, flyout) { + // Returns true if the flyout would always fit at least top + // or bottom of its anchor, regardless of the position of the anchor, + // as long as the anchor never changed its height, nor did the height of + // the visualViewport change. + return ((_Overlay._Overlay._keyboardInfo._visibleDocHeight - anchor.height) / 2) >= flyout.totalHeight; + } + + function spaceAbove(anchor) { + return anchor.top - _Overlay._Overlay._keyboardInfo._visibleDocTop; + } + + function spaceBelow(anchor) { + return _Overlay._Overlay._keyboardInfo._visibleDocBottom - anchor.bottom; + } + + function topHasMoreRoom(anchor) { + return spaceAbove(anchor) > spaceBelow(anchor); + } + + // See if we can fit in various places, fitting in the main view, + // ignoring viewport changes, like for the IHM. + function fitTop(bottomConstraint, flyout) { + that._nextTop = bottomConstraint - flyout.totalHeight; + that._nextAnimOffset = AnimationOffsets.top; + return (that._nextTop >= _Overlay._Overlay._keyboardInfo._visibleDocTop && + that._nextTop + flyout.totalHeight <= _Overlay._Overlay._keyboardInfo._visibleDocBottom); + } + + function fitBottom(topConstraint, flyout) { + that._nextTop = topConstraint; + that._nextAnimOffset = AnimationOffsets.bottom; + return (that._nextTop >= _Overlay._Overlay._keyboardInfo._visibleDocTop && + that._nextTop + flyout.totalHeight <= _Overlay._Overlay._keyboardInfo._visibleDocBottom); + } + + function fitLeft(leftConstraint, flyout) { + that._nextLeft = leftConstraint - flyout.totalWidth; + that._nextAnimOffset = AnimationOffsets.left; + return (that._nextLeft >= 0 && that._nextLeft + flyout.totalWidth <= _Overlay._Overlay._keyboardInfo._visualViewportWidth); + } + + function fitRight(rightConstraint, flyout) { + that._nextLeft = rightConstraint; + that._nextAnimOffset = AnimationOffsets.right; + return (that._nextLeft >= 0 && that._nextLeft + flyout.totalWidth <= _Overlay._Overlay._keyboardInfo._visualViewportWidth); + } + + function centerVertically(anchor, flyout) { + that._nextTop = anchor.top + anchor.height / 2 - flyout.totalHeight / 2; + if (that._nextTop < _Overlay._Overlay._keyboardInfo._visibleDocTop) { + that._nextTop = _Overlay._Overlay._keyboardInfo._visibleDocTop; + } else if (that._nextTop + flyout.totalHeight >= _Overlay._Overlay._keyboardInfo._visibleDocBottom) { + // Flag to pin to bottom edge of visual document. + that._nextTop = _Constants.pinToBottomEdge; + } + } + + function alignHorizontally(anchor, flyout, alignment) { + if (alignment === "center") { + that._nextLeft = anchor.left + anchor.width / 2 - flyout.totalWidth / 2; + } else if (alignment === "left") { + that._nextLeft = anchor.left; + } else if (alignment === "right") { + that._nextLeft = anchor.right - flyout.totalWidth; + } else { + throw new _ErrorFromName("WinJS.UI.Flyout.BadAlignment", strings.badAlignment); + } + if (that._nextLeft < 0) { + that._nextLeft = 0; + } else if (that._nextLeft + flyout.totalWidth >= _Overlay._Overlay._keyboardInfo._visualViewportWidth) { + // Flag to pin to right edge of visible document. + that._nextLeft = _Constants.pinToRightEdge; + } + } + + var anchorRawRectangle, + flyout = {}, + anchor = {}; + + try { + anchorRawRectangle = this._currentAnchor.getBoundingClientRect(); + } + catch (e) { + throw new _ErrorFromName("WinJS.UI.Flyout.NoAnchor", strings.noAnchor); + } + + // Adjust for the anchor's margins. + anchor.top = anchorRawRectangle.top; + anchor.bottom = anchorRawRectangle.bottom; + anchor.left = anchorRawRectangle.left; + anchor.right = anchorRawRectangle.right; + anchor.height = anchor.bottom - anchor.top; + anchor.width = anchor.right - anchor.left; + + // Get our flyout and margins, note that getDimension calls + // window.getComputedStyle, which ensures layout is updated. + flyout.marginTop = getDimension(this._element, "marginTop"); + flyout.marginBottom = getDimension(this._element, "marginBottom"); + flyout.marginLeft = getDimension(this._element, "marginLeft"); + flyout.marginRight = getDimension(this._element, "marginRight"); + flyout.totalWidth = _ElementUtilities.getTotalWidth(this._element); + flyout.totalHeight = _ElementUtilities.getTotalHeight(this._element); + flyout.contentWidth = _ElementUtilities.getContentWidth(this._element); + flyout.contentHeight = _ElementUtilities.getContentHeight(this._element); + this._verticalMarginBorderPadding = (flyout.totalHeight - flyout.contentHeight); + this._adjustedHeight = flyout.contentHeight; + + // Check fit for requested this._currentPlacement, doing fallback if necessary + switch (this._currentPlacement) { + case "top": + if (!fitTop(anchor.top, flyout)) { + // Didn't fit, needs scrollbar + this._nextTop = _Overlay._Overlay._keyboardInfo._visibleDocTop; + this._doesScroll = true; + this._adjustedHeight = spaceAbove(anchor) - this._verticalMarginBorderPadding; + } + alignHorizontally(anchor, flyout, this._currentAlignment); + break; + case "bottom": + if (!fitBottom(anchor.bottom, flyout)) { + // Didn't fit, needs scrollbar + this._nextTop = _Constants.pinToBottomEdge; + this._doesScroll = true; + this._adjustedHeight = spaceBelow(anchor) - this._verticalMarginBorderPadding; + } + alignHorizontally(anchor, flyout, this._currentAlignment); + break; + case "left": + if (!fitLeft(anchor.left, flyout)) { + // Didn't fit, just shove it to edge + this._nextLeft = 0; + } + centerVertically(anchor, flyout); + break; + case "right": + if (!fitRight(anchor.right, flyout)) { + // Didn't fit, just shove it to edge + this._nextLeft = _Constants.pinToRightEdge; + } + centerVertically(anchor, flyout); + break; + case "autovertical": + if (!fitTop(anchor.top, flyout)) { + // Didn't fit above (preferred), so go below. + if (!fitBottom(anchor.bottom, flyout)) { + // Didn't fit, needs scrollbar + configureVerticalWithScroll(anchor); + } + } + alignHorizontally(anchor, flyout, this._currentAlignment); + break; + case "autohorizontal": + if (!fitLeft(anchor.left, flyout)) { + // Didn't fit left (preferred), so go right. + if (!fitRight(anchor.right, flyout)) { + // Didn't fit,just shove it to edge + this._nextLeft = _Constants.pinToRightEdge; + } + } + centerVertically(anchor, flyout); + break; + case "auto": + // Auto, if the anchor was in the vertical center of the display would we fit above it? + if (fitsVerticallyWithCenteredAnchor(anchor, flyout)) { + // It will fit above or below the anchor + if (!fitTop(anchor.top, flyout)) { + // Didn't fit above (preferred), so go below. + fitBottom(anchor.bottom, flyout); + } + alignHorizontally(anchor, flyout, this._currentAlignment); + } else { + // Won't fit above or below, try a side + if (!fitLeft(anchor.left, flyout) && + !fitRight(anchor.right, flyout)) { + // Didn't fit left or right either + configureVerticalWithScroll(anchor); + alignHorizontally(anchor, flyout, this._currentAlignment); + } else { + centerVertically(anchor, flyout); + } + } + break; + case "_cascade": + // Align vertically + // PREFERRED: When there is enough room to align a subMenu to either the top or the bottom of its + // anchor element, the subMenu prefers to be top aligned. + // FALLBACK: When there is enough room to bottom align a subMenu but not enough room to top align it, + // then the subMenu will align to the bottom of its anchor element. + // LASTRESORT: When there is not enough room to top align or bottom align the subMenu to its anchor, + // then the subMenu will be center aligned to it's anchor's vertical midpoint. + if (!fitBottom(anchor.top - flyout.marginTop, flyout) && !fitTop(anchor.bottom + flyout.marginBottom, flyout)) { + centerVertically(anchor, flyout); + } + // Determine horizontal direction + // PREFERRED: When there is enough room to fit a subMenu on either side of the anchor, + // the subMenu prefers to go on the right hand side. + // FALLBACK: When there is only enough room to fit a subMenu on the left side of the anchor, + // the subMenu is placed to the left of the parent menu. + // LASTRESORT: When there is not enough room to fit a subMenu on either side of the anchor, + // the subMenu is pinned to the right edge of the window. + var rtl = _Global.getComputedStyle(this._element).direction === "rtl"; + + // Cascading Menus should overlap their ancestor menu by 4 pixels and we have a unit test to + // verify that behavior. Because we don't have access to the ancestor flyout we need to specify + // the overlap in terms of our anchor element. There is a 1px border around the menu that + // contains our anchor we need to overlap our anchor by 3px to ensure that we overlap the containing + // Menu by 4px. + var pixelsToOverlapAnchor = 3; + + var beginRight = anchor.right - flyout.marginLeft - pixelsToOverlapAnchor; + var beginLeft = anchor.left + flyout.marginRight + pixelsToOverlapAnchor; + + if (rtl) { + if (!fitLeft(beginLeft, flyout) && !fitRight(beginRight, flyout)) { + // Doesn't fit on either side, pin to the left edge. + that._nextLeft = 0; + that._nextAnimOffset = AnimationOffsets.left; + } + } else { + if (!fitRight(beginRight, flyout) && !fitLeft(beginLeft, flyout)) { + // Doesn't fit on either side, pin to the right edge of the visible document. + that._nextLeft = _Constants.pinToRightEdge; + that._nextAnimOffset = AnimationOffsets.right; + } + } + + break; + default: + // Not a legal this._currentPlacement value + throw new _ErrorFromName("WinJS.UI.Flyout.BadPlacement", strings.badPlacement); + } + }, + + _clearAdjustedStyles: function Flyout_clearAdjustedStyles() { + // Move to 0,0 in case it is off screen, so that it lays out at a reasonable size + this._element.style.top = "0px"; + this._element.style.bottom = "auto"; + this._element.style.left = "0px"; + this._element.style.right = "auto"; + + // Clear height restrictons and scrollbar class + _ElementUtilities.removeClass(this._element, _Constants.scrollsClass); + if (this._lastMaxHeight !== null) { + this._element.style.maxHeight = this._lastMaxHeight; + this._lastMaxHeight = null; + } + + // Clear Alignment + _ElementUtilities.removeClass(this._element, "win-rightalign"); + _ElementUtilities.removeClass(this._element, "win-leftalign"); + }, + + _setAlignment: function Flyout_setAlignment(alignment) { + // Alignment + switch (alignment) { + case "left": + _ElementUtilities.addClass(this._element, "win-leftalign"); + break; + case "right": + _ElementUtilities.addClass(this._element, "win-rightalign"); + break; + case "center": + case "none": + break; + } + }, + + _showingKeyboard: function Flyout_showingKeyboard(event) { + if (this.hidden) { + return; + } + + // The only way that we can be showing a keyboard when a flyout is up is because the input was + // in the flyout itself, in which case we'll be moving ourselves. There is no practical way + // for the application to override this as the focused element is in our flyout. + event.ensuredFocusedElementInView = true; + + // See if the keyboard is going to force us to move + this._checkKeyboardFit(); + + if (this._keyboardMovedUs) { + // Pop out immediately, then move to new spot + this._element.style.opacity = 0; + var that = this; + _Global.setTimeout(function () { that._adjustForKeyboard(); that._baseAnimateIn(); }, _Overlay._Overlay._keyboardInfo._animationShowLength); + } + }, + + _resize: function Flyout_resize() { + // If hidden and not busy animating, then nothing to do + if (!this.hidden || this._animating) { + + // This should only happen if the IHM is dismissing, + // the only other way is for viewstate changes, which + // would dismiss any flyout. + if (this._needToHandleHidingKeyboard) { + // Hiding keyboard, update our position, giving the anchor a chance to update first. + var that = this; + _BaseUtils._setImmediate(function () { + if (!that.hidden || that._animating) { + that._findPosition(); + } + }); + this._needToHandleHidingKeyboard = false; + } + } + }, + + // If you were not pinned to the bottom, you might have to be now. + _checkKeyboardFit: function Flyout_checkKeyboardFit() { + // Special Flyout positioning rules to determine if the Flyout needs to adjust its + // position because of the IHM. If the Flyout needs to adjust for the IHM, it will reposition + // itself to be pinned to either the top or bottom edge of the visual viewport. + // - Too Tall, above top, or below bottom. + + var keyboardMovedUs = false; + var viewportHeight = _Overlay._Overlay._keyboardInfo._visibleDocHeight; + var adjustedMarginBoxHeight = this._adjustedHeight + this._verticalMarginBorderPadding; + if (adjustedMarginBoxHeight > viewportHeight) { + // The Flyout is now too tall to fit in the viewport, pin to top and adjust height. + keyboardMovedUs = true; + this._nextTop = _Constants.pinToBottomEdge; + this._adjustedHeight = viewportHeight - this._verticalMarginBorderPadding; + this._doesScroll = true; + } else if (this._nextTop >= 0 && + this._nextTop + adjustedMarginBoxHeight > _Overlay._Overlay._keyboardInfo._visibleDocBottom) { + // Flyout clips the bottom of the viewport. Pin to bottom. + this._nextTop = _Constants.pinToBottomEdge; + keyboardMovedUs = true; + } else if (this._nextTop === _Constants.pinToBottomEdge) { + // We were already pinned to the bottom, so our position on screen will change + keyboardMovedUs = true; + } + + // Signals use of basic fadein animation + this._keyboardMovedUs = keyboardMovedUs; + }, + + _adjustForKeyboard: function Flyout_adjustForKeyboard() { + // Keyboard moved us, update our metrics as needed + if (this._doesScroll) { + // Add scrollbar if we didn't already have scrollsClass + if (!this._lastMaxHeight) { + _ElementUtilities.addClass(this._element, _Constants.scrollsClass); + this._lastMaxHeight = this._element.style.maxHeight; + } + // Adjust height + this._element.style.maxHeight = this._adjustedHeight + "px"; + } + + // Update top/bottom + this._checkScrollPosition(true); + }, + + _hidingKeyboard: function Flyout_hidingKeyboard() { + // If we aren't visible and not animating, or haven't been repositioned, then nothing to do + // We don't know if the keyboard moved the anchor, so _keyboardMovedUs doesn't help here + if (!this.hidden || this._animating) { + + // Snap to the final position + // We'll either just reveal the current space or resize the window + if (_Overlay._Overlay._keyboardInfo._isResized) { + // Flag resize that we'll need an updated position + this._needToHandleHidingKeyboard = true; + } else { + // Not resized, update our final position, giving the anchor a chance to update first. + var that = this; + _BaseUtils._setImmediate(function () { + if (!that.hidden || that._animating) { + that._findPosition(); + } + }); + } + } + }, + + _checkScrollPosition: function Flyout_checkScrollPosition(showing) { + if (this.hidden && !showing) { + return; + } + + // May need to adjust top by viewport offset + if (this._nextTop < 0) { + // Need to attach to bottom + this._element.style.bottom = _Overlay._Overlay._keyboardInfo._visibleDocBottomOffset + "px"; + this._element.style.top = "auto"; + } else { + // Normal, attach to top + this._element.style.top = this._nextTop + "px"; + this._element.style.bottom = "auto"; + } + }, + + // AppBar flyout animations + _flyoutAnimateIn: function Flyout_flyoutAnimateIn() { + if (this._keyboardMovedUs) { + return this._baseAnimateIn(); + } else { + this._element.style.opacity = 1; + this._element.style.visibility = "visible"; + return Animations.showPopup(this._element, this._nextAnimOffset); + } + }, + + _flyoutAnimateOut: function Flyout_flyoutAnimateOut() { + if (this._keyboardMovedUs) { + return this._baseAnimateOut(); + } else { + this._element.style.opacity = 0; + return Animations.hidePopup(this._element, this._nextAnimOffset); + } + }, + + // Hide all other flyouts besides this one + _hideAllOtherFlyouts: function Flyout_hideAllOtherFlyouts(thisFlyout) { + var flyouts = _Global.document.querySelectorAll("." + _Constants.flyoutClass); + for (var i = 0; i < flyouts.length; i++) { + var flyoutControl = flyouts[i].winControl; + if (flyoutControl && !flyoutControl.hidden && (flyoutControl !== thisFlyout)) { + flyoutControl.hide(); + } + } + }, + + _handleKeyDown: function Flyout_handleKeyDown(event) { + if ((event.keyCode === Key.space || event.keyCode === Key.enter) + && (this === _Global.document.activeElement)) { + event.preventDefault(); + event.stopPropagation(); + this.winControl.hide(); + } else if (event.shiftKey && event.keyCode === Key.tab + && this === _Global.document.activeElement + && !event.altKey && !event.ctrlKey && !event.metaKey) { + event.preventDefault(); + event.stopPropagation(); + this.winControl._focusOnLastFocusableElementOrThis(); + } + }, + + _handleFocusIn: function Flyout_handleFocusIn(event) { + if (!this.element.contains(event.relatedTarget)) { + Flyout._cascadeManager.handleFocusIntoFlyout(event); + } + // Else focus is only moving between elements in the flyout. + // Doesn't need to be handled by cascadeManager. + }, + + // Create and add a new first div as the first child + _addFirstDiv: function Flyout_addFirstDiv() { + var firstDiv = _Global.document.createElement("div"); + firstDiv.className = _Constants.firstDivClass; + firstDiv.style.display = "inline"; + firstDiv.setAttribute("role", "menuitem"); + firstDiv.setAttribute("aria-hidden", "true"); + + // add to beginning + if (this._element.children[0]) { + this._element.insertBefore(firstDiv, this._element.children[0]); + } else { + this._element.appendChild(firstDiv); + } + + var that = this; + _ElementUtilities._addEventListener(firstDiv, "focusin", function () { that._focusOnLastFocusableElementOrThis(); }, false); + + return firstDiv; + }, + + // Create and add a new final div as the last child + _addFinalDiv: function Flyout_addFinalDiv() { + var finalDiv = _Global.document.createElement("div"); + finalDiv.className = _Constants.finalDivClass; + finalDiv.style.display = "inline"; + finalDiv.setAttribute("role", "menuitem"); + finalDiv.setAttribute("aria-hidden", "true"); + + this._element.appendChild(finalDiv); + var that = this; + _ElementUtilities._addEventListener(finalDiv, "focusin", function () { that._focusOnFirstFocusableElementOrThis(); }, false); + + return finalDiv; + }, + + _writeProfilerMark: function Flyout_writeProfilerMark(text) { + _WriteProfilerMark("WinJS.UI.Flyout:" + this._id + ":" + text); + } + }, + { + _cascadeManager: new _CascadeManager(), + }); + return Flyout; + }) + }); + +}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('WinJS/Controls/CommandingSurface/_Constants',["require", "exports"], function (require, exports) { + // CommandingSurface class names + exports.ClassNames = { + controlCssClass: "win-commandingsurface", + disposableCssClass: "win-disposable", + actionAreaCssClass: "win-commandingsurface-actionarea", + actionAreaContainerCssClass: "win-commandingsurface-actionareacontainer", + overflowButtonCssClass: "win-commandingsurface-overflowbutton", + spacerCssClass: "win-commandingsurface-spacer", + ellipsisCssClass: "win-commandingsurface-ellipsis", + overflowAreaCssClass: "win-commandingsurface-overflowarea", + overflowAreaContainerCssClass: "win-commandingsurface-overflowareacontainer", + contentFlyoutCssClass: "win-commandingsurface-contentflyout", + emptyCommandingSurfaceCssClass: "win-commandingsurface-empty", + menuCssClass: "win-menu", + menuContainsToggleCommandClass: "win-menu-containstogglecommand", + openedClass: "win-commandingsurface-opened", + closingClass: "win-commandingsurface-closing", + closedClass: "win-commandingsurface-closed", + noneClass: "win-commandingsurface-closeddisplaynone", + minimalClass: "win-commandingsurface-closeddisplayminimal", + compactClass: "win-commandingsurface-closeddisplaycompact", + fullClass: "win-commandingsurface-closeddisplayfull", + overflowTopClass: "win-commandingsurface-overflowtop", + overflowBottomClass: "win-commandingsurface-overflowbottom", + }; + exports.EventNames = { + beforeOpen: "beforeopen", + afterOpen: "afteropen", + beforeClose: "beforeclose", + afterClose: "afterclose", + commandPropertyMutated: "_commandpropertymutated", + }; + exports.actionAreaCommandWidth = 68; + exports.actionAreaSeparatorWidth = 34; + exports.actionAreaOverflowButtonWidth = 32; + exports.overflowCommandHeight = 44; + exports.overflowSeparatorHeight = 12; + exports.controlMinWidth = exports.actionAreaOverflowButtonWidth; + exports.overflowAreaMaxWidth = 480; + exports.heightOfMinimal = 24; + exports.heightOfCompact = 48; + exports.contentMenuCommandDefaultLabel = "Custom content"; + exports.defaultClosedDisplayMode = "compact"; + exports.defaultOpened = false; + exports.defaultOverflowDirection = "bottom"; + // Constants for commands + exports.typeSeparator = "separator"; + exports.typeContent = "content"; + exports.typeButton = "button"; + exports.typeToggle = "toggle"; + exports.typeFlyout = "flyout"; + exports.commandSelector = ".win-command"; + exports.primaryCommandSection = "primary"; + exports.secondaryCommandSection = "secondary"; +}); + +define('WinJS/Controls/ToolBar/_Constants',["require", "exports", "../CommandingSurface/_Constants"], function (require, exports, _CommandingSurfaceConstants) { + // toolbar class names + exports.ClassNames = { + controlCssClass: "win-toolbar", + disposableCssClass: "win-disposable", + actionAreaCssClass: "win-toolbar-actionarea", + overflowButtonCssClass: "win-toolbar-overflowbutton", + spacerCssClass: "win-toolbar-spacer", + ellipsisCssClass: "win-toolbar-ellipsis", + overflowAreaCssClass: "win-toolbar-overflowarea", + contentFlyoutCssClass: "win-toolbar-contentflyout", + emptytoolbarCssClass: "win-toolbar-empty", + menuCssClass: "win-menu", + menuContainsToggleCommandClass: "win-menu-containstogglecommand", + openedClass: "win-toolbar-opened", + closedClass: "win-toolbar-closed", + compactClass: "win-toolbar-closeddisplaycompact", + fullClass: "win-toolbar-closeddisplayfull", + overflowTopClass: "win-toolbar-overflowtop", + overflowBottomClass: "win-toolbar-overflowbottom", + placeHolderCssClass: "win-toolbar-placeholder", + }; + exports.EventNames = { + beforeOpen: "beforeopen", + afterOpen: "afteropen", + beforeClose: "beforeclose", + afterClose: "afterclose" + }; + exports.OverflowDirection = { + top: "top", + bottom: "bottom", + }; + exports.overflowAreaMaxWidth = _CommandingSurfaceConstants.overflowAreaMaxWidth; + exports.controlMinWidth = _CommandingSurfaceConstants.controlMinWidth; + exports.defaultClosedDisplayMode = "compact"; + exports.defaultOpened = false; + // Constants for commands + exports.typeSeparator = "separator"; + exports.typeContent = "content"; + exports.typeButton = "button"; + exports.typeToggle = "toggle"; + exports.typeFlyout = "flyout"; + exports.commandSelector = ".win-command"; + exports.primaryCommandSection = "primary"; + exports.secondaryCommandSection = "secondary"; +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +// Glyph Enumeration +/// Segoe +define('WinJS/Controls/AppBar/_Icon',[ + 'exports', + '../../Core/_Base', + '../../Core/_Resources' + ], function appBarIconInit(exports, _Base, _Resources) { + "use strict"; + + var glyphs = ["previous", + "next", + "play", + "pause", + "edit", + "save", + "clear", + "delete", + "remove", + "add", + "cancel", + "accept", + "more", + "redo", + "undo", + "home", + "up", + "forward", + "right", + "back", + "left", + "favorite", + "camera", + "settings", + "video", + "sync", + "download", + "mail", + "find", + "help", + "upload", + "emoji", + "twopage", + "leavechat", + "mailforward", + "clock", + "send", + "crop", + "rotatecamera", + "people", + "closepane", + "openpane", + "world", + "flag", + "previewlink", + "globe", + "trim", + "attachcamera", + "zoomin", + "bookmarks", + "document", + "protecteddocument", + "page", + "bullets", + "comment", + "mail2", + "contactinfo", + "hangup", + "viewall", + "mappin", + "phone", + "videochat", + "switch", + "contact", + "rename", + "pin", + "musicinfo", + "go", + "keyboard", + "dockleft", + "dockright", + "dockbottom", + "remote", + "refresh", + "rotate", + "shuffle", + "list", + "shop", + "selectall", + "orientation", + "import", + "importall", + "browsephotos", + "webcam", + "pictures", + "savelocal", + "caption", + "stop", + "showresults", + "volume", + "repair", + "message", + "page2", + "calendarday", + "calendarweek", + "calendar", + "characters", + "mailreplyall", + "read", + "link", + "accounts", + "showbcc", + "hidebcc", + "cut", + "attach", + "paste", + "filter", + "copy", + "emoji2", + "important", + "mailreply", + "slideshow", + "sort", + "manage", + "allapps", + "disconnectdrive", + "mapdrive", + "newwindow", + "openwith", + "contactpresence", + "priority", + "uploadskydrive", + "gototoday", + "font", + "fontcolor", + "contact2", + "folder", + "audio", + "placeholder", + "view", + "setlockscreen", + "settile", + "cc", + "stopslideshow", + "permissions", + "highlight", + "disableupdates", + "unfavorite", + "unpin", + "openlocal", + "mute", + "italic", + "underline", + "bold", + "movetofolder", + "likedislike", + "dislike", + "like", + "alignright", + "aligncenter", + "alignleft", + "zoom", + "zoomout", + "openfile", + "otheruser", + "admin", + "street", + "map", + "clearselection", + "fontdecrease", + "fontincrease", + "fontsize", + "cellphone", + "reshare", + "tag", + "repeatone", + "repeatall", + "outlinestar", + "solidstar", + "calculator", + "directions", + "target", + "library", + "phonebook", + "memo", + "microphone", + "postupdate", + "backtowindow", + "fullscreen", + "newfolder", + "calendarreply", + "unsyncfolder", + "reporthacked", + "syncfolder", + "blockcontact", + "switchapps", + "addfriend", + "touchpointer", + "gotostart", + "zerobars", + "onebar", + "twobars", + "threebars", + "fourbars", + "scan", + "preview", + "hamburger"]; + + // Provide properties to grab resources for each of the icons + /// + /// The AppBarIcon enumeration provides a set of glyphs for use with the AppBarCommand icon property. + /// + var icons = glyphs.reduce(function (fixedIcons, item) { + fixedIcons[item] = { get: function () { return _Resources._getWinJSString("ui/appBarIcons/" + item).value; } }; + return fixedIcons; + }, {}); + + _Base.Namespace._moduleDefine(exports, "WinJS.UI.AppBarIcon", icons); +}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +// AppBarCommand +/// appbar,appbars,Flyout,Flyouts,onclick,Statics +define('WinJS/Controls/AppBar/_Command',[ + 'exports', + '../../Core/_Global', + '../../Core/_WinRT', + '../../Core/_Base', + "../../Core/_BaseUtils", + '../../Core/_ErrorFromName', + "../../Core/_Events", + '../../Core/_Resources', + '../../Utilities/_Control', + '../../Utilities/_Dispose', + '../../Utilities/_ElementUtilities', + '../Flyout/_Overlay', + '../Tooltip', + '../_LegacyAppBar/_Constants', + './_Icon' +], function appBarCommandInit(exports, _Global, _WinRT, _Base, _BaseUtils, _ErrorFromName, _Events, _Resources, _Control, _Dispose, _ElementUtilities, _Overlay, Tooltip, _Constants, _Icon) { + "use strict"; + + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + /// + /// + /// Represents a command to display in an AppBar. + /// + /// + /// + /// + /// ]]> + /// Raised after the hidden property has been programmatically changed. + /// The AppBarCommand control itself. + /// The AppBarCommand's icon box. + /// The AppBarCommand's icon's image formatting. + /// The AppBarCommand's label + /// + /// + AppBarCommand: _Base.Namespace._lazy(function () { + + function _handleClick(event) { + /*jshint validthis: true */ + var command = this.winControl; + if (command) { + if (command._type === _Constants.typeToggle) { + command.selected = !command.selected; + } else if (command._type === _Constants.typeFlyout && command._flyout) { + var flyout = command._flyout; + // Flyout may not have processAll'd, so this may be a DOM object + if (typeof flyout === "string") { + flyout = _Global.document.getElementById(flyout); + } + if (!flyout.show) { + flyout = flyout.winControl; + } + if (flyout && flyout.show) { + flyout.show(this, "autovertical"); + } + } + if (command.onclick) { + command.onclick(event); + } + } + } + + // Used by AppBarCommands to notify listeners that a property has changed. + var PropertyMutations = _Base.Class.define(function PropertyMutations_ctor() { + this._observer = _BaseUtils._merge({}, _Events.eventMixin); + }, { + bind: function (callback) { + this._observer.addEventListener(_Constants.commandPropertyMutated, callback); + }, + unbind: function (callback) { + this._observer.removeEventListener(_Constants.commandPropertyMutated, callback); + }, + dispatchEvent: function (type, detail) { + this._observer.dispatchEvent(type, detail); + }, + }); + + var strings = { + get ariaLabel() { return _Resources._getWinJSString("ui/appBarCommandAriaLabel").value; }, + get duplicateConstruction() { return "Invalid argument: Controls may only be instantiated one time for each DOM element"; }, + get badClick() { return "Invalid argument: The onclick property for an {0} must be a function"; }, + get badDivElement() { return "Invalid argument: For a content command, the element must be null or a div element"; }, + get badHrElement() { return "Invalid argument: For a separator, the element must be null or an hr element"; }, + get badButtonElement() { return "Invalid argument: For a button, toggle, or flyout command, the element must be null or a button element"; }, + get badPriority() { return "Invalid argument: the priority of an {0} must be a non-negative integer"; } + }; + + var AppBarCommand = _Base.Class.define(function AppBarCommand_ctor(element, options) { + /// + /// + /// Creates a new AppBarCommand control. + /// + /// + /// The DOM element that will host the control. AppBarCommand will create one if null. + /// + /// + /// The set of properties and values to apply to the new AppBarCommand. + /// + /// + /// The new AppBarCommand control. + /// + /// + + // Check to make sure we weren't duplicated + if (element && element.winControl) { + throw new _ErrorFromName("WinJS.UI.AppBarCommand.DuplicateConstruction", strings.duplicateConstruction); + } + + this._disposed = false; + + // Don't blow up if they didn't pass options + if (!options) { + options = {}; + } + + // Need a type before we can create our element + if (!options.type) { + this._type = _Constants.typeButton; + } + + options.section = options.section || _Constants.sectionPrimary; + + // Go ahead and create it, separator and content types look different than buttons + // Don't forget to use passed in element if one was provided. + this._element = element; + + if (options.type === _Constants.typeContent) { + this._createContent(); + } else if (options.type === _Constants.typeSeparator) { + this._createSeparator(); + } else { + // This will also set the icon & label + this._createButton(); + } + _ElementUtilities.addClass(this._element, "win-disposable"); + + // Remember ourselves + this._element.winControl = this; + + // Attach our css class + _ElementUtilities.addClass(this._element, _Constants.appBarCommandClass); + + if (options.onclick) { + this.onclick = options.onclick; + } + // We want to handle some clicks + options.onclick = _handleClick; + + _Control.setOptions(this, options); + + if (this._type === _Constants.typeToggle && !options.selected) { + this.selected = false; + } + + // Set up pointerdown handler and clean up ARIA if needed + if (this._type !== _Constants.typeSeparator) { + + // Make sure we have an ARIA role + var role = this._element.getAttribute("role"); + if (role === null || role === "" || role === undefined) { + if (this._type === _Constants.typeToggle) { + role = "menuitemcheckbox"; + } else if (this._type === _Constants.typeContent) { + role = "group"; + } else { + role = "menuitem"; + } + this._element.setAttribute("role", role); + if (this._type === _Constants.typeFlyout) { + this._element.setAttribute("aria-haspopup", true); + } + } + // Label should've been set by label, but if it was missed for some reason: + var label = this._element.getAttribute("aria-label"); + if (label === null || label === "" || label === undefined) { + this._element.setAttribute("aria-label", strings.ariaLabel); + } + } + + this._propertyMutations = new PropertyMutations(); + var that = this; + ObservablePropertyWhiteList.forEach(function (propertyName) { + makeObservable(that, propertyName); + }); + }, { + /// + /// Gets or sets the ID of the AppBarCommand. + /// + id: { + get: function () { + return this._element.id; + }, + + set: function (value) { + // we allow setting first time only. otherwise we ignore it. + if (value && !this._element.id) { + this._element.id = value; + } + } + }, + + /// + /// Gets or sets the type of the AppBarCommand. Possible values are "button", "toggle", "flyout", "content" or "separator". + /// + type: { + get: function () { + return this._type; + }, + set: function (value) { + // we allow setting first time only. otherwise we ignore it. + if (!this._type) { + if (value !== _Constants.typeContent && value !== _Constants.typeFlyout && value !== _Constants.typeToggle && value !== _Constants.typeSeparator) { + this._type = _Constants.typeButton; + } else { + this._type = value; + } + } + } + }, + + /// + /// Gets or sets the label of the AppBarCommand. + /// + label: { + get: function () { + return this._label; + }, + set: function (value) { + this._label = value; + if (this._labelSpan) { + this._labelSpan.textContent = this.label; + } + + // Ensure that we have a tooltip, by updating already-constructed tooltips. Separators won't have these: + if (!this.tooltip && this._tooltipControl) { + this._tooltip = this.label; + this._tooltipControl.innerHTML = this.label; + } + + // Update aria-label + this._element.setAttribute("aria-label", this.label); + + // Check if we need to suppress the tooltip + this._testIdenticalTooltip(); + } + }, + + /// + /// Gets or sets the icon of the AppBarCommand. + /// + icon: { + get: function () { + return this._icon; + }, + set: function (value) { + + this._icon = _Icon[value] || value; + + if (this._imageSpan) { + // If the icon's a single character, presume a glyph + if (this._icon && this._icon.length === 1) { + // Set the glyph + this._imageSpan.textContent = this._icon; + this._imageSpan.style.backgroundImage = ""; + this._imageSpan.style.msHighContrastAdjust = ""; + _ElementUtilities.addClass(this._imageSpan, "win-commandglyph"); + } else { + // Must be an image, set that + this._imageSpan.textContent = ""; + this._imageSpan.style.backgroundImage = this._icon; + this._imageSpan.style.msHighContrastAdjust = "none"; + _ElementUtilities.removeClass(this._imageSpan, "win-commandglyph"); + } + } + } + }, + + /// + /// Gets or sets the function to invoke when the command is clicked. + /// + onclick: { + get: function () { + return this._onclick; + }, + set: function (value) { + if (value && typeof value !== "function") { + throw new _ErrorFromName("WinJS.UI.AppBarCommand.BadClick", _Resources._formatString(strings.badClick, "AppBarCommand")); + } + this._onclick = value; + } + }, + + /// + /// Gets or sets the priority of the command + /// + priority: { + get: function () { + return this._priority; + }, + set: function (value) { + if (value === undefined || (typeof value === "number" && value >= 0)) { + this._priority = value; + } else { + throw new _ErrorFromName("WinJS.UI.AppBarCommand.BadPriority", _Resources._formatString(strings.badPriority, "AppBarCommand")); + } + + } + }, + + /// + /// For flyout-type AppBarCommands, this property returns the WinJS.UI.Flyout that this command invokes. + /// When setting this property, you may also use the String ID of the flyout to invoke, the DOM object + /// for the flyout, or the WinJS.UI.Flyout object itself. + /// If the value is set to the String ID of the flyout to invoke, or the DOM object for the flyout, but this + /// has not been processed yet, the getter will return the DOM object until it is processed, and + /// subsequently return a flyout. + /// + flyout: { + get: function () { + // Resolve it to the flyout + var flyout = this._flyout; + if (typeof flyout === "string") { + flyout = _Global.document.getElementById(flyout); + } + // If it doesn't have a .element, then we need to getControl on it + if (flyout && !flyout.element && flyout.winControl) { + flyout = flyout.winControl; + } + + return flyout; + }, + set: function (value) { + // Need to update aria-owns with the new ID. + var id = value; + if (id && typeof id !== "string") { + // Our controls have .element properties + if (id.element) { + id = id.element; + } + // Hope it's a DOM element, get ID from DOM element + if (id) { + if (id.id) { + id = id.id; + } else { + // No id, have to fake one + id.id = _ElementUtilities._uniqueID(id); + id = id.id; + } + } + } + if (typeof id === "string") { + this._element.setAttribute("aria-owns", id); + } + + // Remember it + this._flyout = value; + } + }, + + /// + /// Gets or sets the section that the AppBarCommand is in. Possible values are "secondary" and "primary". + /// + section: { + get: function () { + return this._section; + }, + set: function (value) { + // we allow settings section only one time + if (!this._section || _WinRT.Windows.ApplicationModel.DesignMode.designModeEnabled) { + this._setSection(value); + } + } + }, + + /// Gets or sets the tooltip text of the AppBarCommand. + tooltip: { + get: function () { + return this._tooltip; + }, + set: function (value) { + this._tooltip = value; + + // Update already-constructed tooltips. Separators and content commands won't have these: + if (this._tooltipControl) { + this._tooltipControl.innerHTML = this._tooltip; + } + + // Check if we need to suppress the tooltip + this._testIdenticalTooltip(); + } + }, + + /// Set or get the selected state of a toggle button. + selected: { + get: function () { + // Ensure it's a boolean because we're using the DOM element to keep in-sync + return this._element.getAttribute("aria-checked") === "true"; + }, + set: function (value) { + this._element.setAttribute("aria-checked", value); + } + }, + + /// + element: { + get: function () { + return this._element; + } + }, + + /// + /// Gets or sets a value that indicates whether the AppBarCommand is disabled. A value of true disables the AppBarCommand, and a value of false enables it. + /// + disabled: { + get: function () { + // Ensure it's a boolean because we're using the DOM element to keep in-sync + return !!this._element.disabled; + }, + set: function (value) { + this._element.disabled = value; + } + }, + + /// + hidden: { + get: function () { + // Ensure it's a boolean because we're using the DOM element to keep in-sync + return this._element.style.visibility === "hidden"; + }, + set: function (value) { + if (value === this.hidden) { + // No changes to make. + return; + } + + var style = this._element.style; + var originalVisibility = style.visibility; + var originalDisplay = style.display; + + if (value) { + style.visibility = "hidden"; + style.display = "none"; + } else { + style.visibility = ""; + style.display = "inline-block"; + } + + if (!this._sendEvent(_Constants.commandVisibilityChanged)) { + style.visibility = originalVisibility; + style.display = originalDisplay; + } + } + }, + + /// + /// Gets or sets the HTMLElement within a "content" type AppBarCommand that should receive focus whenever focus moves via Home or the arrow keys, + /// from the previous AppBarCommand to the this AppBarCommand. Returns the AppBarCommand object's host element by default. + /// + firstElementFocus: { + get: function () { + return this._firstElementFocus || this._lastElementFocus || this._element; + }, + set: function (element) { + // Arguments of null and this.element should treated the same to ensure that this.element is never a tabstop when either focus property has been set. + this._firstElementFocus = (element === this.element) ? null : element; + this._updateTabStop(); + } + }, + + /// + /// Gets or sets the HTMLElement within a "content" type AppBarCommand that should receive focus whenever focus would move, via End or arrow keys, + /// from the next AppBarCommand to this AppBarCommand. Returns this AppBarCommand object's host element by default. + /// + lastElementFocus: { + get: function () { + return this._lastElementFocus || this._firstElementFocus || this._element; + }, + set: function (element) { + // Arguments of null and this.element should treated the same to ensure that this.element is never a tabstop when either focus property has been set. + this._lastElementFocus = (element === this.element) ? null : element; + this._updateTabStop(); + } + }, + + dispose: function () { + /// + /// + /// Disposes this control. + /// + /// + if (this._disposed) { + return; + } + this._disposed = true; + + if (this._tooltipControl) { + this._tooltipControl.dispose(); + } + + if (this._type === _Constants.typeContent) { + _Dispose.disposeSubTree(this.element); + } + }, + + addEventListener: function (type, listener, useCapture) { + /// + /// + /// Registers an event handler for the specified event. + /// + /// + /// Required. The name of the event to register. + /// + /// Required. The event handler function to associate with this event. + /// + /// Optional. Set to true to register the event handler for the capturing phase; otherwise, set to false to register the event handler for the bubbling phase. + /// + /// + return this._element.addEventListener(type, listener, useCapture); + }, + + removeEventListener: function (type, listener, useCapture) { + /// + /// + /// Removes an event handler that the addEventListener method registered. + /// + /// Required. The name of the event to remove. + /// Required. The event handler function to remove. + /// + /// Optional. Set to true to remove the capturing phase event handler; otherwise, set to false to remove the bubbling phase event handler. + /// + /// + return this._element.removeEventListener(type, listener, useCapture); + }, + + /// Adds an extra CSS class during construction. + extraClass: { + get: function () { + return this._extraClass; + }, + set: function (value) { + if (this._extraClass) { + _ElementUtilities.removeClass(this._element, this._extraClass); + } + this._extraClass = value; + _ElementUtilities.addClass(this._element, this._extraClass); + } + }, + + // Private + _testIdenticalTooltip: function AppBarCommand_testIdenticalToolTip() { + this._hideIfFullSize = (this._label === this._tooltip); + }, + + _createContent: function AppBarCommand_createContent() { + // Make sure there's an element + if (!this._element) { + this._element = _Global.document.createElement("div"); + } else { + // Verify the element was a div + if (this._element.tagName !== "DIV") { + throw new _ErrorFromName("WinJS.UI.AppBarCommand.BadDivElement", strings.badDivElement); + } + } + + // If a tabIndex isnt set, default to 0; + if (parseInt(this._element.getAttribute("tabIndex"), 10) !== this._element.tabIndex) { + this._element.tabIndex = 0; + } + }, + + _createSeparator: function AppBarCommand_createSeparator() { + // Make sure there's an element + if (!this._element) { + this._element = _Global.document.createElement("hr"); + } else { + // Verify the element was an hr + if (this._element.tagName !== "HR") { + throw new _ErrorFromName("WinJS.UI.AppBarCommand.BadHrElement", strings.badHrElement); + } + } + }, + + _createButton: function AppBarCommand_createButton() { + // Make sure there's an element + if (!this._element) { + this._element = _Global.document.createElement("button"); + } else { + // Verify the element was a button + if (this._element.tagName !== "BUTTON") { + throw new _ErrorFromName("WinJS.UI.AppBarCommand.BadButtonElement", strings.badButtonElement); + } + // Make sure it has a type="button" + var type = this._element.getAttribute("type"); + if (type === null || type === "" || type === undefined) { + this._element.setAttribute("type", "button"); + } + this._element.innerHTML = ""; + } + + // AppBarCommand buttons need to look like this: + //// + this._element.type = "button"; + this._iconSpan = _Global.document.createElement("span"); + this._iconSpan.setAttribute("aria-hidden", "true"); + this._iconSpan.className = "win-commandicon"; + this._iconSpan.tabIndex = -1; + this._element.appendChild(this._iconSpan); + this._imageSpan = _Global.document.createElement("span"); + this._imageSpan.setAttribute("aria-hidden", "true"); + this._imageSpan.className = "win-commandimage"; + this._imageSpan.tabIndex = -1; + this._iconSpan.appendChild(this._imageSpan); + this._labelSpan = _Global.document.createElement("span"); + this._labelSpan.setAttribute("aria-hidden", "true"); + this._labelSpan.className = "win-label"; + this._labelSpan.tabIndex = -1; + this._element.appendChild(this._labelSpan); + // 'win-global' or 'win-selection' are added later by caller. + // Label and icon are added later by caller. + + // Attach a tooltip - Note: we're going to stomp on it's setControl so we don't have to make another DOM element to hang it off of. + // This private _tooltipControl attribute is used by other pieces, changing the name could break them. + this._tooltipControl = new Tooltip.Tooltip(this._element); + var that = this; + this._tooltipControl.addEventListener("beforeopen", function () { + if (that._hideIfFullSize && !_Overlay._Overlay._getParentControlUsingClassName(that._element.parentElement, _Constants.reducedClass)) { + that._tooltipControl.close(); + } + }, false); + }, + + _setSection: function AppBarCommand_setSection(section) { + if (!section) { + section = _Constants.sectionPrimary; + } + + // _Constants.sectionSelection and _Constants.sectionGlobal are deprecated, so we will continue + // adding/removing its corresponding CSS class for app compat. + // _Constants.sectionPrimary and _Constants.sectionSecondary no longer apply CSS classes to the + // commands. + + if (this._section) { + // Remove the old section class + if (this._section === _Constants.sectionGlobal) { + _ElementUtilities.removeClass(this._element, _Constants.appBarCommandGlobalClass); + } else if (this.section === _Constants.sectionSelection) { + _ElementUtilities.removeClass(this._element, _Constants.appBarCommandSelectionClass); + } + } + // Add the new section class + this._section = section; + if (section === _Constants.sectionGlobal) { + _ElementUtilities.addClass(this._element, _Constants.appBarCommandGlobalClass); + } else if (section === _Constants.sectionSelection) { + _ElementUtilities.addClass(this._element, _Constants.appBarCommandSelectionClass); + } + }, + + _updateTabStop: function AppBarCommand_updateTabStop() { + // Whenever the firstElementFocus or lastElementFocus properties are set for content type AppBarCommands, + // the containing command element is no longer a tabstop. + + if (this._firstElementFocus || this._lastElementFocus) { + this.element.tabIndex = -1; + } else { + this.element.tabIndex = 0; + } + }, + + _isFocusable: function AppBarCommand_isFocusable() { + return (!this.hidden && this._type !== _Constants.typeSeparator && !this.element.disabled && + (this.firstElementFocus.tabIndex >= 0 || this.lastElementFocus.tabIndex >= 0)); + }, + + _sendEvent: function AppBarCommand_sendEvent(eventName, detail) { + if (this._disposed) { + return; + } + var event = _Global.document.createEvent("CustomEvent"); + event.initCustomEvent(eventName, true, true, (detail || {})); + return this._element.dispatchEvent(event); + }, + }); + + + // The list of AppBarCommand properties that we care about firing an event + // for, whenever they are changed after initial construction. + var ObservablePropertyWhiteList = [ + "label", + "disabled", + "flyout", + "extraClass", + "selected", + "onclick", + "hidden", + ]; + + function makeObservable(command, propertyName) { + // Make a pre-existing AppBarCommand property observable by firing the "_commandpropertymutated" + // event whenever its value changes. + + // Preserve initial value in JS closure variable + var _value = command[propertyName]; + + // Preserve original getter/setter if they exist, else use inline proxy functions. + var proto = command.constructor.prototype; + var originalDesc = getPropertyDescriptor(proto, propertyName) || {}; + var getter = originalDesc.get.bind(command) || function getterProxy() { + return _value; + }; + var setter = originalDesc.set.bind(command) || function setterProxy(value) { + _value = value; + }; + + // Define new observable Get/Set for propertyName on the command instance + Object.defineProperty(command, propertyName, { + get: function observable_get() { + return getter(); + }, + set: function observable_set(value) { + + var oldValue = getter(); + + // Process value through the original setter & getter before deciding to send an event. + setter(value); + var newValue = getter(); + if (!this._disposed && oldValue !== value && oldValue !== newValue && !command._disposed) { + + command._propertyMutations.dispatchEvent( + _Constants.commandPropertyMutated, + { + command: command, + propertyName: propertyName, + oldValue: oldValue, + newValue: newValue, + }); + } + } + }); + } + + function getPropertyDescriptor(obj, propertyName) { + // Returns a matching property descriptor, or null, + // if no matching descriptor is found. + var desc = null; + while (obj && !desc) { + desc = Object.getOwnPropertyDescriptor(obj, propertyName); + obj = Object.getPrototypeOf(obj); + // Walk obj's prototype chain until we find a match. + } + return desc; + } + + return AppBarCommand; + }) + }); + + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + Command: _Base.Namespace._lazy(function () { return exports.AppBarCommand; }) + }); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +// Menu Command +/// appbar,appbars,Flyout,Flyouts,onclick,Statics +define('WinJS/Controls/Menu/_Command',[ + 'exports', + '../../Core/_Global', + '../../Core/_Base', + '../../Core/_ErrorFromName', + '../../Core/_Resources', + '../../Promise', + '../../Utilities/_Control', + '../../Utilities/_ElementUtilities', + '../_LegacyAppBar/_Constants', + '../Flyout/_Overlay' +], function menuCommandInit(exports, _Global, _Base, _ErrorFromName, _Resources, Promise, _Control, _ElementUtilities, _Constants, _Overlay) { + "use strict"; + + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + /// + /// + /// Represents a command to be displayed in a Menu. MenuCommand objects provide button, toggle button, flyout button, + /// or separator functionality for Menu controls. + /// + /// + /// + /// + /// + /// ]]> + /// The MenuCommand control itself + /// + /// + MenuCommand: _Base.Namespace._lazy(function () { + + var strings = { + get ariaLabel() { return _Resources._getWinJSString("ui/menuCommandAriaLabel").value; }, + get duplicateConstruction() { return "Invalid argument: Controls may only be instantiated one time for each DOM element"; }, + get badClick() { return "Invalid argument: The onclick property for an {0} must be a function"; }, + get badHrElement() { return "Invalid argument: For a separator, the element must be null or an hr element"; }, + get badButtonElement() { return "Invalid argument: For a button, toggle, or flyout command, the element must be null or a button element"; } + }; + + var MenuCommand = _Base.Class.define(function MenuCommand_ctor(element, options) { + /// + /// + /// Creates a new MenuCommand object. + /// + /// + /// The DOM element that will host the control. + /// + /// + /// The set of properties and values to apply to the new MenuCommand. + /// + /// + /// A MenuCommand control. + /// + /// + /// + + // Check to make sure we weren't duplicated + if (element && element.winControl) { + throw new _ErrorFromName("WinJS.UI.MenuCommand.DuplicateConstruction", strings.duplicateConstruction); + } + + this._disposed = false; + + // Don't blow up if they didn't pass options + if (!options) { + options = {}; + } + + // Need a type before we can create our element + if (!options.type) { + this._type = _Constants.typeButton; + } + + // Go ahead and create it, separator types look different than buttons + // Don't forget to use passed in element if one was provided. + this._element = element; + if (options.type === _Constants.typeSeparator) { + this._createSeparator(); + } else { + // This will also set the icon & label + this._createButton(); + } + _ElementUtilities.addClass(this._element, "win-disposable"); + + // Remember ourselves + this._element.winControl = this; + + // Attach our css class + _ElementUtilities.addClass(this._element, _Constants.menuCommandClass); + + if (!options.selected && options.type === _Constants.typeToggle) { + // Make sure toggle's have selected false for CSS + this.selected = false; + } + + if (options.onclick) { + this.onclick = options.onclick; + } + options.onclick = this._handleClick.bind(this); + + _Control.setOptions(this, options); + + // Set our options + if (this._type !== _Constants.typeSeparator) { + // Make sure we have an ARIA role + var role = this._element.getAttribute("role"); + if (role === null || role === "" || role === undefined) { + role = "menuitem"; + if (this._type === _Constants.typeToggle) { + role = "menuitemcheckbox"; + } + this._element.setAttribute("role", role); + if (this._type === _Constants.typeFlyout) { + this._element.setAttribute("aria-haspopup", true); + } + } + var label = this._element.getAttribute("aria-label"); + if (label === null || label === "" || label === undefined) { + this._element.setAttribute("aria-label", strings.ariaLabel); + } + } + + }, { + /// + /// Gets the ID of the MenuCommand. + /// + /// + id: { + get: function () { + return this._element.id; + }, + set: function (value) { + // we allow setting first time only. otherwise we ignore it. + if (!this._element.id) { + this._element.id = value; + } + } + }, + + /// + /// Gets the type of the MenuCommand. Possible values are "button", "toggle", "flyout", or "separator". + /// + /// + type: { + get: function () { + return this._type; + }, + set: function (value) { + // we allow setting first time only. otherwise we ignore it. + if (!this._type) { + if (value !== _Constants.typeButton && value !== _Constants.typeFlyout && value !== _Constants.typeToggle && value !== _Constants.typeSeparator) { + value = _Constants.typeButton; + } + + this._type = value; + + if (value === _Constants.typeButton) { + _ElementUtilities.addClass(this.element, _Constants.menuCommandButtonClass); + } else if (value === _Constants.typeFlyout) { + _ElementUtilities.addClass(this.element, _Constants.menuCommandFlyoutClass); + this.element.addEventListener("keydown", this._handleKeyDown.bind(this), false); + } else if (value === _Constants.typeSeparator) { + _ElementUtilities.addClass(this.element, _Constants.menuCommandSeparatorClass); + } else if (value === _Constants.typeToggle) { + _ElementUtilities.addClass(this.element, _Constants.menuCommandToggleClass); + } + } + } + }, + + /// + /// The label of the MenuCommand + /// + /// + label: { + get: function () { + return this._label; + }, + set: function (value) { + this._label = value || ""; + if (this._labelSpan) { + this._labelSpan.textContent = this.label; + } + + // Update aria-label + this._element.setAttribute("aria-label", this.label); + } + }, + + /// + /// Gets or sets the function to invoke when the command is clicked. + /// + /// + onclick: { + get: function () { + return this._onclick; + }, + set: function (value) { + if (value && typeof value !== "function") { + throw new _ErrorFromName("WinJS.UI.MenuCommand.BadClick", _Resources._formatString(strings.badClick, "MenuCommand")); + } + this._onclick = value; + } + }, + + /// + /// For flyout type MenuCommands, this property returns the WinJS.UI.Flyout that this command invokes. When setting this property, you can set + /// it to the string ID of the Flyout, the DOM object that hosts the Flyout, or the Flyout object itself. + /// + /// + flyout: { + get: function () { + // Resolve it to the flyout + var flyout = this._flyout; + if (typeof flyout === "string") { + flyout = _Global.document.getElementById(flyout); + } + // If it doesn't have a .element, then we need to getControl on it + if (flyout && !flyout.element) { + flyout = flyout.winControl; + } + + return flyout; + }, + set: function (value) { + + // Need to update aria-owns with the new ID. + var id = value; + if (id && typeof id !== "string") { + // Our controls have .element properties + if (id.element) { + id = id.element; + } + // Hope it's a DOM element, get ID from DOM element + if (id) { + if (id.id) { + id = id.id; + } else { + // No id, have to fake one + id.id = _ElementUtilities._uniqueID(id); + id = id.id; + } + } + } + if (typeof id === "string") { + this._element.setAttribute("aria-owns", id); + } + + if (this._flyout !== value) { + MenuCommand._deactivateFlyoutCommand(this); + } + + // Remember it + this._flyout = value; + } + }, + + /// + /// Gets or sets the selected state of a toggle button. This property is true if the toggle button is selected; otherwise, it's false. + /// + /// + selected: { + get: function () { + // Ensure it's a boolean because we're using the DOM element to keep in-sync + return this._element.getAttribute("aria-checked") === "true"; + }, + set: function (value) { + this._element.setAttribute("aria-checked", !!value); + } + }, + + /// + element: { + get: function () { + return this._element; + } + }, + + /// + /// Gets or sets a value that indicates whether the MenuCommand is disabled. This value is true if the MenuCommand is disabled; otherwise, false. + /// + /// + disabled: { + get: function () { + // Ensure it's a boolean because we're using the DOM element to keep in-sync + return !!this._element.disabled; + }, + set: function (value) { + value = !!value; + if (value && this.type === _Constants.typeFlyout) { + MenuCommand._deactivateFlyoutCommand(this); + } + this._element.disabled = value; + } + }, + + /// + hidden: { + get: function () { + // Ensure it's a boolean because we're using the DOM element to keep in-sync + return this._element.style.visibility === "hidden"; + }, + set: function (value) { + var menuControl = _Overlay._Overlay._getParentControlUsingClassName(this._element, _Constants.menuClass); + if (menuControl && !menuControl.hidden) { + throw new _ErrorFromName("WinJS.UI.MenuCommand.CannotChangeHiddenProperty", _Resources._formatString(_Overlay._Overlay.commonstrings.cannotChangeHiddenProperty, "Menu")); + } + + var style = this._element.style; + if (value) { + if (this.type === _Constants.typeFlyout) { + MenuCommand._deactivateFlyoutCommand(this); + } + style.visibility = "hidden"; + style.display = "none"; + } else { + style.visibility = ""; + style.display = "block"; + } + } + }, + + /// + /// Gets or sets the extra CSS class that is applied to the host DOM element. + /// + /// + extraClass: { + get: function () { + return this._extraClass; + }, + set: function (value) { + if (this._extraClass) { + _ElementUtilities.removeClass(this._element, this._extraClass); + } + this._extraClass = value; + _ElementUtilities.addClass(this._element, this._extraClass); + } + }, + + + dispose: function () { + /// + /// + /// Disposes this control. + /// + /// + /// + if (this._disposed) { + return; + } + this._disposed = true; + }, + + addEventListener: function (type, listener, useCapture) { + /// + /// + /// Registers an event handler for the specified event. + /// + /// The name of the event to register. + /// The function that handles the event. + /// + /// Set to true to register the event handler for the capturing phase; otherwise, set to false to register the event handler for the bubbling phase. + /// + /// + /// + return this._element.addEventListener(type, listener, useCapture); + }, + + removeEventListener: function (type, listener, useCapture) { + /// + /// + /// Removes the specified event handler that the addEventListener method registered. + /// + /// The name of the event to remove. + /// The event handler function to remove. + /// + /// Set to true to remove the capturing phase event handler; set to false to remove the bubbling phase event handler. + /// + /// + /// + return this._element.removeEventListener(type, listener, useCapture); + }, + + // Private properties + _createSeparator: function MenuCommand_createSeparator() { + // Make sure there's an input element + if (!this._element) { + this._element = _Global.document.createElement("hr"); + } else { + // Verify the input was an hr + if (this._element.tagName !== "HR") { + throw new _ErrorFromName("WinJS.UI.MenuCommand.BadHrElement", strings.badHrElement); + } + } + }, + + _createButton: function MenuCommand_createButton() { + // Make sure there's an element + if (!this._element) { + this._element = _Global.document.createElement("button"); + } else { + // Verify the input was a button + if (this._element.tagName !== "BUTTON") { + throw new _ErrorFromName("WinJS.UI.MenuCommand.BadButtonElement", strings.badButtonElement); + } + } + + // Create our inner HTML. We will set aria values on the button itself further down in the constructor. + this._element.innerHTML = + '
' + + '' + + '' + + '' + + '
'; + this._element.type = "button"; + + // The purpose of menuCommandLiner is to lay out the MenuCommand's children in a flexbox. Ideally, this flexbox would + // be on MenuCommand.element. However, firefox lays out buttons with display:flex differently. + // Firefox bug 1014285 (Button with display:inline-flex doesn't layout properly) + // https://bugzilla.mozilla.org/show_bug.cgi?id=1014285 + this._menuCommandLiner = this._element.firstElementChild; + this._toggleSpan = this._menuCommandLiner.firstElementChild; + this._labelSpan = this._toggleSpan.nextElementSibling; + this._flyoutSpan = this._labelSpan.nextElementSibling; + + }, + _sendEvent: function MenuCommand_sendEvent(eventName, detail) { + if (!this._disposed) { + var event = _Global.document.createEvent("CustomEvent"); + event.initCustomEvent(eventName, true, true, (detail || {})); + this._element.dispatchEvent(event); + } + }, + + _invoke: function MenuCommand_invoke(event) { + if (!this.hidden && !this.disabled && !this._disposed) { + if (this._type === _Constants.typeToggle) { + this.selected = !this.selected; + } else if (this._type === _Constants.typeFlyout) { + MenuCommand._activateFlyoutCommand(this); + } + + if (event && event.type === "click" && this.onclick) { + this.onclick(event); + } + + // Bubble private 'invoked' event to Menu + this._sendEvent(_Constants._menuCommandInvokedEvent, { command: this }); + } + }, + + _handleClick: function MenuCommand_handleClick(event) { + this._invoke(event); + }, + + _handleKeyDown: function MenuCommand_handleKeyDown(event) { + var Key = _ElementUtilities.Key, + rtl = _Global.getComputedStyle(this.element).direction === "rtl", + rightKey = rtl ? Key.leftArrow : Key.rightArrow; + + if (event.keyCode === rightKey && this.type === _Constants.typeFlyout) { + this._invoke(event); + + // Prevent the page from scrolling + event.preventDefault(); + } + }, + }, { + // Statics + _activateFlyoutCommand: function MenuCommand_activateFlyoutCommand(menuCommand) { + // Activates the associated Flyout command and returns a promise once complete. + // A command is considered to be activated once the proper CSS class has been applied and its associated flyout has finished showing. + return new Promise(function (c, e) { + menuCommand = menuCommand.winControl || menuCommand; + var subFlyout = menuCommand.flyout; + // Flyout may not have processAll'd, so this may be a DOM object + if (subFlyout && subFlyout.hidden && subFlyout.show) { + _ElementUtilities.addClass(menuCommand.element, _Constants.menuCommandFlyoutActivatedClass); + + // Remove activation class from the command if the flyout is ever hidden. + subFlyout.addEventListener("beforehide", function beforeHide() { + subFlyout.removeEventListener("beforehide", beforeHide, false); + _ElementUtilities.removeClass(menuCommand.element, _Constants.menuCommandFlyoutActivatedClass); + }, false); + + subFlyout.addEventListener("aftershow", function afterShow() { + subFlyout.removeEventListener("aftershow", afterShow, false); + // We are considered activated once we start showing the flyout. + c(); + }, false); + + subFlyout.show(menuCommand, "_cascade"); + } else { + // Could not change command to activated state. + e(); + } + }); + }, + + _deactivateFlyoutCommand: function MenuCommand_deactivateFlyoutCommand(menuCommand) { + // Deactivates the associated Flyout command and returns a promise once complete. + // A command is considered to be deactivated once the proper CSS class has been applied and its associated flyout has finished hiding. + return new Promise(function (c) { + menuCommand = menuCommand.winControl || menuCommand; + _ElementUtilities.removeClass(menuCommand.element, _Constants.menuCommandFlyoutActivatedClass); + + var subFlyout = menuCommand.flyout; + // Flyout may not have processAll'd, so this may be a DOM object + if (subFlyout && !subFlyout.hidden && subFlyout.hide) { + + subFlyout.addEventListener("afterhide", function afterHide() { + subFlyout.removeEventListener("afterhide", afterHide, false); + c(); + }, false); + + subFlyout.hide(); + } else { + // subFlyout does not need to be hidden. + c(); + } + }); + }, + }); + return MenuCommand; + }) + }); + +}); + + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +define('WinJS/Controls/CommandingSurface/_MenuCommand',["require", "exports", "../Menu/_Command"], function (require, exports, _MenuCommandBase) { + var _MenuCommand = (function (_super) { + __extends(_MenuCommand, _super); + function _MenuCommand(element, options) { + if (options && options.beforeInvoke) { + this._beforeInvoke = options.beforeInvoke; + } + _super.call(this, element, options); + } + _MenuCommand.prototype._invoke = function (event) { + this._beforeInvoke && this._beforeInvoke(event); + _super.prototype._invoke.call(this, event); + }; + return _MenuCommand; + })(_MenuCommandBase.MenuCommand); + exports._MenuCommand = _MenuCommand; +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// +define('WinJS/Utilities/_OpenCloseMachine',["require", "exports", '../Core/_Global', '../Promise', '../_Signal'], function (require, exports, _Global, Promise, _Signal) { + "use strict"; + // This module provides a state machine which is designed to be used by controls which need to + // open, close, and fire related events (e.g. beforeopen, afterclose). The state machine handles + // many edge cases. For example, what happens if: + // - open is called when we're already opened? + // - close is called while we're in the middle of opening? + // - dispose is called while we're in the middle of firing beforeopen? + // The state machine takes care of all of these edge cases so that the control doesn't have to. + // The control is responible for knowing how to play its open/close animations and update its DOM. + // The state machine is responsible for ensuring that these things happen at the appropriate times. + // This module is broken up into 3 major pieces: + // - OpenCloseMachine: Controls should instantiate one of these. The machine keeps track of the + // current state and has methods for forwarding calls to the current state. + // - IOpenCloseControl: Controls must provide an object which implements this interface. The + // interface gives the machine hooks for invoking the control's open and close animations. + // - States: The various states (e.g. Closed, Opened, Opening) that the machine can be in. Each + // implements IOpenCloseState. + // Example usage: + // class MyControl { + // element: HTMLElement; + // private _machine: OpenCloseMachine; + // + // constructor(element?: HTMLElement, options: any = {}) { + // this.element = element || document.createElement("div"); + // + // // Create the machine. + // this._machine = new OpenCloseMachine({ + // eventElement: this.element, + // onOpen: (): Promise => { + // // Do the work to render the contol in its opened state with an animation. + // // Return the animation promise. + // }, + // onClose: (): Promise => { + // // Do the work to render the contol in its closed state with an animation. + // // Return the animation promise. + // }, + // onUpdateDom() { + // // Do the work to render the internal state of the control to the DOM. If a + // // control restricts all its DOM modifications to onUpdateDom, the state machine + // // can guarantee that the control won't modify its DOM while it is animating. + // }, + // onUpdateDomWithIsOpened: (isOpened: boolean ) => { + // // Do the same work as onUpdateDom but ensure that the DOM is rendered with either + // // the opened or closed visual as dictacted by isOpened. The control should have some + // // internal state to track whether it is currently opened or closed. Treat this as a + // // cue to mutate that internal state to reflect the value of isOpened. + // }, + // }); + // + // // Initialize the control. During this time, the machine will not ask the control to + // // play any animations or update its DOM. + // this.opened = true; + // _Control.setOptions(this, options); + // + // // Tell the machine the control is initialized. After this, the machine will start asking + // // the control to play animations and update its DOM as appropriate. + // this._machine.exitInit(); + // } + // + // get opened() { + // return this._machine.opened; + // } + // set opened(value: boolean) { + // this._machine.opened = value; + // } + // open() { + // this._machine.open(); + // } + // close() { + // this._machine.close(); + // } + // forceLayout() { + // this._machine.updateDom(); + // } + // dispose() { + // this._machine.dispose(); + // } + // } + var EventNames = { + beforeOpen: "beforeopen", + afterOpen: "afteropen", + beforeClose: "beforeclose", + afterClose: "afterclose", + // Private events + // Indicates that the OpenCloseMachine has settled either into the Opened state + // or Closed state. This is more comprehensive than the "afteropen" and "afterclose" + // events because it fires even if the machine has reached the state due to: + // - Exiting the Init state + // - The beforeopen/beforeclose events being canceled + _openCloseStateSettled: "_openCloseStateSettled" + }; + // + // OpenCloseMachine + // + var OpenCloseMachine = (function () { + // + // Methods called by the control + // + // When the machine is created, it sits in the Init state. When in the Init state, calls to + // updateDom will be postponed until the machine exits the Init state. Consequently, while in + // this state, the control can feel free to call updateDom as many times as it wants without + // worrying about it being expensive due to updating the DOM many times. The control should call + // *exitInit* to move the machine out of the Init state. + function OpenCloseMachine(args) { + this._control = args; + this._initializedSignal = new _Signal(); + this._disposed = false; + this._setState(States.Init); + } + // Moves the machine out of the Init state and into the Opened or Closed state depending on whether + // open or close was called more recently. + OpenCloseMachine.prototype.exitInit = function () { + this._initializedSignal.complete(); + }; + // These method calls are forwarded to the current state. + OpenCloseMachine.prototype.updateDom = function () { + this._state.updateDom(); + }; + OpenCloseMachine.prototype.open = function () { + this._state.open(); + }; + OpenCloseMachine.prototype.close = function () { + this._state.close(); + }; + Object.defineProperty(OpenCloseMachine.prototype, "opened", { + get: function () { + return this._state.opened; + }, + set: function (value) { + if (value) { + this.open(); + } + else { + this.close(); + } + }, + enumerable: true, + configurable: true + }); + // Puts the machine into the Disposed state. + OpenCloseMachine.prototype.dispose = function () { + this._setState(States.Disposed); + this._disposed = true; + this._control = null; + }; + // + // Methods called by states + // + OpenCloseMachine.prototype._setState = function (NewState, arg0) { + if (!this._disposed) { + this._state && this._state.exit(); + this._state = new NewState(); + this._state.machine = this; + this._state.enter(arg0); + } + }; + // Triggers arbitrary app code + OpenCloseMachine.prototype._fireEvent = function (eventName, options) { + options = options || {}; + var detail = options.detail || null; + var cancelable = !!options.cancelable; + var eventObject = _Global.document.createEvent("CustomEvent"); + eventObject.initCustomEvent(eventName, true, cancelable, detail); + return this._control.eventElement.dispatchEvent(eventObject); + }; + // Triggers arbitrary app code + OpenCloseMachine.prototype._fireBeforeOpen = function () { + return this._fireEvent(EventNames.beforeOpen, { + cancelable: true + }); + }; + // Triggers arbitrary app code + OpenCloseMachine.prototype._fireBeforeClose = function () { + return this._fireEvent(EventNames.beforeClose, { + cancelable: true + }); + }; + return OpenCloseMachine; + })(); + exports.OpenCloseMachine = OpenCloseMachine; + // + // States (each implements IOpenCloseState) + // + // WinJS animation promises always complete successfully. This + // helper allows an animation promise to complete in the canceled state + // so that the success handler can be skipped when the animation is + // interrupted. + function cancelablePromise(animationPromise) { + return Promise._cancelBlocker(animationPromise, function () { + animationPromise.cancel(); + }); + } + // Noop function, used in the various states to indicate that they don't support a given + // message. Named with the somewhat cute name '_' because it reads really well in the states. + function _() { + } + // Implementing the control as a state machine helps us correctly handle: + // - re-entrancy while firing events + // - calls into the control during asynchronous operations (e.g. animations) + // + // Many of the states do their "enter" work within a promise chain. The idea is that if + // the state is interrupted and exits, the rest of its work can be skipped by canceling + // the promise chain. + // An interesting detail is that anytime the state may trigger app code (e.g. due to + // firing an event), the current promise must end and a new promise must be chained off of it. + // This is necessary because the app code may interact with the control and cause it to + // change states. If we didn't create a new promise, then the very next line of code that runs + // after triggering app code may not be valid because the state may have exited. Starting a + // new promise after each triggering of app code prevents us from having to worry about this + // problem. In this configuration, when a promise's success handler runs, it guarantees that + // the state hasn't exited. + // For similar reasons, each of the promise chains created in "enter" starts off with a _Signal + // which is completed at the end of the "enter" function (this boilerplate is abstracted away by + // the "interruptible" function). The reason is that we don't want any of the code in "enter" + // to run until the promise chain has been stored in a variable. If we didn't do this (e.g. instead, + // started the promise chain with Promise.wrap()), then the "enter" code could trigger the "exit" + // function (via app code) before the promise chain had been stored in a variable. Under these + // circumstances, the promise chain would be uncancelable and so the "enter" work would be + // unskippable. This wouldn't be good when we needed the state to exit early. + // These two functions manage interruptible work promises (one creates them the other cancels + // them). They communicate with each other thru the _interruptibleWorkPromises property which + // "interruptible" creates on your object. + function interruptible(object, workFn) { + object["_interruptibleWorkPromises"] = object["_interruptibleWorkPromises"] || []; + var workStoredSignal = new _Signal(); + object["_interruptibleWorkPromises"].push(workFn(workStoredSignal.promise)); + workStoredSignal.complete(); + } + function cancelInterruptibles() { + (this["_interruptibleWorkPromises"] || []).forEach(function (workPromise) { + workPromise.cancel(); + }); + } + // Transitions: + // When created, the state machine will take one of the following initialization + // transitions depending on how the machines's APIs have been used by the time + // exitInit() is called on it: + // Init -> Closed + // Init -> Opened + // Following that, the life of the machine will be dominated by the following + // sequences of transitions. In geneneral, these sequences are uninterruptible. + // Closed -> BeforeOpen -> Closed (when preventDefault is called on beforeopen event) + // Closed -> BeforeOpen -> Opening -> Opened + // Opened -> BeforeClose -> Opened (when preventDefault is called on beforeclose event) + // Opened -> BeforeClose -> Closing -> Closed + // However, any state can be interrupted to go to the Disposed state: + // * -> Disposed + var States; + (function (States) { + function updateDomImpl() { + this.machine._control.onUpdateDom(); + } + // Initial state. Gives the control the opportunity to initialize itself without + // triggering any animations or DOM modifications. When done, the control should + // call *exitInit* to move the machine to the next state. + var Init = (function () { + function Init() { + this.name = "Init"; + this.exit = cancelInterruptibles; + this.updateDom = _; // Postponed until immediately before we switch to another state + } + Init.prototype.enter = function () { + var _this = this; + interruptible(this, function (ready) { + return ready.then(function () { + return _this.machine._initializedSignal.promise; + }).then(function () { + _this.machine._control.onUpdateDomWithIsOpened(_this._opened); + _this.machine._setState(_this._opened ? Opened : Closed); + }); + }); + }; + Object.defineProperty(Init.prototype, "opened", { + get: function () { + return this._opened; + }, + enumerable: true, + configurable: true + }); + Init.prototype.open = function () { + this._opened = true; + }; + Init.prototype.close = function () { + this._opened = false; + }; + return Init; + })(); + States.Init = Init; + // A rest state. The control is closed and is waiting for the app to call open. + var Closed = (function () { + function Closed() { + this.name = "Closed"; + this.exit = _; + this.opened = false; + this.close = _; + this.updateDom = updateDomImpl; + } + Closed.prototype.enter = function (args) { + args = args || {}; + if (args.openIsPending) { + this.open(); + } + this.machine._fireEvent(EventNames._openCloseStateSettled); + }; + Closed.prototype.open = function () { + this.machine._setState(BeforeOpen); + }; + return Closed; + })(); + // An event state. The control fires the beforeopen event. + var BeforeOpen = (function () { + function BeforeOpen() { + this.name = "BeforeOpen"; + this.exit = cancelInterruptibles; + this.opened = false; + this.open = _; + this.close = _; + this.updateDom = updateDomImpl; + } + BeforeOpen.prototype.enter = function () { + var _this = this; + interruptible(this, function (ready) { + return ready.then(function () { + return _this.machine._fireBeforeOpen(); // Give opportunity for chain to be canceled when triggering app code + }).then(function (shouldOpen) { + if (shouldOpen) { + _this.machine._setState(Opening); + } + else { + _this.machine._setState(Closed); + } + }); + }); + }; + return BeforeOpen; + })(); + // An animation/event state. The control plays its open animation and fires afteropen. + var Opening = (function () { + function Opening() { + this.name = "Opening"; + this.exit = cancelInterruptibles; + this.updateDom = _; // Postponed until immediately before we switch to another state + } + Opening.prototype.enter = function () { + var _this = this; + interruptible(this, function (ready) { + return ready.then(function () { + _this._closeIsPending = false; + return cancelablePromise(_this.machine._control.onOpen()); + }).then(function () { + _this.machine._fireEvent(EventNames.afterOpen); // Give opportunity for chain to be canceled when triggering app code + }).then(function () { + _this.machine._control.onUpdateDom(); + _this.machine._setState(Opened, { closeIsPending: _this._closeIsPending }); + }); + }); + }; + Object.defineProperty(Opening.prototype, "opened", { + get: function () { + return !this._closeIsPending; + }, + enumerable: true, + configurable: true + }); + Opening.prototype.open = function () { + this._closeIsPending = false; + }; + Opening.prototype.close = function () { + this._closeIsPending = true; + }; + return Opening; + })(); + // A rest state. The control is opened and is waiting for the app to call close. + var Opened = (function () { + function Opened() { + this.name = "Opened"; + this.exit = _; + this.opened = true; + this.open = _; + this.updateDom = updateDomImpl; + } + Opened.prototype.enter = function (args) { + args = args || {}; + if (args.closeIsPending) { + this.close(); + } + this.machine._fireEvent(EventNames._openCloseStateSettled); + }; + Opened.prototype.close = function () { + this.machine._setState(BeforeClose); + }; + return Opened; + })(); + // An event state. The control fires the beforeclose event. + var BeforeClose = (function () { + function BeforeClose() { + this.name = "BeforeClose"; + this.exit = cancelInterruptibles; + this.opened = true; + this.open = _; + this.close = _; + this.updateDom = updateDomImpl; + } + BeforeClose.prototype.enter = function () { + var _this = this; + interruptible(this, function (ready) { + return ready.then(function () { + return _this.machine._fireBeforeClose(); // Give opportunity for chain to be canceled when triggering app code + }).then(function (shouldClose) { + if (shouldClose) { + _this.machine._setState(Closing); + } + else { + _this.machine._setState(Opened); + } + }); + }); + }; + return BeforeClose; + })(); + // An animation/event state. The control plays the close animation and fires the afterclose event. + var Closing = (function () { + function Closing() { + this.name = "Closing"; + this.exit = cancelInterruptibles; + this.updateDom = _; // Postponed until immediately before we switch to another state + } + Closing.prototype.enter = function () { + var _this = this; + interruptible(this, function (ready) { + return ready.then(function () { + _this._openIsPending = false; + return cancelablePromise(_this.machine._control.onClose()); + }).then(function () { + _this.machine._fireEvent(EventNames.afterClose); // Give opportunity for chain to be canceled when triggering app code + }).then(function () { + _this.machine._control.onUpdateDom(); + _this.machine._setState(Closed, { openIsPending: _this._openIsPending }); + }); + }); + }; + Object.defineProperty(Closing.prototype, "opened", { + get: function () { + return this._openIsPending; + }, + enumerable: true, + configurable: true + }); + Closing.prototype.open = function () { + this._openIsPending = true; + }; + Closing.prototype.close = function () { + this._openIsPending = false; + }; + return Closing; + })(); + var Disposed = (function () { + function Disposed() { + this.name = "Disposed"; + this.enter = _; + this.exit = _; + this.opened = false; + this.open = _; + this.close = _; + this.updateDom = _; + } + return Disposed; + })(); + States.Disposed = Disposed; + })(States || (States = {})); +}); + + +define('require-style!less/styles-commandingsurface',[],function(){}); + +define('require-style!less/colors-commandingsurface',[],function(){}); +define('WinJS/Controls/CommandingSurface/_CommandingSurface',["require", "exports", "../../Animations", "../../Core/_Base", "../../Core/_BaseUtils", "../../BindingList", "../../ControlProcessor", "../CommandingSurface/_Constants", "../AppBar/_Command", "../CommandingSurface/_MenuCommand", "../../Utilities/_Control", "../../Utilities/_Dispose", "../../Utilities/_ElementUtilities", "../../Core/_ErrorFromName", '../../Core/_Events', "../../Controls/Flyout", "../../Core/_Global", "../../Utilities/_Hoverable", "../../Utilities/_KeyboardBehavior", '../../Core/_Log', '../../Promise', "../../Core/_Resources", "../../Scheduler", '../../Utilities/_OpenCloseMachine', '../../_Signal', "../../Core/_WriteProfilerMark"], function (require, exports, Animations, _Base, _BaseUtils, BindingList, ControlProcessor, _Constants, _Command, _CommandingSurfaceMenuCommand, _Control, _Dispose, _ElementUtilities, _ErrorFromName, _Events, _Flyout, _Global, _Hoverable, _KeyboardBehavior, _Log, Promise, _Resources, Scheduler, _OpenCloseMachine, _Signal, _WriteProfilerMark) { + require(["require-style!less/styles-commandingsurface"]); + require(["require-style!less/colors-commandingsurface"]); + "use strict"; + var strings = { + get overflowButtonAriaLabel() { + return _Resources._getWinJSString("ui/commandingSurfaceOverflowButtonAriaLabel").value; + }, + get badData() { + return "Invalid argument: The data property must an instance of a WinJS.Binding.List"; + }, + get mustContainCommands() { + return "The commandingSurface can only contain WinJS.UI.Command or WinJS.UI.AppBarCommand controls"; + }, + get duplicateConstruction() { + return "Invalid argument: Controls may only be instantiated one time for each DOM element"; + } + }; + var CommandLayoutPipeline = { + newDataStage: 3, + measuringStage: 2, + layoutStage: 1, + idle: 0, + }; + var OverflowDirection = { + /// The _CommandingSurface expands towards the bottom of the screen when opened and the overflow area renders below the actionarea. + bottom: "bottom", + /// The _CommandingSurface expands towards the top of the screen when opened and the overflow area renders above the actionarea. + top: "top", + }; + var overflowDirectionClassMap = {}; + overflowDirectionClassMap[OverflowDirection.top] = _Constants.ClassNames.overflowTopClass; + overflowDirectionClassMap[OverflowDirection.bottom] = _Constants.ClassNames.overflowBottomClass; + var ClosedDisplayMode = { + /// When the _CommandingSurface is closed, the actionarea is not visible and doesn't take up any space. + none: "none", + /// When the _CommandingSurface is closed, the height of the actionarea is reduced to the minimal height required to display only the actionarea overflowbutton. All other content in the actionarea is not displayed. + minimal: "minimal", + /// When the _CommandingSurface is closed, the height of the actionarea is reduced such that button commands are still visible, but their labels are hidden. + compact: "compact", + /// When the _CommandingSurface is closed, the height of the actionarea is always sized to content and does not change between opened and closed states. + full: "full", + }; + var closedDisplayModeClassMap = {}; + closedDisplayModeClassMap[ClosedDisplayMode.none] = _Constants.ClassNames.noneClass; + closedDisplayModeClassMap[ClosedDisplayMode.minimal] = _Constants.ClassNames.minimalClass; + closedDisplayModeClassMap[ClosedDisplayMode.compact] = _Constants.ClassNames.compactClass; + closedDisplayModeClassMap[ClosedDisplayMode.full] = _Constants.ClassNames.fullClass; + // Versions of add/removeClass that are no ops when called with falsy class names. + function addClass(element, className) { + className && _ElementUtilities.addClass(element, className); + } + function removeClass(element, className) { + className && _ElementUtilities.removeClass(element, className); + } + function diffElements(lhs, rhs) { + // Subtract array rhs from array lhs. + // Returns a new Array containing the subset of elements in lhs that are not also in rhs. + return lhs.filter(function (commandElement) { + return rhs.indexOf(commandElement) < 0; + }); + } + /// Represents an apaptive surface for displaying commands. + var _CommandingSurface = (function () { + function _CommandingSurface(element, options) { + /// Creates a new CommandingSurface control. + /// @param element: The DOM element that will host the control. + /// @param options: The set of properties and values to apply to the new CommandingSurface control. + /// @return: The new CommandingSurface control. + var _this = this; + if (options === void 0) { options = {}; } + this._hoverable = _Hoverable.isHoverable; /* force dependency on hoverable module */ + this._dataChangedEvents = ["itemchanged", "iteminserted", "itemmoved", "itemremoved", "reload"]; + // State private to _updateDomImpl_renderDisplayMode. No other method should make use of it. + // + // Nothing has been rendered yet so these are all initialized to undefined. Because + // they are undefined, the first time _updateDomImpl is called, they will all be + // rendered. + this._updateDomImpl_renderedState = { + closedDisplayMode: undefined, + isOpenedMode: undefined, + overflowDirection: undefined, + overflowAlignmentOffset: undefined, + }; + this._writeProfilerMark("constructor,StartTM"); + // Check to make sure we weren't duplicated + if (element && element["winControl"]) { + throw new _ErrorFromName("WinJS.UI._CommandingSurface.DuplicateConstruction", strings.duplicateConstruction); + } + this._initializeDom(element || _Global.document.createElement("div")); + this._machine = options.openCloseMachine || new _OpenCloseMachine.OpenCloseMachine({ + eventElement: this._dom.root, + onOpen: function () { + _this.synchronousOpen(); + return Promise.wrap(); + }, + onClose: function () { + _this.synchronousClose(); + return Promise.wrap(); + }, + onUpdateDom: function () { + _this.updateDomImpl(); + }, + onUpdateDomWithIsOpened: function (isOpened) { + if (isOpened) { + _this.synchronousOpen(); + } + else { + _this.synchronousClose(); + } + } + }); + // Initialize private state. + this._disposed = false; + this._primaryCommands = []; + this._secondaryCommands = []; + this._refreshBound = this._refresh.bind(this); + this._resizeHandlerBound = this._resizeHandler.bind(this); + this._winKeyboard = new _KeyboardBehavior._WinKeyboard(this._dom.root); + this._refreshPending = false; + this._rtl = false; + this._initializedSignal = new _Signal(); + this._nextLayoutStage = CommandLayoutPipeline.idle; + this._isOpenedMode = _Constants.defaultOpened; + this._menuCommandProjections = []; + // Initialize public properties. + this.overflowDirection = _Constants.defaultOverflowDirection; + this.closedDisplayMode = _Constants.defaultClosedDisplayMode; + this.opened = this._isOpenedMode; + if (!options.data) { + // Shallow copy object so we can modify it. + options = _BaseUtils._shallowCopy(options); + // Set default data + options.data = options.data || this._getDataFromDOMElements(); + } + _Control.setOptions(this, options); + // Event handlers + _ElementUtilities._resizeNotifier.subscribe(this._dom.root, this._resizeHandlerBound); + this._dom.root.addEventListener('keydown', this._keyDownHandler.bind(this)); + // Exit the Init state. + _ElementUtilities._inDom(this._dom.root).then(function () { + _this._rtl = _Global.getComputedStyle(_this._dom.root).direction === 'rtl'; + if (!options.openCloseMachine) { + // We should only call exitInit on the machine when we own the machine. + _this._machine.exitInit(); + } + _this._initializedSignal.complete(); + _this._writeProfilerMark("constructor,StopTM"); + }); + } + Object.defineProperty(_CommandingSurface.prototype, "element", { + /// Gets the DOM element that hosts the CommandingSurface. + get: function () { + return this._dom.root; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(_CommandingSurface.prototype, "data", { + /// Gets or sets the Binding List of WinJS.UI.Command for the CommandingSurface. + get: function () { + return this._data; + }, + set: function (value) { + this._writeProfilerMark("set_data,info"); + if (value !== this.data) { + if (!(value instanceof BindingList.List)) { + throw new _ErrorFromName("WinJS.UI._CommandingSurface.BadData", strings.badData); + } + if (this._data) { + this._removeDataListeners(); + } + this._data = value; + this._addDataListeners(); + this._dataUpdated(); + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(_CommandingSurface.prototype, "closedDisplayMode", { + /// Gets or sets the closedDisplayMode for the CommandingSurface. Values are "none", "minimal", "compact", and "full". + get: function () { + return this._closedDisplayMode; + }, + set: function (value) { + this._writeProfilerMark("set_closedDisplayMode,info"); + var isChangingState = (value !== this._closedDisplayMode); + if (ClosedDisplayMode[value] && isChangingState) { + this._closedDisplayMode = value; + this._machine.updateDom(); + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(_CommandingSurface.prototype, "overflowDirection", { + /// Gets or sets which direction the commandingSurface overflows when opened. Values are "top" and "bottom" for. + get: function () { + return this._overflowDirection; + }, + set: function (value) { + var isChangingState = (value !== this._overflowDirection); + if (OverflowDirection[value] && isChangingState) { + this._overflowDirection = value; + this._machine.updateDom(); + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(_CommandingSurface.prototype, "opened", { + /// Gets or sets whether the _CommandingSurface is currently opened. + get: function () { + return this._machine.opened; + }, + set: function (value) { + this._machine.opened = value; + }, + enumerable: true, + configurable: true + }); + _CommandingSurface.prototype.open = function () { + /// Opens the _CommandingSurface's actionarea and overflowarea + this._machine.open(); + }; + _CommandingSurface.prototype.close = function () { + /// Closes the _CommandingSurface's actionarea and overflowarea + this._machine.close(); + }; + _CommandingSurface.prototype.dispose = function () { + /// Disposes this CommandingSurface. + if (this._disposed) { + return; + } + this._disposed = true; + this._machine.dispose(); + _ElementUtilities._resizeNotifier.unsubscribe(this._dom.root, this._resizeHandlerBound); + if (this._contentFlyout) { + this._contentFlyout.dispose(); + this._contentFlyout.element.parentNode.removeChild(this._contentFlyout.element); + } + _Dispose.disposeSubTree(this._dom.root); + }; + _CommandingSurface.prototype.forceLayout = function () { + /// Forces the CommandingSurface to update its layout. Use this function when the window did not change + /// size, but the container of the CommandingSurface changed size. + this._meaurementsDirty(); + this._machine.updateDom(); + }; + _CommandingSurface.prototype.getBoundingRects = function () { + return { + commandingSurface: this._dom.root.getBoundingClientRect(), + overflowArea: this._dom.overflowArea.getBoundingClientRect(), + }; + }; + _CommandingSurface.prototype.getCommandById = function (id) { + if (this._data) { + for (var i = 0, len = this._data.length; i < len; i++) { + var command = this._data.getAt(i); + if (command.id === id) { + return command; + } + } + } + return null; + }; + _CommandingSurface.prototype.showOnlyCommands = function (commands) { + if (this._data) { + for (var i = 0, len = this._data.length; i < len; i++) { + this._data.getAt(i).hidden = true; + } + for (var i = 0, len = commands.length; i < len; i++) { + // The array passed to showOnlyCommands can contain either command ids, or the commands themselves. + var command = (typeof commands[i] === "string" ? this.getCommandById(commands[i]) : commands[i]); + if (command) { + command.hidden = false; + } + } + } + }; + _CommandingSurface.prototype.deferredDomUpate = function () { + // Notify the machine that an update has been requested. + this._machine.updateDom(); + }; + _CommandingSurface.prototype.createOpenAnimation = function (closedHeight) { + // createOpenAnimation should only be called when the commanding surface is in a closed state. The control using the commanding surface is expected + // to call createOpenAnimation() before it opens the surface, then open the commanding surface, then call .execute() to start the animation. + // This function is overridden by our unit tests. + if (_Log.log) { + this._updateDomImpl_renderedState.isOpenedMode && _Log.log("The CommandingSurface should only attempt to create an open animation when it's not already opened"); + } + var that = this; + return { + execute: function () { + var boundingRects = that.getBoundingRects(); + // The overflowAreaContainer has no size by default. Measure the overflowArea's size and apply it to the overflowAreaContainer before animating + that._dom.overflowAreaContainer.style.width = boundingRects.overflowArea.width + "px"; + that._dom.overflowAreaContainer.style.height = boundingRects.overflowArea.height + "px"; + return Animations._commandingSurfaceOpenAnimation({ + actionAreaClipper: that._dom.actionAreaContainer, + actionArea: that._dom.actionArea, + overflowAreaClipper: that._dom.overflowAreaContainer, + overflowArea: that._dom.overflowArea, + oldHeight: closedHeight, + newHeight: boundingRects.commandingSurface.height, + overflowAreaHeight: boundingRects.overflowArea.height, + menuPositionedAbove: (that.overflowDirection === OverflowDirection.top), + }).then(function () { + that._clearAnimation(); + }); + } + }; + }; + _CommandingSurface.prototype.createCloseAnimation = function (closedHeight) { + // createCloseAnimation should only be called when the commanding surface is in an opened state. The control using the commanding surface is expected + // to call createCloseAnimation() before it closes the surface, then call execute() to let the animation run. Once the animation finishes, the control + // should close the commanding surface. + // This function is overridden by our unit tests. + if (_Log.log) { + !this._updateDomImpl_renderedState.isOpenedMode && _Log.log("The CommandingSurface should only attempt to create an closed animation when it's not already closed"); + } + var openedHeight = this.getBoundingRects().commandingSurface.height, overflowAreaOpenedHeight = this._dom.overflowArea.offsetHeight, oldOverflowTop = this._dom.overflowArea.offsetTop, that = this; + return { + execute: function () { + _ElementUtilities.addClass(that.element, _Constants.ClassNames.closingClass); + return Animations._commandingSurfaceCloseAnimation({ + actionAreaClipper: that._dom.actionAreaContainer, + actionArea: that._dom.actionArea, + overflowAreaClipper: that._dom.overflowAreaContainer, + overflowArea: that._dom.overflowArea, + oldHeight: openedHeight, + newHeight: closedHeight, + overflowAreaHeight: overflowAreaOpenedHeight, + menuPositionedAbove: (that.overflowDirection === OverflowDirection.top), + }).then(function () { + _ElementUtilities.removeClass(that.element, _Constants.ClassNames.closingClass); + that._clearAnimation(); + }); + } + }; + }; + Object.defineProperty(_CommandingSurface.prototype, "initialized", { + get: function () { + return this._initializedSignal.promise; + }, + enumerable: true, + configurable: true + }); + _CommandingSurface.prototype._writeProfilerMark = function (text) { + _WriteProfilerMark("WinJS.UI._CommandingSurface:" + this._id + ":" + text); + }; + _CommandingSurface.prototype._initializeDom = function (root) { + var _this = this; + this._writeProfilerMark("_intializeDom,info"); + // Attaching JS control to DOM element + root["winControl"] = this; + this._id = root.id || _ElementUtilities._uniqueID(root); + if (!root.hasAttribute("tabIndex")) { + root.tabIndex = -1; + } + _ElementUtilities.addClass(root, _Constants.ClassNames.controlCssClass); + _ElementUtilities.addClass(root, _Constants.ClassNames.disposableCssClass); + var actionArea = _Global.document.createElement("div"); + _ElementUtilities.addClass(actionArea, _Constants.ClassNames.actionAreaCssClass); + _ElementUtilities._reparentChildren(root, actionArea); + var actionAreaContainer = _Global.document.createElement("div"); + _ElementUtilities.addClass(actionAreaContainer, _Constants.ClassNames.actionAreaContainerCssClass); + actionAreaContainer.appendChild(actionArea); + root.appendChild(actionAreaContainer); + var spacer = _Global.document.createElement("div"); + _ElementUtilities.addClass(spacer, _Constants.ClassNames.spacerCssClass); + actionArea.appendChild(spacer); + var overflowButton = _Global.document.createElement("button"); + overflowButton.tabIndex = 0; + overflowButton.innerHTML = ""; + _ElementUtilities.addClass(overflowButton, _Constants.ClassNames.overflowButtonCssClass); + actionArea.appendChild(overflowButton); + overflowButton.addEventListener("click", function () { + _this.opened = !_this.opened; + }); + var overflowArea = _Global.document.createElement("div"); + _ElementUtilities.addClass(overflowArea, _Constants.ClassNames.overflowAreaCssClass); + _ElementUtilities.addClass(overflowArea, _Constants.ClassNames.menuCssClass); + var overflowAreaContainer = _Global.document.createElement("div"); + _ElementUtilities.addClass(overflowAreaContainer, _Constants.ClassNames.overflowAreaContainerCssClass); + overflowAreaContainer.appendChild(overflowArea); + root.appendChild(overflowAreaContainer); + this._dom = { + root: root, + actionArea: actionArea, + actionAreaContainer: actionAreaContainer, + spacer: spacer, + overflowButton: overflowButton, + overflowArea: overflowArea, + overflowAreaContainer: overflowAreaContainer + }; + }; + _CommandingSurface.prototype._getFocusableElementsInfo = function () { + var _this = this; + var focusableCommandsInfo = { + elements: [], + focusedIndex: -1 + }; + var elementsInReach = Array.prototype.slice.call(this._dom.actionArea.children); + var elementsInReach = Array.prototype.slice.call(this._dom.actionArea.children); + if (this._dom.overflowArea.style.display !== "none") { + elementsInReach = elementsInReach.concat(Array.prototype.slice.call(this._dom.overflowArea.children)); + } + elementsInReach.forEach(function (element) { + if (_this._isElementFocusable(element)) { + focusableCommandsInfo.elements.push(element); + if (element.contains(_Global.document.activeElement)) { + focusableCommandsInfo.focusedIndex = focusableCommandsInfo.elements.length - 1; + } + } + }); + return focusableCommandsInfo; + }; + _CommandingSurface.prototype._dataUpdated = function () { + var _this = this; + this._primaryCommands = []; + this._secondaryCommands = []; + if (this.data.length > 0) { + this.data.forEach(function (command) { + if (command.section === "secondary") { + _this._secondaryCommands.push(command); + } + else { + _this._primaryCommands.push(command); + } + }); + } + this._dataDirty(); + this._machine.updateDom(); + }; + _CommandingSurface.prototype._refresh = function () { + var _this = this; + if (!this._refreshPending) { + this._refreshPending = true; + // Batch calls to _dataUpdated + Scheduler.schedule(function () { + if (_this._refreshPending && !_this._disposed) { + _this._refreshPending = false; + _this._dataUpdated(); + } + }, Scheduler.Priority.high, null, "WinJS.UI._CommandingSurface._refresh"); + } + }; + _CommandingSurface.prototype._addDataListeners = function () { + var _this = this; + this._dataChangedEvents.forEach(function (eventName) { + _this._data.addEventListener(eventName, _this._refreshBound, false); + }); + }; + _CommandingSurface.prototype._removeDataListeners = function () { + var _this = this; + this._dataChangedEvents.forEach(function (eventName) { + _this._data.removeEventListener(eventName, _this._refreshBound, false); + }); + }; + _CommandingSurface.prototype._isElementFocusable = function (element) { + var focusable = false; + if (element) { + var command = element["winControl"]; + if (command) { + focusable = command.element.style.display !== "none" && command.type !== _Constants.typeSeparator && !command.hidden && !command.disabled && (!command.firstElementFocus || command.firstElementFocus.tabIndex >= 0 || command.lastElementFocus.tabIndex >= 0); + } + else { + // e.g. the overflow button + focusable = element.style.display !== "none" && getComputedStyle(element).visibility !== "hidden" && element.tabIndex >= 0; + } + } + return focusable; + }; + _CommandingSurface.prototype._isCommandInActionArea = function (element) { + // Returns true if the element is a command in the actionarea, false otherwise + return element && element["winControl"] && element.parentElement === this._dom.actionArea; + }; + _CommandingSurface.prototype._getLastElementFocus = function (element) { + if (this._isCommandInActionArea(element)) { + // Only commands in the actionarea support lastElementFocus + return element["winControl"].lastElementFocus; + } + else { + return element; + } + }; + _CommandingSurface.prototype._getFirstElementFocus = function (element) { + if (this._isCommandInActionArea(element)) { + // Only commands in the actionarea support firstElementFocus + return element["winControl"].firstElementFocus; + } + else { + return element; + } + }; + _CommandingSurface.prototype._keyDownHandler = function (ev) { + if (!ev.altKey) { + if (_ElementUtilities._matchesSelector(ev.target, ".win-interactive, .win-interactive *")) { + return; + } + var Key = _ElementUtilities.Key; + var focusableElementsInfo = this._getFocusableElementsInfo(); + var targetCommand; + if (focusableElementsInfo.elements.length) { + switch (ev.keyCode) { + case (this._rtl ? Key.rightArrow : Key.leftArrow): + case Key.upArrow: + var index = Math.max(0, focusableElementsInfo.focusedIndex - 1); + targetCommand = this._getLastElementFocus(focusableElementsInfo.elements[index % focusableElementsInfo.elements.length]); + break; + case (this._rtl ? Key.leftArrow : Key.rightArrow): + case Key.downArrow: + var index = Math.min(focusableElementsInfo.focusedIndex + 1, focusableElementsInfo.elements.length - 1); + targetCommand = this._getFirstElementFocus(focusableElementsInfo.elements[index]); + break; + case Key.home: + var index = 0; + targetCommand = this._getFirstElementFocus(focusableElementsInfo.elements[index]); + break; + case Key.end: + var index = focusableElementsInfo.elements.length - 1; + targetCommand = this._getLastElementFocus(focusableElementsInfo.elements[index]); + break; + } + } + if (targetCommand && targetCommand !== _Global.document.activeElement) { + targetCommand.focus(); + ev.preventDefault(); + } + } + }; + _CommandingSurface.prototype._getDataFromDOMElements = function () { + this._writeProfilerMark("_getDataFromDOMElements,info"); + ControlProcessor.processAll(this._dom.actionArea, true); + var commands = []; + var childrenLength = this._dom.actionArea.children.length; + var child; + for (var i = 0; i < childrenLength; i++) { + child = this._dom.actionArea.children[i]; + if (child["winControl"] && child["winControl"] instanceof _Command.AppBarCommand) { + commands.push(child["winControl"]); + } + else if (child !== this._dom.overflowButton && child !== this._dom.spacer) { + throw new _ErrorFromName("WinJS.UI._CommandingSurface.MustContainCommands", strings.mustContainCommands); + } + } + return new BindingList.List(commands); + }; + _CommandingSurface.prototype._resizeHandler = function () { + if (this._dom.root.offsetWidth) { + var currentActionAreaWidth = _ElementUtilities._getPreciseContentWidth(this._dom.actionArea); + if (this._cachedMeasurements && this._cachedMeasurements.actionAreaContentBoxWidth !== currentActionAreaWidth) { + this._cachedMeasurements.actionAreaContentBoxWidth = currentActionAreaWidth; + this._layoutDirty(); + this._machine.updateDom(); + } + } + }; + _CommandingSurface.prototype._dataDirty = function () { + this._nextLayoutStage = Math.max(CommandLayoutPipeline.newDataStage, this._nextLayoutStage); + }; + _CommandingSurface.prototype._meaurementsDirty = function () { + this._nextLayoutStage = Math.max(CommandLayoutPipeline.measuringStage, this._nextLayoutStage); + }; + _CommandingSurface.prototype._layoutDirty = function () { + this._nextLayoutStage = Math.max(CommandLayoutPipeline.layoutStage, this._nextLayoutStage); + }; + _CommandingSurface.prototype.synchronousOpen = function () { + this._overflowAlignmentOffset = 0; + this._isOpenedMode = true; + this.updateDomImpl(); + this._overflowAlignmentOffset = this._computeAdjustedOverflowAreaOffset(); + this.updateDomImpl(); + }; + _CommandingSurface.prototype._computeAdjustedOverflowAreaOffset = function () { + // Returns any negative offset needed to prevent the shown overflowarea from clipping outside of the viewport. + // This function should only be called when CommandingSurface has been rendered in the opened state with + // an overflowAlignmentOffset of 0. + if (_Log.log) { + !this._updateDomImpl_renderedState.isOpenedMode && _Log.log("The CommandingSurface should only attempt to compute adjusted overflowArea offset " + " when it has been rendered opened"); + this._updateDomImpl_renderedState.overflowAlignmentOffset !== 0 && _Log.log("The CommandingSurface should only attempt to compute adjusted overflowArea offset " + " when it has been rendered with an overflowAlignementOffset of 0"); + } + var overflowArea = this._dom.overflowArea, boundingClientRects = this.getBoundingRects(), adjustedOffset = 0; + if (this._rtl) { + // In RTL the left edge of overflowarea prefers to align to the LEFT edge of the commandingSurface. + // Make sure we avoid clipping through the RIGHT edge of the viewport + var viewportRight = window.innerWidth, rightOffsetFromViewport = boundingClientRects.overflowArea.right; + adjustedOffset = Math.min(viewportRight - rightOffsetFromViewport, 0); + } + else { + // In LTR the right edge of overflowarea prefers to align to the RIGHT edge of the commandingSurface. + // Make sure we avoid clipping through the LEFT edge of the viewport. + var leftOffsetFromViewport = boundingClientRects.overflowArea.left; + adjustedOffset = Math.min(0, leftOffsetFromViewport); + } + return adjustedOffset; + }; + _CommandingSurface.prototype.synchronousClose = function () { + this._isOpenedMode = false; + this.updateDomImpl(); + }; + _CommandingSurface.prototype.updateDomImpl = function () { + this._updateDomImpl_renderDisplayMode(); + this._updateDomImpl_updateCommands(); + }; + _CommandingSurface.prototype._updateDomImpl_renderDisplayMode = function () { + var rendered = this._updateDomImpl_renderedState; + if (rendered.isOpenedMode !== this._isOpenedMode) { + if (this._isOpenedMode) { + // Render opened + removeClass(this._dom.root, _Constants.ClassNames.closedClass); + addClass(this._dom.root, _Constants.ClassNames.openedClass); + } + else { + // Render closed + removeClass(this._dom.root, _Constants.ClassNames.openedClass); + addClass(this._dom.root, _Constants.ClassNames.closedClass); + } + rendered.isOpenedMode = this._isOpenedMode; + } + if (rendered.closedDisplayMode !== this.closedDisplayMode) { + removeClass(this._dom.root, closedDisplayModeClassMap[rendered.closedDisplayMode]); + addClass(this._dom.root, closedDisplayModeClassMap[this.closedDisplayMode]); + rendered.closedDisplayMode = this.closedDisplayMode; + } + if (rendered.overflowDirection !== this.overflowDirection) { + removeClass(this._dom.root, overflowDirectionClassMap[rendered.overflowDirection]); + addClass(this._dom.root, overflowDirectionClassMap[this.overflowDirection]); + rendered.overflowDirection = this.overflowDirection; + } + if (this._overflowAlignmentOffset !== rendered.overflowAlignmentOffset) { + var offsetProperty = (this._rtl ? "left" : "right"); + var offsetTextValue = this._overflowAlignmentOffset + "px"; + this._dom.overflowAreaContainer.style[offsetProperty] = offsetTextValue; + } + }; + _CommandingSurface.prototype._updateDomImpl_updateCommands = function () { + this._writeProfilerMark("_updateDomImpl_updateCommands,info"); + var nextStage = this._nextLayoutStage; + while (nextStage !== CommandLayoutPipeline.idle) { + var currentStage = nextStage; + var okToProceed = false; + switch (currentStage) { + case CommandLayoutPipeline.newDataStage: + nextStage = CommandLayoutPipeline.measuringStage; + okToProceed = this._processNewData(); + break; + case CommandLayoutPipeline.measuringStage: + nextStage = CommandLayoutPipeline.layoutStage; + okToProceed = this._measure(); + break; + case CommandLayoutPipeline.layoutStage: + nextStage = CommandLayoutPipeline.idle; + okToProceed = this._layoutCommands(); + break; + } + if (!okToProceed) { + // If a stage fails, exit the loop and track that stage + // to be restarted the next time _updateCommands is run. + nextStage = currentStage; + break; + } + } + this._nextLayoutStage = nextStage; + if (nextStage === CommandLayoutPipeline.idle) { + // Callback for unit tests. + this._layoutCompleteCallback && this._layoutCompleteCallback(); + } + }; + _CommandingSurface.prototype._getDataChangeInfo = function () { + var i = 0, len = 0; + var added = []; + var deleted = []; + var affected = []; + var currentShown = []; + var currentElements = []; + var newShown = []; + var newHidden = []; + var newElements = []; + Array.prototype.forEach.call(this._dom.actionArea.querySelectorAll(_Constants.commandSelector), function (commandElement) { + if (commandElement.style.display !== "none") { + currentShown.push(commandElement); + } + currentElements.push(commandElement); + }); + this.data.forEach(function (command) { + if (command.element.style.display !== "none") { + newShown.push(command.element); + } + else { + newHidden.push(command.element); + } + newElements.push(command.element); + }); + deleted = diffElements(currentShown, newShown); + affected = diffElements(currentShown, deleted); + // "added" must also include the elements from "newHidden" to ensure that we continue + // to animate any command elements that have underflowed back into the actionarea + // as a part of this data change. + added = diffElements(newShown, currentShown).concat(newHidden); + return { + newElements: newElements, + currentElements: currentElements, + added: added, + deleted: deleted, + affected: affected, + }; + }; + _CommandingSurface.prototype._processNewData = function () { + var _this = this; + this._writeProfilerMark("_processNewData,info"); + var changeInfo = this._getDataChangeInfo(); + // Take a snapshot of the current state + var updateCommandAnimation = Animations._createUpdateListAnimation(changeInfo.added, changeInfo.deleted, changeInfo.affected); + // Unbind property mutation event listener from deleted IObservableCommands + changeInfo.deleted.forEach(function (deletedElement) { + var command = (deletedElement['winControl']); + if (command && command['_propertyMutations']) { + command._propertyMutations.unbind(_this._refreshBound); + } + }); + // Bind property mutation event listener to added IObservable commands. + changeInfo.added.forEach(function (deletedElement) { + var command = (deletedElement['winControl']); + if (command && command['_propertyMutations']) { + command._propertyMutations.bind(_this._refreshBound); + } + }); + // Remove current ICommand elements + changeInfo.currentElements.forEach(function (element) { + if (element.parentElement) { + element.parentElement.removeChild(element); + } + }); + // Add new ICommand elements in the right order. + changeInfo.newElements.forEach(function (element) { + _this._dom.actionArea.appendChild(element); + }); + // Ensure that the overflow button is always the last element in the actionarea + this._dom.actionArea.appendChild(this._dom.overflowButton); + if (this.data.length > 0) { + _ElementUtilities.removeClass(this._dom.root, _Constants.ClassNames.emptyCommandingSurfaceCssClass); + } + else { + _ElementUtilities.addClass(this._dom.root, _Constants.ClassNames.emptyCommandingSurfaceCssClass); + } + // Execute the animation. + updateCommandAnimation.execute(); + // Indicate processing was successful. + return true; + }; + _CommandingSurface.prototype._measure = function () { + var _this = this; + this._writeProfilerMark("_measure,info"); + var canMeasure = (_Global.document.body.contains(this._dom.root) && this._dom.actionArea.offsetWidth > 0); + if (canMeasure) { + var overflowButtonWidth = _ElementUtilities._getPreciseTotalWidth(this._dom.overflowButton), actionAreaContentBoxWidth = _ElementUtilities._getPreciseContentWidth(this._dom.actionArea), separatorWidth = 0, standardCommandWidth = 0, contentCommandWidths = {}; + this._primaryCommands.forEach(function (command) { + // Ensure that the element we are measuring does not have display: none (e.g. it was just added, and it + // will be animated in) + var originalDisplayStyle = command.element.style.display; + command.element.style.display = ""; + if (command.type === _Constants.typeContent) { + // Measure each 'content' command type that we find + contentCommandWidths[_this._commandUniqueId(command)] = _ElementUtilities._getPreciseTotalWidth(command.element); + } + else if (command.type === _Constants.typeSeparator) { + // Measure the first 'separator' command type we find. + if (!separatorWidth) { + separatorWidth = _ElementUtilities._getPreciseTotalWidth(command.element); + } + } + else { + // Button, toggle, 'flyout' command types have the same width. Measure the first one we find. + if (!standardCommandWidth) { + standardCommandWidth = _ElementUtilities._getPreciseTotalWidth(command.element); + } + } + // Restore the original display style + command.element.style.display = originalDisplayStyle; + }); + this._cachedMeasurements = { + contentCommandWidths: contentCommandWidths, + separatorWidth: separatorWidth, + standardCommandWidth: standardCommandWidth, + overflowButtonWidth: overflowButtonWidth, + actionAreaContentBoxWidth: actionAreaContentBoxWidth, + }; + // Indicate measure was successful + return true; + } + else { + // Indicate measure was unsuccessful + return false; + } + }; + _CommandingSurface.prototype._layoutCommands = function () { + var _this = this; + this._writeProfilerMark("_layoutCommands,StartTM"); + // + // Filter commands that will not be visible in the actionarea + // + this._primaryCommands.forEach(function (command) { + command.element.style.display = (command.hidden ? "none" : ""); + }); + var primaryCommandsLocation = this._getVisiblePrimaryCommandsLocation(); + this._hideSeparatorsIfNeeded(primaryCommandsLocation.actionArea); + // Primary commands that will be mirrored in the overflow area should be hidden so + // that they are not visible in the actionarea. + primaryCommandsLocation.overflowArea.forEach(function (command) { + command.element.style.display = "none"; + }); + // The secondary commands in the actionarea should be hidden since they are always + // mirrored as new elements in the overflow area. + this._secondaryCommands.forEach(function (command) { + command.element.style.display = "none"; + }); + var overflowCommands = primaryCommandsLocation.overflowArea; + var showOverflowButton = (overflowCommands.length > 0 || this._secondaryCommands.length > 0); + this._dom.overflowButton.style.display = showOverflowButton ? "" : "none"; + // Set up a custom content flyout if there will be "content" typed commands in the overflowarea. + var isCustomContent = function (command) { + return command.type === _Constants.typeContent; + }; + var hasCustomContent = overflowCommands.some(isCustomContent) || this._secondaryCommands.some(isCustomContent); + if (hasCustomContent && !this._contentFlyout) { + this._contentFlyoutInterior = _Global.document.createElement("div"); + _ElementUtilities.addClass(this._contentFlyoutInterior, _Constants.ClassNames.contentFlyoutCssClass); + this._contentFlyout = new _Flyout.Flyout(); + this._contentFlyout.element.appendChild(this._contentFlyoutInterior); + _Global.document.body.appendChild(this._contentFlyout.element); + this._contentFlyout.onbeforeshow = function () { + _ElementUtilities.empty(_this._contentFlyoutInterior); + _ElementUtilities._reparentChildren(_this._chosenCommand.element, _this._contentFlyoutInterior); + }; + this._contentFlyout.onafterhide = function () { + _ElementUtilities._reparentChildren(_this._contentFlyoutInterior, _this._chosenCommand.element); + }; + } + // + // Project overflowing and secondary commands into the overflowArea as MenuCommands + // + // Clean up previous MenuCommand projections + _ElementUtilities.empty(this._dom.overflowArea); + this._menuCommandProjections.map(function (menuCommand) { + if (_this._contentFlyout && menuCommand.flyout === _this._contentFlyout) { + // Prevent our _contentFlyout from being disposed with the MenuCommand. + menuCommand.flyout = null; + } + menuCommand.dispose(); + }); + var hasToggleCommands = false, menuCommandProjections = []; + // Add primary commands that have overflowed. + overflowCommands.forEach(function (command) { + if (command.type === _Constants.typeToggle) { + hasToggleCommands = true; + } + menuCommandProjections.push(_this._projectAsMenuCommand(command)); + }); + // Add separator between primary and secondary command if applicable + var secondaryCommandsLength = this._secondaryCommands.length; + if (overflowCommands.length > 0 && secondaryCommandsLength > 0) { + var separator = new _CommandingSurfaceMenuCommand._MenuCommand(null, { + type: _Constants.typeSeparator + }); + menuCommandProjections.push(separator); + } + // Add secondary commands + this._secondaryCommands.forEach(function (command) { + if (!command.hidden) { + if (command.type === _Constants.typeToggle) { + hasToggleCommands = true; + } + menuCommandProjections.push(_this._projectAsMenuCommand(command)); + } + }); + this._hideSeparatorsIfNeeded(menuCommandProjections); + menuCommandProjections.forEach(function (command) { + _this._dom.overflowArea.appendChild(command.element); + }); + this._menuCommandProjections = menuCommandProjections; + _ElementUtilities[hasToggleCommands ? "addClass" : "removeClass"](this._dom.overflowArea, _Constants.ClassNames.menuContainsToggleCommandClass); + this._writeProfilerMark("_layoutCommands,StopTM"); + // Indicate layout was successful. + return true; + }; + _CommandingSurface.prototype._commandUniqueId = function (command) { + return _ElementUtilities._uniqueID(command.element); + }; + _CommandingSurface.prototype._getVisiblePrimaryCommandsInfo = function () { + var width = 0; + var commands = []; + var priority = 0; + var currentAssignedPriority = 0; + for (var i = this._primaryCommands.length - 1; i >= 0; i--) { + var command = this._primaryCommands[i]; + if (!command.hidden) { + if (command.priority === undefined) { + priority = currentAssignedPriority--; + } + else { + priority = command.priority; + } + width = (command.element.style.display === "none" ? 0 : this._getCommandWidth(command)); + commands.unshift({ + command: command, + width: width, + priority: priority + }); + } + } + return commands; + }; + _CommandingSurface.prototype._getVisiblePrimaryCommandsLocation = function () { + this._writeProfilerMark("_getVisiblePrimaryCommandsLocation,info"); + var actionAreaCommands = []; + var overflowAreaCommands = []; + var overflowButtonSpace = 0; + var hasSecondaryCommands = this._secondaryCommands.length > 0; + var commandsInfo = this._getVisiblePrimaryCommandsInfo(); + var sortedCommandsInfo = commandsInfo.slice(0).sort(function (commandInfo1, commandInfo2) { + return commandInfo1.priority - commandInfo2.priority; + }); + var maxPriority = Number.MAX_VALUE; + var availableWidth = this._cachedMeasurements.actionAreaContentBoxWidth; + for (var i = 0, len = sortedCommandsInfo.length; i < len; i++) { + availableWidth -= sortedCommandsInfo[i].width; + // The overflow button needs space if there are secondary commands, or we are not evaluating the last command. + overflowButtonSpace = (hasSecondaryCommands || (i < len - 1) ? this._cachedMeasurements.overflowButtonWidth : 0); + if (availableWidth - overflowButtonSpace < 0) { + maxPriority = sortedCommandsInfo[i].priority - 1; + break; + } + } + commandsInfo.forEach(function (commandInfo) { + if (commandInfo.priority <= maxPriority) { + actionAreaCommands.push(commandInfo.command); + } + else { + overflowAreaCommands.push(commandInfo.command); + } + }); + return { + actionArea: actionAreaCommands, + overflowArea: overflowAreaCommands + }; + }; + _CommandingSurface.prototype._getCommandWidth = function (command) { + if (command.type === _Constants.typeContent) { + return this._cachedMeasurements.contentCommandWidths[this._commandUniqueId(command)]; + } + else if (command.type === _Constants.typeSeparator) { + return this._cachedMeasurements.separatorWidth; + } + else { + return this._cachedMeasurements.standardCommandWidth; + } + }; + _CommandingSurface.prototype._projectAsMenuCommand = function (originalCommand) { + var _this = this; + var menuCommand = new _CommandingSurfaceMenuCommand._MenuCommand(null, { + label: originalCommand.label, + type: (originalCommand.type === _Constants.typeContent ? _Constants.typeFlyout : originalCommand.type) || _Constants.typeButton, + disabled: originalCommand.disabled, + flyout: originalCommand.flyout, + beforeInvoke: function () { + // Save the command that was selected + _this._chosenCommand = (menuCommand["_originalICommand"]); + // If this WinJS.UI.MenuCommand has type: toggle, we should also toggle the value of the original WinJS.UI.Command + if (_this._chosenCommand.type === _Constants.typeToggle) { + _this._chosenCommand.selected = !_this._chosenCommand.selected; + } + } + }); + if (originalCommand.selected) { + menuCommand.selected = true; + } + if (originalCommand.extraClass) { + menuCommand.extraClass = originalCommand.extraClass; + } + if (originalCommand.type === _Constants.typeContent) { + if (!menuCommand.label) { + menuCommand.label = _Constants.contentMenuCommandDefaultLabel; + } + menuCommand.flyout = this._contentFlyout; + } + else { + menuCommand.onclick = originalCommand.onclick; + } + menuCommand["_originalICommand"] = originalCommand; + return menuCommand; + }; + _CommandingSurface.prototype._hideSeparatorsIfNeeded = function (commands) { + var prevType = _Constants.typeSeparator; + var command; + // Hide all leading or consecutive separators + var commandsLength = commands.length; + commands.forEach(function (command) { + if (command.type === _Constants.typeSeparator && prevType === _Constants.typeSeparator) { + command.element.style.display = "none"; + } + prevType = command.type; + }); + for (var i = commandsLength - 1; i >= 0; i--) { + command = commands[i]; + if (command.type === _Constants.typeSeparator) { + command.element.style.display = "none"; + } + else { + break; + } + } + }; + _CommandingSurface.prototype._clearAnimation = function () { + var transformScriptName = _BaseUtils._browserStyleEquivalents["transform"].scriptName; + this._dom.actionAreaContainer.style[transformScriptName] = ""; + this._dom.actionArea.style[transformScriptName] = ""; + this._dom.overflowAreaContainer.style[transformScriptName] = ""; + this._dom.overflowArea.style[transformScriptName] = ""; + }; + /// Display options for the actionarea when the _CommandingSurface is closed. + _CommandingSurface.ClosedDisplayMode = ClosedDisplayMode; + /// Display options used by the _Commandingsurface to determine which direction it should expand when opening. + _CommandingSurface.OverflowDirection = OverflowDirection; + _CommandingSurface.supportedForProcessing = true; + return _CommandingSurface; + })(); + exports._CommandingSurface = _CommandingSurface; + _Base.Class.mix(_CommandingSurface, _Events.createEventProperties(_Constants.EventNames.beforeOpen, _Constants.EventNames.afterOpen, _Constants.EventNames.beforeClose, _Constants.EventNames.afterClose)); + // addEventListener, removeEventListener, dispatchEvent + _Base.Class.mix(_CommandingSurface, _Control.DOMEventMixin); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// +define('WinJS/Controls/CommandingSurface',["require", "exports"], function (require, exports) { + var module = null; + function getModule() { + if (!module) { + require(["./CommandingSurface/_CommandingSurface"], function (m) { + module = m; + }); + } + return module._CommandingSurface; + } + var publicMembers = Object.create({}, { + _CommandingSurface: { + get: function () { + return getModule(); + } + } + }); + return publicMembers; +}); + + +define('require-style!less/styles-toolbar',[],function(){}); +define('WinJS/Controls/ToolBar/_ToolBar',["require", "exports", "../../Core/_Base", "../ToolBar/_Constants", "../CommandingSurface", "../../Utilities/_Control", "../../Utilities/_Dispose", "../../Utilities/_ElementUtilities", "../../Core/_ErrorFromName", '../../Core/_Events', "../../Core/_Global", '../../_LightDismissService', "../../Core/_Resources", '../../Utilities/_OpenCloseMachine', "../../Core/_WriteProfilerMark"], function (require, exports, _Base, _Constants, _CommandingSurface, _Control, _Dispose, _ElementUtilities, _ErrorFromName, _Events, _Global, _LightDismissService, _Resources, _OpenCloseMachine, _WriteProfilerMark) { + require(["require-style!less/styles-toolbar"]); + "use strict"; + var strings = { + get ariaLabel() { + return _Resources._getWinJSString("ui/toolbarAriaLabel").value; + }, + get overflowButtonAriaLabel() { + return _Resources._getWinJSString("ui/toolbarOverflowButtonAriaLabel").value; + }, + get mustContainCommands() { + return "The toolbar can only contain WinJS.UI.Command or WinJS.UI.AppBarCommand controls"; + }, + get duplicateConstruction() { + return "Invalid argument: Controls may only be instantiated one time for each DOM element"; + } + }; + var ClosedDisplayMode = { + /// + /// When the ToolBar is closed, the height of the ToolBar is reduced such that button commands are still visible, but their labels are hidden. + /// + compact: "compact", + /// + /// When the ToolBar is closed, the height of the ToolBar is always sized to content. + /// + full: "full", + }; + var closedDisplayModeClassMap = {}; + closedDisplayModeClassMap[ClosedDisplayMode.compact] = _Constants.ClassNames.compactClass; + closedDisplayModeClassMap[ClosedDisplayMode.full] = _Constants.ClassNames.fullClass; + // Versions of add/removeClass that are no ops when called with falsy class names. + function addClass(element, className) { + className && _ElementUtilities.addClass(element, className); + } + function removeClass(element, className) { + className && _ElementUtilities.removeClass(element, className); + } + /// + /// + /// Displays ICommands within the flow of the app. Use the ToolBar around other statically positioned app content. + /// + /// + /// + /// + /// + /// + /// ]]> + /// The entire ToolBar control. + /// The toolbar overflow button. + /// The container for toolbar commands that overflow. + /// + /// + var ToolBar = (function () { + function ToolBar(element, options) { + /// + /// + /// Creates a new ToolBar control. + /// + /// + /// The DOM element that will host the control. + /// + /// + /// The set of properties and values to apply to the new ToolBar control. + /// + /// + /// The new ToolBar control. + /// + /// + var _this = this; + if (options === void 0) { options = {}; } + // State private to the _updateDomImpl family of method. No other methods should make use of it. + // + // Nothing has been rendered yet so these are all initialized to undefined. Because + // they are undefined, the first time _updateDomImpl is called, they will all be + // rendered. + this._updateDomImpl_renderedState = { + isOpenedMode: undefined, + closedDisplayMode: undefined, + prevInlineWidth: undefined, + }; + this._writeProfilerMark("constructor,StartTM"); + // Check to make sure we weren't duplicated + if (element && element["winControl"]) { + throw new _ErrorFromName("WinJS.UI.ToolBar.DuplicateConstruction", strings.duplicateConstruction); + } + this._initializeDom(element || _Global.document.createElement("div")); + var stateMachine = new _OpenCloseMachine.OpenCloseMachine({ + eventElement: this.element, + onOpen: function () { + var openAnimation = _this._commandingSurface.createOpenAnimation(_this._getClosedHeight()); + _this._synchronousOpen(); + return openAnimation.execute(); + }, + onClose: function () { + var closeAnimation = _this._commandingSurface.createCloseAnimation(_this._getClosedHeight()); + return closeAnimation.execute().then(function () { + _this._synchronousClose(); + }); + }, + onUpdateDom: function () { + _this._updateDomImpl(); + }, + onUpdateDomWithIsOpened: function (isOpened) { + _this._isOpenedMode = isOpened; + _this._updateDomImpl(); + } + }); + // Events + this._handleShowingKeyboardBound = this._handleShowingKeyboard.bind(this); + _ElementUtilities._inputPaneListener.addEventListener(this._dom.root, "showing", this._handleShowingKeyboardBound); + // Initialize private state. + this._disposed = false; + this._cachedClosedHeight = null; + this._commandingSurface = new _CommandingSurface._CommandingSurface(this._dom.commandingSurfaceEl, { openCloseMachine: stateMachine }); + addClass(this._dom.commandingSurfaceEl.querySelector(".win-commandingsurface-actionarea"), _Constants.ClassNames.actionAreaCssClass); + addClass(this._dom.commandingSurfaceEl.querySelector(".win-commandingsurface-overflowarea"), _Constants.ClassNames.overflowAreaCssClass); + addClass(this._dom.commandingSurfaceEl.querySelector(".win-commandingsurface-overflowbutton"), _Constants.ClassNames.overflowButtonCssClass); + addClass(this._dom.commandingSurfaceEl.querySelector(".win-commandingsurface-ellipsis"), _Constants.ClassNames.ellipsisCssClass); + this._isOpenedMode = _Constants.defaultOpened; + this._dismissable = new _LightDismissService.LightDismissableElement({ + element: this._dom.root, + tabIndex: this._dom.root.hasAttribute("tabIndex") ? this._dom.root.tabIndex : -1, + onLightDismiss: function () { + _this.close(); + } + }); + // Initialize public properties. + this.closedDisplayMode = _Constants.defaultClosedDisplayMode; + this.opened = this._isOpenedMode; + _Control.setOptions(this, options); + // Exit the Init state. + _ElementUtilities._inDom(this.element).then(function () { + return _this._commandingSurface.initialized; + }).then(function () { + stateMachine.exitInit(); + _this._writeProfilerMark("constructor,StopTM"); + }); + } + Object.defineProperty(ToolBar.prototype, "element", { + /// + get: function () { + return this._dom.root; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ToolBar.prototype, "data", { + /// + /// Gets or sets the Binding List of WinJS.UI.Command for the ToolBar. + /// + get: function () { + return this._commandingSurface.data; + }, + set: function (value) { + this._commandingSurface.data = value; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ToolBar.prototype, "closedDisplayMode", { + /// + /// Gets or sets the closedDisplayMode for the ToolBar. Values are "compact" and "full". + /// + get: function () { + return this._commandingSurface.closedDisplayMode; + }, + set: function (value) { + if (ClosedDisplayMode[value]) { + this._commandingSurface.closedDisplayMode = value; + this._cachedClosedHeight = null; + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ToolBar.prototype, "opened", { + /// + get: function () { + return this._commandingSurface.opened; + }, + set: function (value) { + this._commandingSurface.opened = value; + }, + enumerable: true, + configurable: true + }); + ToolBar.prototype.open = function () { + /// + /// + /// Opens the ToolBar + /// + /// + this._commandingSurface.open(); + }; + ToolBar.prototype.close = function () { + /// + /// + /// Closes the ToolBar + /// + /// + this._commandingSurface.close(); + }; + ToolBar.prototype.dispose = function () { + /// + /// + /// Disposes this ToolBar. + /// + /// + if (this._disposed) { + return; + } + this._disposed = true; + _LightDismissService.hidden(this._dismissable); + // Disposing the _commandingSurface will trigger dispose on its OpenCloseMachine and synchronously complete any animations that might have been running. + this._commandingSurface.dispose(); + // If page navigation is happening, we don't want the ToolBar left behind in the body. + // Synchronoulsy close the ToolBar to force it out of the body and back into its parent element. + this._synchronousClose(); + _ElementUtilities._inputPaneListener.removeEventListener(this._dom.root, "showing", this._handleShowingKeyboardBound); + _Dispose.disposeSubTree(this.element); + }; + ToolBar.prototype.forceLayout = function () { + /// + /// + /// Forces the ToolBar to update its layout. Use this function when the window did not change size, but the container of the ToolBar changed size. + /// + /// + this._commandingSurface.forceLayout(); + }; + ToolBar.prototype.getCommandById = function (id) { + /// + /// + /// Retrieves the command with the specified ID from this ToolBar. + /// If more than one command is found, this method returns the first command found. + /// + /// Id of the command to return. + /// + /// The command found, or null if no command is found. + /// + /// + return this._commandingSurface.getCommandById(id); + }; + ToolBar.prototype.showOnlyCommands = function (commands) { + /// + /// + /// Show the specified commands, hiding all of the others in the ToolBar. + /// + /// + /// An array of the commands to show. The array elements may be Command objects, or the string identifiers (IDs) of commands. + /// + /// + return this._commandingSurface.showOnlyCommands(commands); + }; + ToolBar.prototype._writeProfilerMark = function (text) { + _WriteProfilerMark("WinJS.UI.ToolBar:" + this._id + ":" + text); + }; + ToolBar.prototype._initializeDom = function (root) { + this._writeProfilerMark("_intializeDom,info"); + // Attaching JS control to DOM element + root["winControl"] = this; + this._id = root.id || _ElementUtilities._uniqueID(root); + _ElementUtilities.addClass(root, _Constants.ClassNames.controlCssClass); + _ElementUtilities.addClass(root, _Constants.ClassNames.disposableCssClass); + // Make sure we have an ARIA role + var role = root.getAttribute("role"); + if (!role) { + root.setAttribute("role", "menubar"); + } + var label = root.getAttribute("aria-label"); + if (!label) { + root.setAttribute("aria-label", strings.ariaLabel); + } + // Create element for commandingSurface and reparent any declarative Commands. + // The CommandingSurface constructor will parse child elements as AppBarCommands. + var commandingSurfaceEl = document.createElement("DIV"); + _ElementUtilities._reparentChildren(root, commandingSurfaceEl); + root.appendChild(commandingSurfaceEl); + // While the ToolBar is open, it will place itself in the so it can become a light dismissible + // overlay. It leaves the placeHolder element behind as stand in at the ToolBar's original DOM location + // to avoid reflowing surrounding app content and create the illusion that the ToolBar hasn't moved along + // the x or y planes. + var placeHolder = _Global.document.createElement("DIV"); + _ElementUtilities.addClass(placeHolder, _Constants.ClassNames.placeHolderCssClass); + // If the ToolBar's original HTML parent node is disposed while the ToolBar is open and repositioned as + // a temporary child of the , make sure that calling dispose on the placeHolder element will trigger + // dispose on the ToolBar as well. + _Dispose.markDisposable(placeHolder, this.dispose.bind(this)); + this._dom = { + root: root, + commandingSurfaceEl: commandingSurfaceEl, + placeHolder: placeHolder, + }; + }; + ToolBar.prototype._handleShowingKeyboard = function (event) { + // Because the ToolBar takes up layout space and is not an overlay, it doesn't have the same expectation + // to move itself to get out of the way of a showing IHM. Instsead we just close the ToolBar to avoid + // scenarios where the ToolBar is occluded, but the click-eating-div is still present since it may seem + // strange to end users that an occluded ToolBar (out of sight, out of mind) is still eating their first + // click. + // Mitigation: + // Because (1) custom content in a ToolBar can only be included as a 'content' type command, because (2) + // the ToolBar only supports closedDisplayModes 'compact' and 'full', and because (3) 'content' type + // commands in the overflowarea use a separate contentflyout to display their contents: + // Interactable custom content contained within the ToolBar actionarea or overflowarea, will remain + // visible and interactable even when showing the IHM closes the ToolBar. + this.close(); + }; + ToolBar.prototype._synchronousOpen = function () { + this._isOpenedMode = true; + this._updateDomImpl(); + }; + ToolBar.prototype._synchronousClose = function () { + this._isOpenedMode = false; + this._updateDomImpl(); + }; + ToolBar.prototype._updateDomImpl = function () { + var rendered = this._updateDomImpl_renderedState; + if (rendered.isOpenedMode !== this._isOpenedMode) { + if (this._isOpenedMode) { + this._updateDomImpl_renderOpened(); + } + else { + this._updateDomImpl_renderClosed(); + } + rendered.isOpenedMode = this._isOpenedMode; + } + if (rendered.closedDisplayMode !== this.closedDisplayMode) { + removeClass(this._dom.root, closedDisplayModeClassMap[rendered.closedDisplayMode]); + addClass(this._dom.root, closedDisplayModeClassMap[this.closedDisplayMode]); + rendered.closedDisplayMode = this.closedDisplayMode; + } + this._commandingSurface.updateDomImpl(); + }; + ToolBar.prototype._getClosedHeight = function () { + if (this._cachedClosedHeight === null) { + var wasOpen = this._isOpenedMode; + if (this._isOpenedMode) { + this._synchronousClose(); + } + this._cachedClosedHeight = this._commandingSurface.getBoundingRects().commandingSurface.height; + if (wasOpen) { + this._synchronousOpen(); + } + } + return this._cachedClosedHeight; + }; + ToolBar.prototype._updateDomImpl_renderOpened = function () { + var _this = this; + // Measure closed state. + this._updateDomImpl_renderedState.prevInlineWidth = this._dom.root.style.width; + var closedBorderBox = this._dom.root.getBoundingClientRect(); + var closedContentWidth = _ElementUtilities._getPreciseContentWidth(this._dom.root); + var closedContentHeight = _ElementUtilities._getPreciseContentHeight(this._dom.root); + var closedStyle = getComputedStyle(this._dom.root); + var closedPaddingTop = _ElementUtilities._convertToPrecisePixels(closedStyle.paddingTop); + var closedBorderTop = _ElementUtilities._convertToPrecisePixels(closedStyle.borderTopWidth); + var closedMargins = _ElementUtilities._getPreciseMargins(this._dom.root); + var closedContentBoxTop = closedBorderBox.top + closedBorderTop + closedPaddingTop; + var closedContentBoxBottom = closedContentBoxTop + closedContentHeight; + // Size our placeHolder. Set height and width to match borderbox of the closed ToolBar. + // Copy ToolBar margins to the placeholder. + var placeHolder = this._dom.placeHolder; + var placeHolderStyle = placeHolder.style; + placeHolderStyle.width = closedBorderBox.width + "px"; + placeHolderStyle.height = closedBorderBox.height + "px"; + placeHolderStyle.marginTop = closedMargins.top + "px"; + placeHolderStyle.marginRight = closedMargins.right + "px"; + placeHolderStyle.marginBottom = closedMargins.bottom + "px"; + placeHolderStyle.marginLeft = closedMargins.left + "px"; + _ElementUtilities._maintainFocus(function () { + // Move ToolBar element to the body in preparation of becoming a light dismissible. Leave an equal sized placeHolder element + // at our original DOM location to avoid reflowing surrounding app content. + _this._dom.root.parentElement.insertBefore(placeHolder, _this._dom.root); + _Global.document.body.appendChild(_this._dom.root); + // Position the ToolBar to completely cover the same region as the placeholder element. + _this._dom.root.style.width = closedContentWidth + "px"; + _this._dom.root.style.left = closedBorderBox.left - closedMargins.left + "px"; + // Determine which direction to expand the CommandingSurface elements when opened. The overflow area will be rendered at the corresponding edge of + // the ToolBar's content box, so we choose the direction that offers the most space between that edge and the corresponding edge of the viewport. + // This is to reduce the chance that the overflow area might clip through the edge of the viewport. + var topOfViewport = 0; + var bottomOfViewport = _Global.innerHeight; + var distanceFromTop = closedContentBoxTop - topOfViewport; + var distanceFromBottom = bottomOfViewport - closedContentBoxBottom; + if (distanceFromTop > distanceFromBottom) { + // CommandingSurface is going to expand updwards. + _this._commandingSurface.overflowDirection = _Constants.OverflowDirection.top; + // Position the bottom edge of the ToolBar marginbox over the bottom edge of the placeholder marginbox. + _this._dom.root.style.bottom = (bottomOfViewport - closedBorderBox.bottom) - closedMargins.bottom + "px"; + } + else { + // CommandingSurface is going to expand downwards. + _this._commandingSurface.overflowDirection = _Constants.OverflowDirection.bottom; + // Position the top edge of the ToolBar marginbox over the top edge of the placeholder marginbox. + _this._dom.root.style.top = (topOfViewport + closedBorderBox.top) - closedMargins.top + "px"; + } + // Render opened state + _ElementUtilities.addClass(_this._dom.root, _Constants.ClassNames.openedClass); + _ElementUtilities.removeClass(_this._dom.root, _Constants.ClassNames.closedClass); + }); + this._commandingSurface.synchronousOpen(); + _LightDismissService.shown(this._dismissable); // Call at the start of the open animation + }; + ToolBar.prototype._updateDomImpl_renderClosed = function () { + var _this = this; + _ElementUtilities._maintainFocus(function () { + if (_this._dom.placeHolder.parentElement) { + // Restore our placement in the DOM + var placeHolder = _this._dom.placeHolder; + placeHolder.parentElement.insertBefore(_this._dom.root, placeHolder); + placeHolder.parentElement.removeChild(placeHolder); + } + // Render Closed + _this._dom.root.style.top = ""; + _this._dom.root.style.right = ""; + _this._dom.root.style.bottom = ""; + _this._dom.root.style.left = ""; + _this._dom.root.style.width = _this._updateDomImpl_renderedState.prevInlineWidth; + _ElementUtilities.addClass(_this._dom.root, _Constants.ClassNames.closedClass); + _ElementUtilities.removeClass(_this._dom.root, _Constants.ClassNames.openedClass); + }); + this._commandingSurface.synchronousClose(); + _LightDismissService.hidden(this._dismissable); // Call after the close animation + }; + /// + /// Display options for the actionarea when the ToolBar is closed. + /// + ToolBar.ClosedDisplayMode = ClosedDisplayMode; + ToolBar.supportedForProcessing = true; + return ToolBar; + })(); + exports.ToolBar = ToolBar; + _Base.Class.mix(ToolBar, _Events.createEventProperties(_Constants.EventNames.beforeOpen, _Constants.EventNames.afterOpen, _Constants.EventNames.beforeClose, _Constants.EventNames.afterClose)); + // addEventListener, removeEventListener, dispatchEvent + _Base.Class.mix(ToolBar, _Control.DOMEventMixin); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// +define('WinJS/Controls/ToolBar',["require", "exports", '../Core/_Base'], function (require, exports, _Base) { + var module = null; + _Base.Namespace.define("WinJS.UI", { + ToolBar: { + get: function () { + if (!module) { + require(["./ToolBar/_ToolBar"], function (m) { + module = m; + }); + } + return module.ToolBar; + } + } + }); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('WinJS/Controls/_LegacyAppBar/_Layouts',[ + 'exports', + '../../Animations/_TransitionAnimation', + '../../BindingList', + '../../Core/_BaseUtils', + '../../Core/_Global', + '../../Core/_Base', + '../../Core/_ErrorFromName', + '../../Core/_Resources', + '../../Core/_WriteProfilerMark', + '../../Controls/ToolBar', + '../../Controls/ToolBar/_Constants', + '../../Promise', + '../../Scheduler', + '../../Utilities/_Control', + '../../Utilities/_Dispose', + '../../Utilities/_ElementUtilities', + '../AppBar/_Command', + './_Constants' +], function appBarLayoutsInit(exports, _TransitionAnimation, BindingList, _BaseUtils, _Global, _Base, _ErrorFromName, _Resources, _WriteProfilerMark, ToolBar, _ToolBarConstants, Promise, Scheduler, _Control, _Dispose, _ElementUtilities, _Command, _Constants) { + "use strict"; + + // AppBar will use this when AppBar.layout property is set to "custom" + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + _AppBarBaseLayout: _Base.Namespace._lazy(function () { + var baseType = _Constants.appBarLayoutCustom; + + var strings = { + get nullCommand() { return "Invalid argument: command must not be null"; } + }; + + var _AppBarBaseLayout = _Base.Class.define(function _AppBarBaseLayout_ctor(appBarEl, options) { + this._disposed = false; + + options = options || {}; + _Control.setOptions(this, options); + + if (appBarEl) { + this.connect(appBarEl); + } + }, { + // Members + className: { + get: function _AppBarBaseLayout_get_className() { + return this._className; + }, + }, + type: { + get: function _AppBarBaseLayout_get_className() { + return this._type || baseType; + }, + }, + commandsInOrder: { + get: function _AppBarBaseLayout_get_commandsInOrder() { + // Get a DOM ordered collection of the AppBarCommand elements in the AppBar. + var commandElements = this.appBarEl.querySelectorAll("." + _Constants.appBarCommandClass); + + // Return an array of AppBarCommand objects. + return Array.prototype.map.call(commandElements, function (commandElement) { + return commandElement.winControl; + }); + } + }, + connect: function _AppBarBaseLayout_connect(appBarEl) { + if (this.className) { + _ElementUtilities.addClass(appBarEl, this.className); + } + this.appBarEl = appBarEl; + }, + disconnect: function _AppBarBaseLayout_disconnect() { + if (this.className) { + _ElementUtilities.removeClass(this.appBarEl, this.className); + } + this.appBarEl = null; + this.dispose(); + }, + layout: function _AppBarBaseLayout_layout(commands) { + // Append commands to the DOM. + var len = commands.length; + for (var i = 0; i < len; i++) { + var command = this.sanitizeCommand(commands[i]); + this.appBarEl.appendChild(command._element); + } + }, + showCommands: function _AppBarBaseLayout_showCommands(commands) { + // Use the default overlay showCommands implementation + this.appBarEl.winControl._showCommands(commands); + }, + showOnlyCommands: function _AppBarBaseLayout_showOnlyCommands(commands) { + // Use the default overlay _showOnlyCommands implementation + this.appBarEl.winControl._showOnlyCommands(commands); + }, + hideCommands: function _AppBarBaseLayout_hideCommands(commands) { + // Use the default overlay _hideCommands implementation + this.appBarEl.winControl._hideCommands(commands); + }, + sanitizeCommand: function _AppBarBaseLayout_sanitizeCommand(command) { + if (!command) { + throw new _ErrorFromName("WinJS.UI.AppBar.NullCommand", strings.nullCommand); + } + // See if it's a command already + command = command.winControl || command; + if (!command._element) { + // Not a command, so assume it is options for the command's constructor. + command = new _Command.AppBarCommand(null, command); + } + // If we were attached somewhere else, detach us + if (command._element.parentElement) { + command._element.parentElement.removeChild(command._element); + } + + return command; + }, + dispose: function _AppBarBaseLayout_dispose() { + this._disposed = true; + }, + disposeChildren: function _AppBarBaseLayout_disposeChildren() { + var appBarFirstDiv = this.appBarEl.querySelectorAll("." + _Constants.firstDivClass); + appBarFirstDiv = appBarFirstDiv.length >= 1 ? appBarFirstDiv[0] : null; + var appBarFinalDiv = this.appBarEl.querySelectorAll("." + _Constants.finalDivClass); + appBarFinalDiv = appBarFinalDiv.length >= 1 ? appBarFinalDiv[0] : null; + + var children = this.appBarEl.children; + var length = children.length; + for (var i = 0; i < length; i++) { + var element = children[i]; + if (element === appBarFirstDiv || element === appBarFinalDiv) { + continue; + } else { + _Dispose.disposeSubTree(element); + } + } + }, + handleKeyDown: function _AppBarBaseLayout_handleKeyDown() { + // NOP + }, + commandsUpdated: function _AppBarBaseLayout_commandsUpdated() { + // NOP + }, + beginAnimateCommands: function _AppBarBaseLayout_beginAnimateCommands() { + // The parameters are 3 mutually exclusive arrays of win-command elements contained in this Overlay. + // 1) showCommands[]: All of the HIDDEN win-command elements that ARE scheduled to show. + // 2) hideCommands[]: All of the VISIBLE win-command elements that ARE scheduled to hide. + // 3) otherVisibleCommands[]: All VISIBLE win-command elements that ARE NOT scheduled to hide. + + // NOP + }, + endAnimateCommands: function _AppBarBaseLayout_endAnimateCommands() { + // NOP + }, + scale: function _AppBarBaseLayout_scale() { + // NOP + }, + resize: function _AppBarBaseLayout_resize() { + // NOP + }, + positionChanging: function _AppBarBaseLayout_positionChanging(fromPosition, toPosition) { + // NOP + return Promise.wrap(); + }, + setFocusOnShow: function _AppBarBaseLayout_setFocusOnShow() { + this.appBarEl.winControl._setFocusToAppBar(); + } + }); + return _AppBarBaseLayout; + }), + }); + + // AppBar will use this when AppBar.layout property is set to "commands" + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + _AppBarCommandsLayout: _Base.Namespace._lazy(function () { + var layoutClassName = _Constants.commandLayoutClass; + var layoutType = _Constants.appBarLayoutCommands; + + var _AppBarCommandsLayout = _Base.Class.derive(exports._AppBarBaseLayout, function _AppBarCommandsLayout_ctor(appBarEl) { + exports._AppBarBaseLayout.call(this, appBarEl, { _className: layoutClassName, _type: layoutType }); + this._commandLayoutsInit(appBarEl); + }, { + commandsInOrder: { + get: function _AppBarCommandsLayout_get_commandsInOrder() { + return this._originalCommands.filter(function (command) { + // Make sure the element is still in the AppBar. + return this.appBarEl.contains(command.element); + }, this); + } + }, + layout: function _AppBarCommandsLayout_layout(commands) { + // Insert commands and other layout specific DOM into the AppBar element. + + // Empty our tree. + _ElementUtilities.empty(this._primaryCommands); + _ElementUtilities.empty(this._secondaryCommands); + + // Keep track of the order we receive the commands in. + this._originalCommands = []; + + // Layout commands + for (var i = 0, len = commands.length; i < len; i++) { + var command = this.sanitizeCommand(commands[i]); + + this._originalCommands.push(command); + + if ("primary" === command.section || "global" === command.section) { + this._primaryCommands.appendChild(command._element); + } else { + this._secondaryCommands.appendChild(command._element); + } + } + + // Append layout containers to AppBar element. + // Secondary Commands should come first in Tab Order. + this.appBarEl.appendChild(this._secondaryCommands); + this.appBarEl.appendChild(this._primaryCommands); + + + // Need to measure all content commands after they have been added to the AppBar to make sure we allow + // user defined CSS rules based on the ancestor of the content command to take affect. + this._needToMeasureNewCommands = true; + + // In case this is called from the constructor before the AppBar element has been appended to the DOM, + // we schedule the initial scaling of commands, with the expectation that the element will be added + // synchronously, in the same block of code that called the constructor. + Scheduler.schedule(function () { + if (this._needToMeasureNewCommands && !this._disposed) { + this.scale(); + } + }.bind(this), Scheduler.Priority.idle, this, "WinJS._commandLayoutsMixin._scaleNewCommands"); + + }, + disposeChildren: function _AppBarCommandsLayout_disposeChildren() { + _Dispose.disposeSubTree(this._primaryCommands); + _Dispose.disposeSubTree(this._secondaryCommands); + }, + handleKeyDown: function _AppBarCommandsLayout_handleKeyDown(event) { + var Key = _ElementUtilities.Key; + + if (_ElementUtilities._matchesSelector(event.target, ".win-interactive, .win-interactive *")) { + return; // Ignore left, right, home & end keys if focused element has win-interactive class. + } + var rtl = _Global.getComputedStyle(this.appBarEl).direction === "rtl"; + var leftKey = rtl ? Key.rightArrow : Key.leftArrow; + var rightKey = rtl ? Key.leftArrow : Key.rightArrow; + + if (event.keyCode === leftKey || event.keyCode === rightKey || event.keyCode === Key.home || event.keyCode === Key.end) { + + var globalCommandHasFocus = this._primaryCommands.contains(_Global.document.activeElement); + var focusableCommands = this._getFocusableCommandsInLogicalOrder(globalCommandHasFocus); + var targetCommand; + + if (focusableCommands.length) { + switch (event.keyCode) { + case leftKey: + // Arrowing past the last command wraps back around to the first command. + var index = Math.max(-1, focusableCommands.focusedIndex - 1) + focusableCommands.length; + targetCommand = focusableCommands[index % focusableCommands.length].winControl.lastElementFocus; + break; + + case rightKey: + // Arrowing previous to the first command wraps back around to the last command. + var index = focusableCommands.focusedIndex + 1 + focusableCommands.length; + targetCommand = focusableCommands[index % focusableCommands.length].winControl.firstElementFocus; + break; + + case Key.home: + var index = 0; + targetCommand = focusableCommands[index].winControl.firstElementFocus; + break; + + case Key.end: + var index = focusableCommands.length - 1; + targetCommand = focusableCommands[index].winControl.lastElementFocus; + break; + } + } + + if (targetCommand && targetCommand !== _Global.document.activeElement) { + targetCommand.focus(); + // Prevent default so that the browser doesn't also evaluate the keydown event on the newly focused element. + event.preventDefault(); + } + } + }, + commandsUpdated: function _AppBarCommandsLayout_commandsUpdated(newSetOfVisibleCommands) { + // Whenever new commands are set or existing commands are hiding/showing in the AppBar, this + // function is called to update the cached width measurement of all visible AppBarCommands. + + var visibleCommands = (newSetOfVisibleCommands) ? newSetOfVisibleCommands : this.commandsInOrder.filter(function (command) { + return !command.hidden; + }); + this._fullSizeWidthOfLastKnownVisibleCommands = this._getWidthOfFullSizeCommands(visibleCommands); + }, + beginAnimateCommands: function _AppBarCommandsLayout_beginAnimateCommands(showCommands, hideCommands, otherVisibleCommands) { + // The parameters are 3 mutually exclusive arrays of win-command elements contained in this Overlay. + // 1) showCommands[]: All of the HIDDEN win-command elements that ARE scheduled to show. + // 2) hideCommands[]: All of the VISIBLE win-command elements that ARE scheduled to hide. + // 3) otherVisibleCommands[]: All VISIBLE win-command elements that ARE NOT scheduled to hide. + + this._scaleAfterAnimations = false; + + // Determine if the overall width of visible commands in the primary row will be increasing OR decreasing. + var changeInWidth = this._getWidthOfFullSizeCommands(showCommands) - this._getWidthOfFullSizeCommands(hideCommands); + if (changeInWidth > 0) { + // Width of contents is going to increase, update our command counts now, to what they will be after we complete the animations. + var visibleCommandsAfterAnimations = otherVisibleCommands.concat(showCommands); + this.commandsUpdated(visibleCommandsAfterAnimations); + // Make sure we will have enough room to fit everything on a single row. + this.scale(); + } else if (changeInWidth < 0) { + // Width of contents is going to decrease. Once animations are complete, check if + // there is enough available space to make the remaining commands full size. + this._scaleAfterAnimations = true; + } + }, + endAnimateCommands: function _AppBarCommandsLayout_endAnimateCommands() { + if (this._scaleAfterAnimations) { + this.commandsUpdated(); + this.scale(); + } + }, + resize: function _AppBarCommandsLayout_resize() { + if (!this._disposed) { + // Check for horizontal window resizes. + this._appBarTotalKnownWidth = null; + if (this.appBarEl.winControl.opened) { + this.scale(); + } + } + }, + disconnect: function _AppBarCommandsLayout_disconnect() { + exports._AppBarBaseLayout.prototype.disconnect.call(this); + }, + _getWidthOfFullSizeCommands: function _AppBarCommandsLayout_getWidthOfFullSizeCommands(commands) { + // Commands layout puts primary commands and secondary commands into the primary row. + // Return the total width of all visible primary and secondary commands as if they were full-size. + + // Perform any pending measurements on "content" type AppBarCommands. + if (this._needToMeasureNewCommands) { + this._measureContentCommands(); + } + var accumulatedWidth = 0; + var separatorsCount = 0; + var buttonsCount = 0; + + if (!commands) { + // Return the cached full size width of the last known visible commands in the AppBar. + return this._fullSizeWidthOfLastKnownVisibleCommands; + } else { + // Return the width of the specified commands. + var command; + for (var i = 0, len = commands.length; i < len; i++) { + command = commands[i].winControl || commands[i]; + if (command._type === _Constants.typeSeparator) { + separatorsCount++; + } else if (command._type !== _Constants.typeContent) { + // button, toggle, and flyout types all have the same width. + buttonsCount++; + } else { + accumulatedWidth += command._fullSizeWidth; + } + } + } + return accumulatedWidth += (separatorsCount * _Constants.separatorWidth) + (buttonsCount * _Constants.buttonWidth); + }, + _getFocusableCommandsInLogicalOrder: function _AppBarCommandsLayout_getCommandsInLogicalOrder() { + // Function returns an array of all the contained AppBarCommands which are reachable by left/right arrows. + + var secondaryCommands = this._secondaryCommands.children, + primaryCommands = this._primaryCommands.children, + focusedIndex = -1; + + var getFocusableCommandsHelper = function (commandsInReach) { + var focusableCommands = []; + for (var i = 0, len = commandsInReach.length; i < len; i++) { + var element = commandsInReach[i]; + if (_ElementUtilities.hasClass(element, _Constants.appBarCommandClass) && element.winControl) { + var containsFocus = element.contains(_Global.document.activeElement); + // With the inclusion of content type commands, it may be possible to tab to elements in AppBarCommands that are not reachable by arrow keys. + // Regardless, when an AppBarCommand contains the element with focus, we just include the whole command so that we can determine which + // commands are adjacent to it when looking for the next focus destination. + if (element.winControl._isFocusable() || containsFocus) { + focusableCommands.push(element); + if (containsFocus) { + focusedIndex = focusableCommands.length - 1; + } + } + } + } + return focusableCommands; + }; + + // Determines which set of commands the user could potentially reach through Home, End, and arrow keys. + // All commands in the commands layout AppBar, from left to right are in reach. Secondary (previously known as Selection) + // then Primary (previously known as Global). + var commandsInReach = Array.prototype.slice.call(secondaryCommands).concat(Array.prototype.slice.call(primaryCommands)); + + var focusableCommands = getFocusableCommandsHelper(commandsInReach); + focusableCommands.focusedIndex = focusedIndex; + return focusableCommands; + }, + _commandLayoutsInit: function _AppBarCommandsLayout_commandLayoutsInit() { + // Create layout infrastructure + this._primaryCommands = _Global.document.createElement("DIV"); + this._secondaryCommands = _Global.document.createElement("DIV"); + _ElementUtilities.addClass(this._primaryCommands, _Constants.primaryCommandsClass); + _ElementUtilities.addClass(this._secondaryCommands, _Constants.secondaryCommandsClass); + }, + _scaleHelper: function _AppBarCommandsLayout_scaleHelper() { + // This exists as a single line function so that unit tests can + // overwrite it since they can't resize the WWA window. + + // It is expected that AppBar is an immediate child of the and will have 100% width. + // We measure the clientWidth of the documentElement so that we can scale the AppBar lazily + // even while its element is display: 'none' + var extraPadding = this.appBarEl.winControl.closedDisplayMode === "minimal" ? _Constants.appBarInvokeButtonWidth : 0; + return _Global.document.documentElement.clientWidth - extraPadding; + }, + _measureContentCommands: function _AppBarCommandsLayout_measureContentCommands() { + // AppBar measures the width of content commands when they are first added + // and then caches that value to avoid additional layouts in the future. + + // Can't measure unless We're in the document body + if (_Global.document.body.contains(this.appBarEl)) { + this._needToMeasureNewCommands = false; + + var hadHiddenClass = _ElementUtilities.hasClass(this.appBarEl, "win-navbar-closed"); + _ElementUtilities.removeClass(this.appBarEl, "win-navbar-closed"); + + // Make sure AppBar and children have width dimensions. + var prevAppBarDisplay = this.appBarEl.style.display; + this.appBarEl.style.display = ""; + var prevCommandDisplay; + + var contentElements = this.appBarEl.querySelectorAll("div." + _Constants.appBarCommandClass); + var element; + for (var i = 0, len = contentElements.length; i < len; i++) { + element = contentElements[i]; + if (element.winControl && element.winControl._type === _Constants.typeContent) { + // Make sure command has width dimensions before we measure. + prevCommandDisplay = element.style.display; + element.style.display = ""; + element.winControl._fullSizeWidth = _ElementUtilities.getTotalWidth(element) || 0; + element.style.display = prevCommandDisplay; + } + } + + // Restore state to AppBar. + this.appBarEl.style.display = prevAppBarDisplay; + if (hadHiddenClass) { + _ElementUtilities.addClass(this.appBarEl, "win-navbar-closed"); + } + + this.commandsUpdated(); + } + }, + }); + return _AppBarCommandsLayout; + }), + }); + + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + _AppBarMenuLayout: _Base.Namespace._lazy(function () { + var layoutClassName = _Constants.menuLayoutClass; + var layoutType = _Constants.appBarLayoutMenu; + + // + // Resize animation + // The resize animation requires 2 animations to run simultaneously in sync with each other. It's implemented + // without PVL because PVL doesn't provide a way to guarantee that 2 animations will start at the same time. + // + var transformNames = _BaseUtils._browserStyleEquivalents["transform"]; + function transformWithTransition(element, transition) { + // transition's properties: + // - duration: Number representing the duration of the animation in milliseconds. + // - timing: String representing the CSS timing function that controls the progress of the animation. + // - to: The value of *element*'s transform property after the animation. + var duration = transition.duration * _TransitionAnimation._animationFactor; + var transitionProperty = _BaseUtils._browserStyleEquivalents["transition"].scriptName; + element.style[transitionProperty] = duration + "ms " + transformNames.cssName + " " + transition.timing; + element.style[transformNames.scriptName] = transition.to; + + var finish; + return new Promise(function (c) { + var onTransitionEnd = function (eventObject) { + if (eventObject.target === element && eventObject.propertyName === transformNames.cssName) { + finish(); + } + }; + + var didFinish = false; + finish = function () { + if (!didFinish) { + _Global.clearTimeout(timeoutId); + element.removeEventListener(_BaseUtils._browserEventEquivalents["transitionEnd"], onTransitionEnd); + element.style[transitionProperty] = ""; + didFinish = true; + } + c(); + }; + + // Watch dog timeout + var timeoutId = _Global.setTimeout(function () { + timeoutId = _Global.setTimeout(finish, duration); + }, 50); + + element.addEventListener(_BaseUtils._browserEventEquivalents["transitionEnd"], onTransitionEnd); + }, function () { + finish(); // On cancelation, complete the promise successfully to match PVL + }); + } + // See resizeTransition's comment for documentation on *args*. + function growTransition(elementClipper, element, args) { + var diff = args.anchorTrailingEdge ? args.to.total - args.from.total : args.from.total - args.to.total; + var translate = args.dimension === "width" ? "translateX" : "translateY"; + var size = args.dimension; + var duration = args.duration || 367; + var timing = args.timing || "cubic-bezier(0.1, 0.9, 0.2, 1)"; + + // Set up + elementClipper.style[size] = args.to.total + "px"; + elementClipper.style[transformNames.scriptName] = translate + "(" + diff + "px)"; + element.style[size] = args.to.content + "px"; + element.style[transformNames.scriptName] = translate + "(" + -diff + "px)"; + + // Resolve styles + _Global.getComputedStyle(elementClipper).opacity; + _Global.getComputedStyle(element).opacity; + + // Animate + var transition = { + duration: duration, + timing: timing, + to: "" + }; + return Promise.join([ + transformWithTransition(elementClipper, transition), + transformWithTransition(element, transition) + ]); + } + // See resizeTransition's comment for documentation on *args*. + function shrinkTransition(elementClipper, element, args) { + var diff = args.anchorTrailingEdge ? args.from.total - args.to.total : args.to.total - args.from.total; + var translate = args.dimension === "width" ? "translateX" : "translateY"; + var duration = args.duration || 367; + var timing = args.timing || "cubic-bezier(0.1, 0.9, 0.2, 1)"; + + // Set up + elementClipper.style[transformNames.scriptName] = ""; + element.style[transformNames.scriptName] = ""; + + // Resolve styles + _Global.getComputedStyle(elementClipper).opacity; + _Global.getComputedStyle(element).opacity; + + // Animate + var transition = { + duration: duration, + timing: timing + }; + var clipperTransition = _BaseUtils._merge(transition, { to: translate + "(" + diff + "px)" }); + var elementTransition = _BaseUtils._merge(transition, { to: translate + "(" + -diff + "px)" }); + return Promise.join([ + transformWithTransition(elementClipper, clipperTransition), + transformWithTransition(element, elementTransition) + ]); + } + // Plays an animation which makes an element look like it is resizing in 1 dimension. Arguments: + // - elementClipper: The parent of *element*. It shouldn't have any margin, border, or padding and its + // size should match element's size. Its purpose is to clip *element* during the animation to give + // it the illusion that it is resizing. + // - element: The element that should look like it's resizing. + // - args: An object with the following required properties: + // - from: An object representing the old width/height of the element. + // - to: An object representing the new width/height of the element. + // from/to are objects of the form { content: number; total: number; }. "content" is the + // width/height of *element*'s content box (e.g. getContentWidth). "total" is the width/height + // of *element*'s margin box (e.g. getTotalWidth). + // - duration: The CSS transition duration property. + // - timing: The CSS transition timing property. + // - dimension: The dimension on which *element* is resizing. Either "width" or "height". + // - anchorTrailingEdge: During the resize animation, one edge will move and the other edge will + // remain where it is. This flag specifies which edge is anchored (i.e. won't move). + // + function resizeTransition(elementClipper, element, args) { + if (args.to.total > args.from.total) { + return growTransition(elementClipper, element, args); + } else if (args.to.total < args.from.total) { + return shrinkTransition(elementClipper, element, args); + } else { + return Promise.as(); + } + } + + var _AppBarMenuLayout = _Base.Class.derive(exports._AppBarBaseLayout, function _AppBarMenuLayout_ctor(appBarEl) { + exports._AppBarBaseLayout.call(this, appBarEl, { _className: layoutClassName, _type: layoutType }); + this._tranformNames = _BaseUtils._browserStyleEquivalents["transform"]; + this._animationCompleteBound = this._animationComplete.bind(this); + this._positionToolBarBound = this._positionToolBar.bind(this); + }, { + commandsInOrder: { + get: function _AppBarMenuLayout_get_commandsInOrder() { + return this._originalCommands; + } + }, + layout: function _AppBarMenuLayout_layout(commands) { + this._writeProfilerMark("layout,info"); + + commands = commands || []; + this._originalCommands = []; + + var that = this; + commands.forEach(function (command) { + that._originalCommands.push(that.sanitizeCommand(command)); + }); + this._displayedCommands = this._originalCommands.slice(0); + + if (this._menu) { + _ElementUtilities.empty(this._menu); + } else { + this._menu = _Global.document.createElement("div"); + _ElementUtilities.addClass(this._menu, _Constants.menuContainerClass); + } + this.appBarEl.appendChild(this._menu); + + this._toolbarEl = _Global.document.createElement("div"); + this._menu.appendChild(this._toolbarEl); + + this._createToolBar(commands); + }, + + showCommands: function _AppBarMenuLayout_showCommands(commands) { + var elements = this._getCommandsElements(commands); + var data = []; + var newDisplayedCommands = []; + var that = this; + this._originalCommands.forEach(function (command) { + if (elements.indexOf(command.element) >= 0 || that._displayedCommands.indexOf(command) >= 0) { + newDisplayedCommands.push(command); + data.push(command); + } + }); + this._displayedCommands = newDisplayedCommands; + this._updateData(data); + }, + + showOnlyCommands: function _AppBarMenuLayout_showOnlyCommands(commands) { + this._displayedCommands = []; + this.showCommands(commands); + }, + + hideCommands: function _AppBarMenuLayout_hideCommands(commands) { + var elements = this._getCommandsElements(commands); + var data = []; + var newDisplayedCommands = []; + var that = this; + this._originalCommands.forEach(function (command) { + if (elements.indexOf(command.element) === -1 && that._displayedCommands.indexOf(command) >= 0) { + newDisplayedCommands.push(command); + data.push(command); + } + }); + this._displayedCommands = newDisplayedCommands; + this._updateData(data); + }, + + connect: function _AppBarMenuLayout_connect(appBarEl) { + this._writeProfilerMark("connect,info"); + + exports._AppBarBaseLayout.prototype.connect.call(this, appBarEl); + this._id = _ElementUtilities._uniqueID(appBarEl); + }, + + resize: function _AppBarMenuLayout_resize() { + this._writeProfilerMark("resize,info"); + + if (this._initialized) { + this._forceLayoutPending = true; + } + }, + + positionChanging: function _AppBarMenuLayout_positionChanging(fromPosition, toPosition) { + this._writeProfilerMark("positionChanging from:" + fromPosition + " to: " + toPosition + ",info"); + + this._animationPromise = this._animationPromise || Promise.wrap(); + + if (this._animating) { + this._animationPromise.cancel(); + } + + this._animating = true; + if (toPosition === "shown" || (fromPosition !== "shown" && toPosition === "compact")) { + this._positionToolBar(); + this._animationPromise = this._animateToolBarEntrance(); + } else { + if (fromPosition === "minimal" || fromPosition === "compact" || fromPosition === "hidden") { + this._animationPromise = Promise.wrap(); + } else { + this._animationPromise = this._animateToolBarExit(); + } + } + this._animationPromise.then(this._animationCompleteBound, this._animationCompleteBound); + return this._animationPromise; + }, + + disposeChildren: function _AppBarMenuLayout_disposeChildren() { + this._writeProfilerMark("disposeChildren,info"); + + if (this._toolbar) { + _Dispose.disposeSubTree(this._toolbarEl); + } + this._originalCommands = []; + this._displayedCommands = []; + }, + + setFocusOnShow: function _AppBarMenuLayout_setFocusOnShow() { + // Make sure the menu (used for clipping during the resize animation) + // doesn't scroll when we give focus to the AppBar. + this.appBarEl.winControl._setFocusToAppBar(true, this._menu); + }, + + _updateData: function _AppBarMenuLayout_updateData(data) { + var hadHiddenClass = _ElementUtilities.hasClass(this.appBarEl, "win-navbar-closed"); + var hadShownClass = _ElementUtilities.hasClass(this.appBarEl, "win-navbar-opened"); + _ElementUtilities.removeClass(this.appBarEl, "win-navbar-closed"); + + // Make sure AppBar and children have width dimensions. + var prevAppBarDisplay = this.appBarEl.style.display; + this.appBarEl.style.display = ""; + + + this._toolbar.data = new BindingList.List(data); + if (hadHiddenClass) { + this._positionToolBar(); + } + + // Restore state to AppBar. + this.appBarEl.style.display = prevAppBarDisplay; + if (hadHiddenClass) { + _ElementUtilities.addClass(this.appBarEl, "win-navbar-closed"); + } + + if (hadShownClass) { + this._positionToolBar(); + this._animateToolBarEntrance(); + } + }, + + _getCommandsElements: function _AppBarMenuLayout_getCommandsElements(commands) { + if (!commands) { + return []; + } + + if (typeof commands === "string" || !commands || !commands.length) { + commands = [commands]; + } + + var elements = []; + for (var i = 0, len = commands.length; i < len; i++) { + if (commands[i]) { + if (typeof commands[i] === "string") { + var element = _Global.document.getElementById(commands[i]); + if (element) { + elements.push(element); + } else { + // Check in the list we are tracking, since it might not be in the DOM yet + for (var j = 0, len2 = this._originalCommands.length; j < len2; j++) { + var element = this._originalCommands[j].element; + if (element.id === commands[i]) { + elements.push(element); + } + } + } + } else if (commands[i].element) { + elements.push(commands[i].element); + } else { + elements.push(commands[i]); + } + } + } + + return elements; + }, + + _animationComplete: function _AppBarMenuLayout_animationComplete() { + if (!this._disposed) { + this._animating = false; + } + }, + + _createToolBar: function _AppBarMenuLayout_createToolBar(commands) { + this._writeProfilerMark("_createToolBar,info"); + + var hadHiddenClass = _ElementUtilities.hasClass(this.appBarEl, "win-navbar-closed"); + _ElementUtilities.removeClass(this.appBarEl, "win-navbar-closed"); + + // Make sure AppBar and children have width dimensions. + var prevAppBarDisplay = this.appBarEl.style.display; + this.appBarEl.style.display = ""; + + this._toolbar = new ToolBar.ToolBar(this._toolbarEl, { + data: new BindingList.List(this._originalCommands), + shownDisplayMode: 'full', + }); + + var that = this; + this._appbarInvokeButton = this.appBarEl.querySelector("." + _Constants.invokeButtonClass); + this._overflowButton = this._toolbarEl.querySelector("." + _ToolBarConstants.overflowButtonCssClass); + this._overflowButton.addEventListener("click", function () { + that._appbarInvokeButton.click(); + }); + + this._positionToolBar(); + + // Restore state to AppBar. + this.appBarEl.style.display = prevAppBarDisplay; + if (hadHiddenClass) { + _ElementUtilities.addClass(this.appBarEl, "win-navbar-closed"); + } + }, + + _positionToolBar: function _AppBarMenuLayout_positionToolBar() { + if (!this._disposed) { + this._writeProfilerMark("_positionToolBar,info"); + this._initialized = true; + } + }, + + _animateToolBarEntrance: function _AppBarMenuLayout_animateToolBarEntrance() { + this._writeProfilerMark("_animateToolBarEntrance,info"); + + if (this._forceLayoutPending) { + this._forceLayoutPending = false; + this._toolbar.forceLayout(); + this._positionToolBar(); + } + var heightVisible = this._isMinimal() ? 0 : this.appBarEl.offsetHeight; + if (this._isBottom()) { + // Bottom AppBar Animation + var offsetTop = this._menu.offsetHeight - heightVisible; + return this._executeTranslate(this._menu, "translateY(" + -offsetTop + "px)"); + } else { + // Top AppBar Animation + return resizeTransition(this._menu, this._toolbarEl, { + from: { content: heightVisible, total: heightVisible }, + to: { content: this._menu.offsetHeight, total: this._menu.offsetHeight }, + dimension: "height", + duration: 400, + timing: "ease-in", + }); + } + }, + + _animateToolBarExit: function _AppBarMenuLayout_animateToolBarExit() { + this._writeProfilerMark("_animateToolBarExit,info"); + + var heightVisible = this._isMinimal() ? 0 : this.appBarEl.offsetHeight; + if (this._isBottom()) { + return this._executeTranslate(this._menu, "none"); + } else { + // Top AppBar Animation + return resizeTransition(this._menu, this._toolbarEl, { + from: { content: this._menu.offsetHeight, total: this._menu.offsetHeight }, + to: { content: heightVisible, total: heightVisible }, + dimension: "height", + duration: 400, + timing: "ease-in", + }); + } + }, + + _executeTranslate: function _AppBarMenuLayout_executeTranslate(element, value) { + return _TransitionAnimation.executeTransition(element, + { + property: this._tranformNames.cssName, + delay: 0, + duration: 400, + timing: "ease-in", + to: value + }); + }, + + _isMinimal: function _AppBarMenuLayout_isMinimal() { + return this.appBarEl.winControl.closedDisplayMode === "minimal"; + }, + + _isBottom: function _AppBarMenuLayout_isBottom() { + return this.appBarEl.winControl.placement === "bottom"; + }, + + _writeProfilerMark: function _AppBarMenuLayout_writeProfilerMark(text) { + _WriteProfilerMark("WinJS.UI._AppBarMenuLayout:" + this._id + ":" + text); + } + }); + + return _AppBarMenuLayout; + }), + }); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +// _LegacyAppBar +/// appbar,appBars,Flyout,Flyouts,iframe,Statics,unfocus,WinJS +define('WinJS/Controls/_LegacyAppBar',[ + 'exports', + '../Core/_Global', + '../Core/_WinRT', + '../Core/_Base', + '../Core/_BaseUtils', + '../Core/_ErrorFromName', + '../Core/_Events', + '../Core/_Resources', + '../Core/_WriteProfilerMark', + '../Animations', + '../Promise', + '../Scheduler', + '../_LightDismissService', + '../Utilities/_Control', + '../Utilities/_Dispose', + '../Utilities/_ElementUtilities', + '../Utilities/_Hoverable', + '../Utilities/_KeyboardBehavior', + './_LegacyAppBar/_Constants', + './_LegacyAppBar/_Layouts', + './AppBar/_Command', + './AppBar/_Icon', + './Flyout/_Overlay', + '../Application' +], function appBarInit(exports, _Global, _WinRT, _Base, _BaseUtils, _ErrorFromName, _Events, _Resources, _WriteProfilerMark, Animations, Promise, Scheduler, _LightDismissService, _Control, _Dispose, _ElementUtilities, _Hoverable, _KeyboardBehavior, _Constants, _Layouts, _Command, _Icon, _Overlay, Application) { + "use strict"; + + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + /// + /// + /// Represents an application toolbar for display commands. + /// + /// + /// + /// + /// + /// + /// ]]> + /// Raised just before showing the _LegacyAppBar. + /// Raised immediately after the _LegacyAppBar is fully shown. + /// Raised just before hiding the _LegacyAppBar. + /// Raised immediately after the _LegacyAppBar is fully hidden. + /// The _LegacyAppBar control itself. + /// Style for a custom layout _LegacyAppBar. + /// + /// + _LegacyAppBar: _Base.Namespace._lazy(function () { + var EVENTS = { + beforeOpen: "beforeopen", + afterOpen: "afteropen", + beforeClose: "beforeclose", + afterClose: "afterclose", + }; + + var createEvent = _Events._createEventProperty; + + // Enum of known constant pixel values for display modes. + var knownVisibleHeights = { + none: 0, + hidden: 0, + minimal: 25, + compact: 48 + }; + + // Maps each notion of a display modes to the corresponding visible position + var displayModeVisiblePositions = { + none: "hidden", + hidden: "hidden", + minimal: "minimal", + shown: "shown", + compact: "compact" + }; + + // Enum of closedDisplayMode constants + var closedDisplayModes = { + none: "none", + minimal: "minimal", + compact: "compact" + }; + + // Constants shown/hidden states + var appbarShownState = "shown", + appbarHiddenState = "hidden"; + + // Hook into event + var globalEventsInitialized = false; + + function _allManipulationChanged(event) { + var elements = _Global.document.querySelectorAll("." + _Constants.appBarClass); + if (elements) { + var len = elements.length; + for (var i = 0; i < len; i++) { + var element = elements[i]; + var appbar = element.winControl; + if (appbar && !element.disabled) { + appbar._manipulationChanged(event); + } + } + } + } + + var strings = { + get ariaLabel() { return _Resources._getWinJSString("ui/appBarAriaLabel").value; }, + get requiresCommands() { return "Invalid argument: commands must not be empty"; }, + get cannotChangePlacementWhenVisible() { return "Invalid argument: The placement property cannot be set when the AppBar is visible, call hide() first"; }, + get cannotChangeLayoutWhenVisible() { return "Invalid argument: The layout property cannot be set when the AppBar is visible, call hide() first"; } + }; + + var _LegacyAppBar = _Base.Class.derive(_Overlay._Overlay, function _LegacyAppBar_ctor(element, options) { + /// + /// + /// Creates a new _LegacyAppBar control. + /// + /// + /// The DOM element that will host the control. + /// + /// + /// The set of properties and values to apply to the new _LegacyAppBar control. + /// + /// + /// The new _LegacyAppBar control. + /// + /// + + this._initializing = true; + + // Simplify checking later + options = options || {}; + + // Make sure there's an element + this._element = element || _Global.document.createElement("div"); + this._id = this._element.id || _ElementUtilities._uniqueID(this._element); + this._writeProfilerMark("constructor,StartTM"); + + // Attach our css class. + _ElementUtilities.addClass(this._element, _Constants.appBarClass); + + var that = this; + this._dismissable = new _LightDismissService.LightDismissableElement({ + element: this._element, + tabIndex: this._element.hasAttribute("tabIndex") ? this._element.tabIndex : -1, + onLightDismiss: function () { + that.close(); + }, + onTakeFocus: function (useSetActive) { + if (!that._dismissable.restoreFocus()) { + that._layoutImpl.setFocusOnShow(); + } + }, + }); + + // Make sure we have an ARIA role + var role = this._element.getAttribute("role"); + if (!role) { + this._element.setAttribute("role", "menubar"); + } + var label = this._element.getAttribute("aria-label"); + if (!label) { + this._element.setAttribute("aria-label", strings.ariaLabel); + } + + // Call the _Overlay constructor helper to finish setting up our element. + // Don't pass constructor options, _LegacyAppBar needs to set those itself specific order. + this._baseOverlayConstructor(this._element); + + // Start off hidden + this._lastPositionVisited = displayModeVisiblePositions.none; + _ElementUtilities.addClass(this._element, _Constants.hiddenClass); + + // Add Invoke button. + this._invokeButton = _Global.document.createElement("button"); + this._invokeButton.tabIndex = 0; + this._invokeButton.setAttribute("type", "button"); + this._invokeButton.innerHTML = ""; + _ElementUtilities.addClass(this._invokeButton, _Constants.invokeButtonClass); + this._element.appendChild(this._invokeButton); + this._invokeButton.addEventListener("click", function () { + if (that.opened) { + that._hide(); + } else { + that._show(); + } + }, false); + + // Run layout setter immediately. We need to know our layout in order to correctly + // position any commands that may be getting set through the constructor. + this._layout = _Constants.appBarLayoutCustom; + delete options._layout; + + // Need to set placement before closedDisplayMode, closedDisplayMode sets our starting position, which is dependant on placement. + this.placement = options.placement || _Constants.appBarPlacementBottom; + this.closedDisplayMode = options.closedDisplayMode || closedDisplayModes.compact; + + _Control.setOptions(this, options); + + var commandsUpdatedBound = this._commandsUpdated.bind(this); + this._element.addEventListener(_Constants.commandVisibilityChanged, function (ev) { + if (that._disposed) { + return; + } + if (that.opened) { + ev.preventDefault(); + } + commandsUpdatedBound(); + }); + + this._initializing = false; + + this._setFocusToAppBarBound = this._setFocusToAppBar.bind(this); + + // Handle key down (left & right) + this._element.addEventListener("keydown", this._handleKeyDown.bind(this), false); + + // Attach global event handlers + if (!globalEventsInitialized) { + // Need to know if the IHM is done scrolling + _Global.document.addEventListener("MSManipulationStateChanged", _allManipulationChanged, false); + + globalEventsInitialized = true; + } + + if (this.closedDisplayMode === closedDisplayModes.none && this.layout === _Constants.appBarLayoutCommands) { + // Remove the commands layout _LegacyAppBar from the layout tree at this point so we don't cause unnecessary layout costs whenever + // the window resizes or when CSS changes are applied to the commands layout _LegacyAppBar's parent element. + this._element.style.display = "none"; + } + + this._winKeyboard = new _KeyboardBehavior._WinKeyboard(this._element); + + this._writeProfilerMark("constructor,StopTM"); + + return this; + }, { + // Public Properties + + /// The placement of the _LegacyAppBar on the display. Values are "top" or "bottom". + placement: { + get: function _LegacyAppBar_get_placement() { + return this._placement; + }, + set: function _LegacyAppBar_set_placement(value) { + // In designer we may have to move it + var wasShown = false; + if (_WinRT.Windows.ApplicationModel.DesignMode.designModeEnabled) { + this._hide(); + wasShown = true; + } + + if (this.opened) { + throw new _ErrorFromName("WinJS.UI._LegacyAppBar.CannotChangePlacementWhenVisible", strings.cannotChangePlacementWhenVisible); + } + + // Set placement, coerce invalid values to 'bottom' + this._placement = (value === _Constants.appBarPlacementTop) ? _Constants.appBarPlacementTop : _Constants.appBarPlacementBottom; + + // Clean up win-top, win-bottom styles + if (this._placement === _Constants.appBarPlacementTop) { + _ElementUtilities.addClass(this._element, _Constants.topClass); + _ElementUtilities.removeClass(this._element, _Constants.bottomClass); + } else if (this._placement === _Constants.appBarPlacementBottom) { + _ElementUtilities.removeClass(this._element, _Constants.topClass); + _ElementUtilities.addClass(this._element, _Constants.bottomClass); + } + + // Update our position on screen. + this._ensurePosition(); + if (wasShown) { + // Show again if we hid ourselves for the designer + this._show(); + } + } + }, + + _layout: { + get: function _LegacyAppBar_get_layout() { + return this._layoutImpl.type; + }, + set: function (layout) { + if (layout !== _Constants.appBarLayoutCommands && + layout !== _Constants.appBarLayoutCustom && + layout !== _Constants.appBarLayoutMenu) { + } + + // In designer we may have to redraw it + var wasShown = false; + if (_WinRT.Windows.ApplicationModel.DesignMode.designModeEnabled) { + this._hide(); + wasShown = true; + } + + if (this.opened) { + throw new _ErrorFromName("WinJS.UI._LegacyAppBar.CannotChangeLayoutWhenVisible", strings.cannotChangeLayoutWhenVisible); + } + + var commands; + if (!this._initializing) { + // Gather commands in preparation for hand off to new layout. + // We expect prev layout to return commands in the order they were set in, + // not necessarily the current DOM order the layout is using. + commands = this._layoutImpl.commandsInOrder; + this._layoutImpl.disconnect(); + } + + // Set layout + if (layout === _Constants.appBarLayoutCommands) { + this._layoutImpl = new _Layouts._AppBarCommandsLayout(); + } else if (layout === _Constants.appBarLayoutMenu) { + this._layoutImpl = new _Layouts._AppBarMenuLayout(); + } else { + // Custom layout uses Base _LegacyAppBar Layout class. + this._layoutImpl = new _Layouts._AppBarBaseLayout(); + } + this._layoutImpl.connect(this._element); + + if (commands && commands.length) { + // Reset _LegacyAppBar since layout changed. + this._layoutCommands(commands); + } + + // Show again if we hid ourselves for the designer + if (wasShown) { + this._show(); + } + }, + configurable: true + }, + + /// + /// Sets the AppBarCommands in the _LegacyAppBar. This property accepts an array of AppBarCommand objects. + /// + commands: { + set: function _LegacyAppBar_set_commands(commands) { + // Fail if trying to set when shown + if (this.opened) { + throw new _ErrorFromName("WinJS.UI._LegacyAppBar.CannotChangeCommandsWhenVisible", _Resources._formatString(_Overlay._Overlay.commonstrings.cannotChangeCommandsWhenVisible, "_LegacyAppBar")); + } + + // Dispose old commands before tossing them out. + if (!this._initializing) { + // AppBarCommands defined in markup don't want to be disposed during initialization. + this._disposeChildren(); + } + this._layoutCommands(commands); + } + }, + + _layoutCommands: function _LegacyAppBar_layoutCommands(commands) { + // Function precondition: _LegacyAppBar must not be shown. + + // Empties _LegacyAppBar HTML and repopulates with passed in commands. + _ElementUtilities.empty(this._element); + this._element.appendChild(this._invokeButton); // Keep our Show/Hide button. + + // In case they had only one command to set... + if (!Array.isArray(commands)) { + commands = [commands]; + } + + this._layoutImpl.layout(commands); + }, + + /// + /// Gets/Sets how _LegacyAppBar will display itself while hidden. Values are "none", "minimal" and '"compact". + /// + closedDisplayMode: { + get: function _LegacyAppBar_get_closedDisplayMode() { + return this._closedDisplayMode; + }, + set: function _LegacyAppBar_set_closedDisplayMode(value) { + var oldValue = this._closedDisplayMode; + + if (oldValue !== value) { + + // Determine if the visible position is changing. This can be used to determine if we need to delay updating closedDisplayMode related CSS classes + // to avoid affecting the animation. + var changeVisiblePosition = _ElementUtilities.hasClass(this._element, _Constants.hiddenClass) || _ElementUtilities.hasClass(this._element, _Constants.hidingClass); + + if (value === closedDisplayModes.none) { + this._closedDisplayMode = closedDisplayModes.none; + if (!changeVisiblePosition || !oldValue) { + _ElementUtilities.removeClass(this._element, _Constants.minimalClass); + _ElementUtilities.removeClass(this._element, _Constants.compactClass); + } + } else if (value === closedDisplayModes.minimal) { + this._closedDisplayMode = closedDisplayModes.minimal; + if (!changeVisiblePosition || !oldValue || oldValue === closedDisplayModes.none) { + _ElementUtilities.addClass(this._element, _Constants.minimalClass); + _ElementUtilities.removeClass(this._element, _Constants.compactClass); + } + } else { + // Compact is default fallback. + this._closedDisplayMode = closedDisplayModes.compact; + _ElementUtilities.addClass(this._element, _Constants.compactClass); + _ElementUtilities.removeClass(this._element, _Constants.minimalClass); + } + + // The invoke button has changed the amount of available space in the _LegacyAppBar. Layout might need to scale. + this._layoutImpl.resize(); + + if (changeVisiblePosition) { + // If the value is being set while we are not showing, change to our new position. + this._changeVisiblePosition(displayModeVisiblePositions[this._closedDisplayMode]); + } + } + }, + }, + + /// + opened: { + get: function () { + // Returns true if _LegacyAppBar is not 'hidden'. + return !_ElementUtilities.hasClass(this._element, _Constants.hiddenClass) && + !_ElementUtilities.hasClass(this._element, _Constants.hidingClass) && + this._doNext !== displayModeVisiblePositions.minimal && + this._doNext !== displayModeVisiblePositions.compact && + this._doNext !== displayModeVisiblePositions.none; + }, + set: function (opened) { + var currentlyOpen = this.opened; + if (opened && !currentlyOpen) { + this._show(); + } else if (!opened && currentlyOpen) { + this._hide(); + } + } + }, + + /// + /// Occurs immediately before the control is opened. + /// + onbeforeopen: createEvent(EVENTS.beforeOpen), + + /// + /// Occurs immediately after the control is opened. + /// + onafteropen: createEvent(EVENTS.afterOpen), + + /// + /// Occurs immediately before the control is closed. + /// + onbeforeclose: createEvent(EVENTS.beforeClose), + + /// + /// Occurs immediately after the control is closed. + /// + onafterclose: createEvent(EVENTS.afterClose), + + getCommandById: function (id) { + /// + /// + /// Retrieves the command with the specified ID from this _LegacyAppBar. + /// If more than one command is found, this method returns them all. + /// + /// Id of the command to return. + /// + /// The command found, an array of commands if more than one have the same ID, or null if no command is found. + /// + /// + var commands = this._layoutImpl.commandsInOrder.filter(function (command) { + return command.id === id || command.element.id === id; + }); + + if (commands.length === 1) { + return commands[0]; + } else if (commands.length === 0) { + return null; + } + + return commands; + }, + + showCommands: function (commands) { + /// + /// + /// Show the specified commands of the _LegacyAppBar. + /// + /// + /// An array of the commands to show. The array elements may be AppBarCommand objects, or the string identifiers (IDs) of commands. + /// + /// + if (!commands) { + throw new _ErrorFromName("WinJS.UI._LegacyAppBar.RequiresCommands", strings.requiresCommands); + } + + this._layoutImpl.showCommands(commands); + }, + + hideCommands: function (commands) { + /// + /// + /// Hides the specified commands of the _LegacyAppBar. + /// + /// Required. Command or Commands to hide, either String, DOM elements, or WinJS objects. + /// + if (!commands) { + throw new _ErrorFromName("WinJS.UI._LegacyAppBar.RequiresCommands", strings.requiresCommands); + } + + this._layoutImpl.hideCommands(commands); + }, + + showOnlyCommands: function (commands) { + /// + /// + /// Show the specified commands, hiding all of the others in the _LegacyAppBar. + /// + /// + /// An array of the commands to show. The array elements may be AppBarCommand objects, or the string identifiers (IDs) of commands. + /// + /// + if (!commands) { + throw new _ErrorFromName("WinJS.UI._LegacyAppBar.RequiresCommands", strings.requiresCommands); + } + + this._layoutImpl.showOnlyCommands(commands); + }, + + open: function () { + /// + /// + /// Opens the _LegacyAppBar, if closed and not disabled, regardless of other state. + /// + /// + // Just wrap the private one, turning off keyboard invoked flag + this._writeProfilerMark("show,StartTM"); + this._show(); + }, + + _show: function _LegacyAppBar_show() { + + var toPosition = displayModeVisiblePositions.shown; + var showing = null; + + // If we're already shown, we are just going to animate our position, not fire events or manage focus. + if (!this.disabled && (_ElementUtilities.hasClass(this._element, _Constants.hiddenClass) || _ElementUtilities.hasClass(this._element, _Constants.hidingClass))) { + showing = appbarShownState; + } + + this._changeVisiblePosition(toPosition, showing); + + if (showing) { + // Clean up tabbing behavior by making sure first and final divs are correct after showing. + this._updateFirstAndFinalDiv(); + + _LightDismissService.shown(this._dismissable); + } + }, + + close: function () { + /// + /// + /// Closes the _LegacyAppBar. + /// + /// + // Just wrap the private one + this._writeProfilerMark("hide,StartTM"); + this._hide(); + }, + + _hide: function _LegacyAppBar_hide(toPosition) { + + var toPosition = toPosition || displayModeVisiblePositions[this.closedDisplayMode]; + var hiding = null; + + // If were already hidden, we are just going to animate our position, not fire events or manage focus again. + if (!_ElementUtilities.hasClass(this._element, _Constants.hiddenClass) && !_ElementUtilities.hasClass(this._element, _Constants.hidingClass)) { + hiding = appbarHiddenState; + } + + this._changeVisiblePosition(toPosition, hiding); + }, + + _dispose: function _LegacyAppBar_dispose() { + _Dispose.disposeSubTree(this.element); + _LightDismissService.hidden(this._dismissable); + this._layoutImpl.dispose(); + this.disabled = true; + this.close(); + }, + + _disposeChildren: function _LegacyAppBar_disposeChildren() { + // Be purposeful about what we dispose. + this._layoutImpl.disposeChildren(); + }, + + _handleKeyDown: function _LegacyAppBar_handleKeyDown(event) { + // On Left/Right arrow keys, moves focus to previous/next AppbarCommand element. + + // If the current active element isn't an intrinsic part of the _LegacyAppBar, + // Layout might want to handle additional keys. + if (!this._invokeButton.contains(_Global.document.activeElement)) { + this._layoutImpl.handleKeyDown(event); + } + }, + + _visiblePixels: { + get: function () { + // Returns object containing pixel height of each visible position + return { + hidden: knownVisibleHeights.hidden, + minimal: knownVisibleHeights.minimal, + compact: Math.max(this._heightWithoutLabels || 0, knownVisibleHeights.compact), + // Element can change size as content gets added or removed or if it + // experinces style changes. We have to look this up at run time. + shown: this._element.offsetHeight, + }; + } + }, + + _visiblePosition: { + // Returns string value of our nearest, stationary, visible position. + get: function () { + // If we're animating into a new posistion, return the position we're animating into. + if (this._animating && displayModeVisiblePositions[this._element.winAnimating]) { + return this._element.winAnimating; + } else { + return this._lastPositionVisited; + } + } + }, + + _visible: { + // Returns true if our visible position is not completely hidden, else false. + get: function () { + return (this._visiblePosition !== displayModeVisiblePositions.none); + } + }, + + _changeVisiblePosition: function (toPosition, newState) { + /// + /// + /// Changes the visible position of the _LegacyAppBar. + /// + /// + /// Name of the visible position we want to move to. + /// + /// + /// Name of the state we are entering. Values can be "showing", "hiding" or null. + /// If the value is null, then we are not changing states, only changing visible position. + /// + /// + + if ((this._visiblePosition === toPosition && !this._keyboardObscured) || + (this.disabled && toPosition !== displayModeVisiblePositions.disabled)) { + // If we want to go where we already are, or we're disabled, return false. + this._afterPositionChange(null); + } else if (this._animating || this._needToHandleShowingKeyboard || this._needToHandleHidingKeyboard) { + // Only do one thing at a time. If we are already animating, + // or the IHM is animating, schedule this for later. + this._doNext = toPosition; + this._afterPositionChange(null); + } else { + // Begin position changing sequence. + + // Set the animating flag to block any queued position changes until we're done. + this._element.winAnimating = toPosition; + var performAnimation = this._initializing ? false : true; + + // Assume we are animating from the last position visited. + var fromPosition = this._lastPositionVisited; + + // We'll need to measure our element to determine how far we need to animate. + // Make sure we have accurate dimensions. + this._element.style.display = ""; + + // Are we hiding completely, or about to become visible? + var hidingCompletely = (toPosition === displayModeVisiblePositions.hidden); + + if (this._keyboardObscured) { + // We're changing position while covered by the IHM. + if (hidingCompletely) { + // If we're covered by the IHM we already look hidden. + // We can skip our animation and just hide. + performAnimation = false; + } else { + // Some portion of the _LegacyAppBar should be visible to users after its position changes. + + // Un-obscure ourselves and become visible to the user again. + // Need to animate to our desired position as if we were coming up from behind the keyboard. + fromPosition = displayModeVisiblePositions.hidden; + } + this._keyboardObscured = false; + } + + // Fire "before" event if we are changing state. + if (newState === appbarShownState) { + this._beforeShow(); + } else if (newState === appbarHiddenState) { + this._beforeHide(); + } + + // Position our element into the correct "end of animation" position, + // also accounting for any viewport scrolling or soft keyboard positioning. + this._ensurePosition(); + + this._element.style.opacity = 1; + this._element.style.visibility = "visible"; + + this._animationPromise = (performAnimation) ? this._animatePositionChange(fromPosition, toPosition) : Promise.wrap(); + this._animationPromise.then( + function () { this._afterPositionChange(toPosition, newState); }.bind(this), + function () { this._afterPositionChange(toPosition, newState); }.bind(this) + ); + } + }, + + _afterPositionChange: function _LegacyAppBar_afterPositionChange(newPosition, newState) { + // Defines body of work to perform after changing positions. + if (this._disposed) { + return; + } + + if (newPosition) { + + // Update closedDisplayMode related CSS classes, which were delayed from the closedDisplayMode setter to avoid affecting the animation + if (newPosition === displayModeVisiblePositions.minimal) { + _ElementUtilities.addClass(this._element, _Constants.minimalClass); + _ElementUtilities.removeClass(this._element, _Constants.compactClass); + } + + if (newPosition === displayModeVisiblePositions.hidden && this.closedDisplayMode === closedDisplayModes.none) { + _ElementUtilities.removeClass(this._element, _Constants.minimalClass); + _ElementUtilities.removeClass(this._element, _Constants.compactClass); + } + + // Clear animation flag and record having visited this position. + this._element.winAnimating = ""; + this._lastPositionVisited = newPosition; + + if (this._doNext === this._lastPositionVisited) { + this._doNext = ""; + } + + if (newState === appbarHiddenState) { + _LightDismissService.hidden(this._dismissable); + } + + if (newPosition === displayModeVisiblePositions.hidden) { + // Make sure animation is finished. + this._element.style.visibility = "hidden"; + this._element.style.display = "none"; + } + + // Clean up animation transforms. + var transformProperty = _BaseUtils._browserStyleEquivalents["transform"].scriptName; + this._element.style[transformProperty] = ""; + + // Fire "after" event if we changed state. + if (newState === appbarShownState) { + this._afterShow(); + } else if (newState === appbarHiddenState) { + this._afterHide(); + } + + // If we had something queued, do that + Scheduler.schedule(this._checkDoNext, Scheduler.Priority.normal, this, "WinJS.UI._LegacyAppBar._checkDoNext"); + } + + this._afterPositionChangeCallBack(); + }, + + _afterPositionChangeCallBack: function () { + // Leave this blank for unit tests to overwrite. + }, + + _beforeShow: function _LegacyAppBar_beforeShow() { + // In case their event 'beforeopen' event listener is going to manipulate commands, + // first see if there are any queued command animations we can handle while we're still hidden. + if (this._queuedCommandAnimation) { + this._showAndHideFast(this._queuedToShow, this._queuedToHide); + this._queuedToShow = []; + this._queuedToHide = []; + } + + // Make sure everything fits before showing + this._layoutImpl.scale(); + + if (this.closedDisplayMode === closedDisplayModes.compact) { + this._heightWithoutLabels = this._element.offsetHeight; + } + + _ElementUtilities.removeClass(this._element, _Constants.hiddenClass); + _ElementUtilities.addClass(this._element, _Constants.showingClass); + + // Send our "beforeopen" event + this._sendEvent(EVENTS.beforeOpen); + }, + + _afterShow: function _LegacyAppBar_afterShow() { + _ElementUtilities.removeClass(this._element, _Constants.showingClass); + _ElementUtilities.addClass(this._element, _Constants.shownClass); + + // Send our "afteropen" event + this._sendEvent(EVENTS.afterOpen); + this._writeProfilerMark("show,StopTM"); + }, + + _beforeHide: function _LegacyAppBar_beforeHide() { + + _ElementUtilities.removeClass(this._element, _Constants.shownClass); + _ElementUtilities.addClass(this._element, _Constants.hidingClass); + + // Send our "beforeclose" event + this._sendEvent(EVENTS.beforeClose); + }, + + _afterHide: function _LegacyAppBar_afterHide() { + + // In case their 'afterclose' event handler is going to manipulate commands, + // first see if there are any queued command animations we can handle now we're hidden. + if (this._queuedCommandAnimation) { + this._showAndHideFast(this._queuedToShow, this._queuedToHide); + this._queuedToShow = []; + this._queuedToHide = []; + } + + _ElementUtilities.removeClass(this._element, _Constants.hidingClass); + _ElementUtilities.addClass(this._element, _Constants.hiddenClass); + + // Send our "afterclose" event + this._sendEvent(EVENTS.afterClose); + this._writeProfilerMark("hide,StopTM"); + }, + + _animatePositionChange: function _LegacyAppBar_animatePositionChange(fromPosition, toPosition) { + // Determines and executes the proper transition between visible positions + + var layoutElementsAnimationPromise = this._layoutImpl.positionChanging(fromPosition, toPosition), + appBarElementAnimationPromise; + + // Get values in terms of pixels to perform animation. + var beginningVisiblePixelHeight = this._visiblePixels[fromPosition], + endingVisiblePixelHeight = this._visiblePixels[toPosition], + distance = Math.abs(endingVisiblePixelHeight - beginningVisiblePixelHeight), + offsetTop = (this._placement === _Constants.appBarPlacementTop) ? -distance : distance; + + if ((this._placement === _Constants.appBarPlacementTop) && + ((fromPosition === displayModeVisiblePositions.shown && + toPosition === displayModeVisiblePositions.compact) || + (fromPosition === displayModeVisiblePositions.compact && + toPosition === displayModeVisiblePositions.shown))) { + // Command icons remain in the same location on a top appbar + // when going from compact > shown or shown > compact. + offsetTop = 0; + } + + // Animate + if (endingVisiblePixelHeight > beginningVisiblePixelHeight) { + var fromOffset = { top: offsetTop + "px", left: "0px" }; + appBarElementAnimationPromise = Animations.showEdgeUI(this._element, fromOffset, { mechanism: "transition" }); + } else { + var toOffset = { top: offsetTop + "px", left: "0px" }; + appBarElementAnimationPromise = Animations.hideEdgeUI(this._element, toOffset, { mechanism: "transition" }); + } + + return Promise.join([layoutElementsAnimationPromise, appBarElementAnimationPromise]); + }, + + _checkDoNext: function _LegacyAppBar_checkDoNext() { + // Do nothing if we're still animating + if (this._animating || this._needToHandleShowingKeyboard || this._needToHandleHidingKeyboard || this._disposed) { + return; + } + + if (this._doNext === displayModeVisiblePositions.disabled || + this._doNext === displayModeVisiblePositions.hidden || + this._doNext === displayModeVisiblePositions.minimal || + this._doNext === displayModeVisiblePositions.compact) { + // Do hide first because animating commands would be easier + this._hide(this._doNext); + this._doNext = ""; + } else if (this._queuedCommandAnimation) { + // Do queued commands before showing if possible + this._showAndHideQueue(); + } else if (this._doNext === displayModeVisiblePositions.shown) { + // Show last so that we don't unnecessarily animate commands + this._show(); + this._doNext = ""; + } + }, + + // Set focus to the passed in _LegacyAppBar + _setFocusToAppBar: function _LegacyAppBar_setFocusToAppBar(useSetActive, scroller) { + if (!this._focusOnFirstFocusableElement(useSetActive, scroller)) { + // No first element, set it to appbar itself + _Overlay._Overlay._trySetActive(this._element, scroller); + } + }, + + _commandsUpdated: function _LegacyAppBar_commandsUpdated() { + // If we are still initializing then we don't have a layout yet so it doesn't need updating. + if (!this._initializing) { + this._layoutImpl.commandsUpdated(); + this._layoutImpl.scale(); + } + }, + + _beginAnimateCommands: function _LegacyAppBar_beginAnimateCommands(showCommands, hideCommands, otherVisibleCommands) { + // The parameters are 3 mutually exclusive arrays of win-command elements contained in this Overlay. + // 1) showCommands[]: All of the HIDDEN win-command elements that ARE scheduled to show. + // 2) hideCommands[]: All of the VISIBLE win-command elements that ARE scheduled to hide. + // 3) otherVisibleCommands[]: All VISIBLE win-command elements that ARE NOT scheduled to hide. + this._layoutImpl.beginAnimateCommands(showCommands, hideCommands, otherVisibleCommands); + }, + + _endAnimateCommands: function _LegacyAppBar_endAnimateCommands() { + this._layoutImpl.endAnimateCommands(); + this._endAnimateCommandsCallBack(); + }, + + _endAnimateCommandsCallBack: function _LegacyAppBar_endAnimateCommandsCallBack() { + // Leave this blank for unit tests to overwrite. + }, + + // Get the top offset for top appbars. + _getTopOfVisualViewport: function _LegacyAppBar_getTopOfVisualViewPort() { + return _Overlay._Overlay._keyboardInfo._visibleDocTop; + }, + + // Get the bottom offset for bottom appbars. + _getAdjustedBottom: function _LegacyAppBar_getAdjustedBottom() { + // Need the distance the IHM moved as well. + return _Overlay._Overlay._keyboardInfo._visibleDocBottomOffset; + }, + + _showingKeyboard: function _LegacyAppBar_showingKeyboard(event) { + // Remember keyboard showing state. + this._keyboardObscured = false; + this._needToHandleHidingKeyboard = false; + + // If we're already moved, then ignore the whole thing + if (_Overlay._Overlay._keyboardInfo._visible && this._alreadyInPlace()) { + return; + } + + this._needToHandleShowingKeyboard = true; + // If focus is in the appbar, don't cause scrolling. + if (this.opened && this._element.contains(_Global.document.activeElement)) { + event.ensuredFocusedElementInView = true; + } + + // Check if appbar moves or if we're ok leaving it obscured instead. + if (this._visible && this._placement !== _Constants.appBarPlacementTop && _Overlay._Overlay._isFlyoutVisible()) { + // Remember that we're obscured + this._keyboardObscured = true; + } else { + // Don't be obscured, clear _scrollHappened flag to give us inference later on when to re-show ourselves. + this._scrollHappened = false; + } + + // Also set timeout regardless, so we can clean up our _keyboardShowing flag. + var that = this; + _Global.setTimeout(function (e) { that._checkKeyboardTimer(e); }, _Overlay._Overlay._keyboardInfo._animationShowLength + _Overlay._Overlay._scrollTimeout); + }, + + _hidingKeyboard: function _LegacyAppBar_hidingKeyboard() { + // We'll either just reveal the current space under the IHM or restore the window height. + + // We won't be obscured + this._keyboardObscured = false; + this._needToHandleShowingKeyboard = false; + this._needToHandleHidingKeyboard = true; + + // We'll either just reveal the current space or resize the window + if (!_Overlay._Overlay._keyboardInfo._isResized) { + // If we're not completely hidden, only fake hiding under keyboard, or already animating, + // then snap us to our final position. + if (this._visible || this._animating) { + // Not resized, update our final position immediately + this._checkScrollPosition(); + this._element.style.display = ""; + } + this._needToHandleHidingKeyboard = false; + } + // Else resize should clear keyboardHiding. + }, + + _resize: function _LegacyAppBar_resize(event) { + // If we're hidden by the keyboard, then hide bottom appbar so it doesn't pop up twice when it scrolls + if (this._needToHandleShowingKeyboard) { + // Top is allowed to scroll off the top, but we don't want bottom to peek up when + // scrolled into view since we'll show it ourselves and don't want a stutter effect. + if (this._visible) { + if (this._placement !== _Constants.appBarPlacementTop && !this._keyboardObscured) { + // If viewport doesn't match window, need to vanish momentarily so it doesn't scroll into view, + // however we don't want to toggle the visibility="hidden" hidden flag. + this._element.style.display = "none"; + } + } + // else if we're top we stay, and if there's a flyout, stay obscured by the keyboard. + } else if (this._needToHandleHidingKeyboard) { + this._needToHandleHidingKeyboard = false; + if (this._visible || this._animating) { + // Snap to final position + this._checkScrollPosition(); + this._element.style.display = ""; + } + } + + // Make sure everything still fits. + if (!this._initializing) { + this._layoutImpl.resize(event); + } + }, + + _checkKeyboardTimer: function _LegacyAppBar_checkKeyboardTimer() { + if (!this._scrollHappened) { + this._mayEdgeBackIn(); + } + }, + + _manipulationChanged: function _LegacyAppBar_manipulationChanged(event) { + // See if we're at the not manipulating state, and we had a scroll happen, + // which is implicitly after the keyboard animated. + if (event.currentState === 0 && this._scrollHappened) { + this._mayEdgeBackIn(); + } + }, + + _mayEdgeBackIn: function _LegacyAppBar_mayEdgeBackIn() { + // May need to react to IHM being resized event + if (this._needToHandleShowingKeyboard) { + // If not top appbar or viewport isn't still at top, then need to show again + this._needToHandleShowingKeyboard = false; + // If obscured (IHM + flyout showing), it's ok to stay obscured. + // If bottom we have to move, or if top scrolled off screen. + if (!this._keyboardObscured && + (this._placement !== _Constants.appBarPlacementTop || _Overlay._Overlay._keyboardInfo._visibleDocTop !== 0)) { + var toPosition = this._visiblePosition; + this._lastPositionVisited = displayModeVisiblePositions.hidden; + this._changeVisiblePosition(toPosition, false); + } else { + // Ensure any animations dropped during the showing keyboard are caught up. + this._checkDoNext(); + } + } + this._scrollHappened = false; + }, + + _ensurePosition: function _LegacyAppBar_ensurePosition() { + // Position the _LegacyAppBar element relative to the top or bottom edge of the visible + // document, based on the the visible position we think we need to be in. + var offSet = this._computePositionOffset(); + this._element.style.bottom = offSet.bottom; + this._element.style.top = offSet.top; + + }, + + _computePositionOffset: function _LegacyAppBar_computePositionOffset() { + // Calculates and returns top and bottom offsets for the _LegacyAppBar element, relative to the top or bottom edge of the visible + // document. + var positionOffSet = {}; + + if (this._placement === _Constants.appBarPlacementBottom) { + // If the IHM is open, the bottom of the visual viewport may or may not be obscured + // Use _getAdjustedBottom to account for the IHM if it is covering the bottom edge. + positionOffSet.bottom = this._getAdjustedBottom() + "px"; + positionOffSet.top = ""; + } else if (this._placement === _Constants.appBarPlacementTop) { + positionOffSet.bottom = ""; + positionOffSet.top = this._getTopOfVisualViewport() + "px"; + } + + return positionOffSet; + }, + + _checkScrollPosition: function _LegacyAppBar_checkScrollPosition() { + // If IHM has appeared, then remember we may come in + if (this._needToHandleShowingKeyboard) { + // Tag that it's OK to edge back in. + this._scrollHappened = true; + return; + } + + // We only need to update if we're not completely hidden. + if (this._visible || this._animating) { + this._ensurePosition(); + // Ensure any animations dropped during the showing keyboard are caught up. + this._checkDoNext(); + } + }, + + _alreadyInPlace: function _LegacyAppBar_alreadyInPlace() { + // See if we're already where we're supposed to be. + var offSet = this._computePositionOffset(); + return (offSet.top === this._element.style.top && offSet.bottom === this._element.style.bottom); + }, + + // If there is a shown non-sticky _LegacyAppBar then it sets the firstDiv tabIndex to + // the minimum tabIndex found in the _LegacyAppBars and finalDiv to the max found. + // Otherwise sets their tabIndex to -1 so they are not tab stops. + _updateFirstAndFinalDiv: function _LegacyAppBar_updateFirstAndFinalDiv() { + var appBarFirstDiv = this._element.querySelectorAll("." + _Constants.firstDivClass); + appBarFirstDiv = appBarFirstDiv.length >= 1 ? appBarFirstDiv[0] : null; + + var appBarFinalDiv = this._element.querySelectorAll("." + _Constants.finalDivClass); + appBarFinalDiv = appBarFinalDiv.length >= 1 ? appBarFinalDiv[0] : null; + + // Remove the firstDiv & finalDiv if they are not at the appropriate locations + if (appBarFirstDiv && (this._element.children[0] !== appBarFirstDiv)) { + appBarFirstDiv.parentNode.removeChild(appBarFirstDiv); + appBarFirstDiv = null; + } + if (appBarFinalDiv && (this._element.children[this._element.children.length - 1] !== appBarFinalDiv)) { + appBarFinalDiv.parentNode.removeChild(appBarFinalDiv); + appBarFinalDiv = null; + } + + // Create and add the firstDiv & finalDiv if they don't already exist + if (!appBarFirstDiv) { + // Add a firstDiv that will be the first child of the appBar. + // On focus set focus to the last element of the AppBar. + appBarFirstDiv = _Global.document.createElement("div"); + // display: inline is needed so that the div doesn't take up space and cause the page to scroll on focus + appBarFirstDiv.style.display = "inline"; + appBarFirstDiv.className = _Constants.firstDivClass; + appBarFirstDiv.tabIndex = -1; + appBarFirstDiv.setAttribute("aria-hidden", "true"); + _ElementUtilities._addEventListener(appBarFirstDiv, "focusin", this._focusOnLastFocusableElementOrThis.bind(this), false); + // add to beginning + if (this._element.children[0]) { + this._element.insertBefore(appBarFirstDiv, this._element.children[0]); + } else { + this._element.appendChild(appBarFirstDiv); + } + } + if (!appBarFinalDiv) { + // Add a finalDiv that will be the last child of the appBar. + // On focus set focus to the first element of the AppBar. + appBarFinalDiv = _Global.document.createElement("div"); + // display: inline is needed so that the div doesn't take up space and cause the page to scroll on focus + appBarFinalDiv.style.display = "inline"; + appBarFinalDiv.className = _Constants.finalDivClass; + appBarFinalDiv.tabIndex = -1; + appBarFinalDiv.setAttribute("aria-hidden", "true"); + _ElementUtilities._addEventListener(appBarFinalDiv, "focusin", this._focusOnFirstFocusableElementOrThis.bind(this), false); + this._element.appendChild(appBarFinalDiv); + } + + + // invokeButton should be the second to last element in the _LegacyAppBar's tab order. Second to the finalDiv. + if (this._element.children[this._element.children.length - 2] !== this._invokeButton) { + this._element.insertBefore(this._invokeButton, appBarFinalDiv); + } + var elms = this._element.getElementsByTagName("*"); + var highestTabIndex = _ElementUtilities._getHighestTabIndexInList(elms); + this._invokeButton.tabIndex = highestTabIndex; + + // Update the tabIndex of the firstDiv & finalDiv + if (appBarFirstDiv) { + appBarFirstDiv.tabIndex = _ElementUtilities._getLowestTabIndexInList(elms); + } + if (appBarFinalDiv) { + appBarFinalDiv.tabIndex = highestTabIndex; + } + }, + + _writeProfilerMark: function _LegacyAppBar_writeProfilerMark(text) { + _WriteProfilerMark("WinJS.UI._LegacyAppBar:" + this._id + ":" + text); + } + }, { + // Statics + _Events: EVENTS, + }); + + return _LegacyAppBar; + }) + }); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +// Menu +/// Menu,Menus,Flyout,Flyouts,Statics +define('WinJS/Controls/Menu',[ + 'exports', + '../Core/_Global', + '../Core/_Base', + '../Core/_BaseUtils', + '../Core/_ErrorFromName', + '../Core/_Resources', + '../Core/_WriteProfilerMark', + '../Promise', + '../Utilities/_ElementUtilities', + '../Utilities/_Hoverable', + '../Utilities/_KeyboardBehavior', + './_LegacyAppBar/_Constants', + './Flyout', + './Flyout/_Overlay', + './Menu/_Command' +], function menuInit(exports, _Global, _Base, _BaseUtils, _ErrorFromName, _Resources, _WriteProfilerMark, Promise, _ElementUtilities, _Hoverable, _KeyboardBehavior, _Constants, Flyout, _Overlay, _Command) { + "use strict"; + + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + /// + /// Represents a menu flyout for displaying commands. + /// + /// + /// Menu + /// + /// + /// + /// + /// ]]> + /// Raised just before showing a menu. + /// Raised immediately after a menu is fully shown. + /// Raised just before hiding a menu. + /// Raised immediately after a menu is fully hidden. + /// The Menu control itself + /// + /// + Menu: _Base.Namespace._lazy(function () { + var Key = _ElementUtilities.Key; + + var strings = { + get ariaLabel() { return _Resources._getWinJSString("ui/menuAriaLabel").value; }, + get requiresCommands() { return "Invalid argument: commands must not be empty"; }, + get nullCommand() { return "Invalid argument: command must not be null"; }, + }; + + function isCommandInMenu(object) { + // Verifies that we have a menuCommand element and that it is in a Menu. + var element = object.element || object; + return _ElementUtilities._matchesSelector(element, "." + _Constants.menuClass + " " + "." + _Constants.menuCommandClass); + } + + var Menu = _Base.Class.derive(Flyout.Flyout, function Menu_ctor(element, options) { + /// + /// + /// Creates a new Menu control. + /// + /// + /// The DOM element that will host the control. + /// + /// + /// The set of properties and values to apply to the control. + /// + /// The new Menu control. + /// + /// + + // We need to be built on top of a Flyout, so stomp on the user's input + options = options || {}; + + // Make sure there's an input element + this._element = element || _Global.document.createElement("div"); + this._id = this._element.id || _ElementUtilities._uniqueID(this._element); + this._writeProfilerMark("constructor,StartTM"); + + // validate that if they didn't set commands, in which + // case any HTML only contains commands. Do this first + // so that we don't leave partial Menus in the DOM. + if (!options.commands && this._element) { + // Shallow copy object so we can modify it. + options = _BaseUtils._shallowCopy(options); + options.commands = this._verifyCommandsOnly(this._element, "WinJS.UI.MenuCommand"); + } + + // Remember aria role in case base constructor changes it + var role = this._element ? this._element.getAttribute("role") : null; + var label = this._element ? this._element.getAttribute("aria-label") : null; + + // Call the base overlay constructor helper + this._baseFlyoutConstructor(this._element, options); + + // Make sure we have an ARIA role + if (role === null || role === "" || role === undefined) { + this._element.setAttribute("role", "menu"); + } + if (label === null || label === "" || label === undefined) { + this._element.setAttribute("aria-label", strings.ariaLabel); + } + + // Handle "esc" & "up/down" key presses + this._element.addEventListener("keydown", this._handleKeyDown.bind(this), true); + this._element.addEventListener(_Constants._menuCommandInvokedEvent, this._handleCommandInvoked.bind(this), false); + this._element.addEventListener("mouseover", this._handleMouseOver.bind(this), false); + this._element.addEventListener("mouseout", this._handleMouseOut.bind(this), false); + + // Attach our css class + _ElementUtilities.addClass(this._element, _Constants.menuClass); + + this._winKeyboard = new _KeyboardBehavior._WinKeyboard(this._element); + + // Need to set our commands, making sure we're hidden first + this.hide(); + this._writeProfilerMark("constructor,StopTM"); + }, { + // Public Properties + + /// + /// Sets the MenuCommand objects that appear in the Menu. You can set this to a single MenuCommand or an array of MenuCommand objects. + /// + /// + commands: { + set: function (value) { + // Fail if trying to set when visible + if (!this.hidden) { + throw new _ErrorFromName("WinJS.UI.Menu.CannotChangeCommandsWhenVisible", _Resources._formatString(_Overlay._Overlay.commonstrings.cannotChangeCommandsWhenVisible, "Menu")); + } + + // Start from scratch + _ElementUtilities.empty(this._element); + + // In case they had only one... + if (!Array.isArray(value)) { + value = [value]; + } + + // Add commands + var len = value.length; + for (var i = 0; i < len; i++) { + this._addCommand(value[i]); + } + } + }, + + getCommandById: function (id) { + /// + /// + /// Retrieve the command with the specified ID from this Menu. If more than one command is found, all are returned. + /// + /// The ID of the command to find. + /// + /// The command found, an array of commands if more than one have the same ID, or null if no command is found. + /// + /// + /// + var commands = this.element.querySelectorAll("#" + id); + var newCommands = []; + for (var count = 0, len = commands.length; count < len; count++) { + if (commands[count].winControl) { + newCommands.push(commands[count].winControl); + } + } + + if (newCommands.length === 1) { + return newCommands[0]; + } else if (newCommands.length === 0) { + return null; + } + + return newCommands; + }, + + + showCommands: function (commands) { + /// + /// + /// Shows the specified commands of the Menu. + /// + /// + /// The commands to show. The array elements may be Menu objects, or the string identifiers (IDs) of commands. + /// + /// + /// + if (!commands) { + throw new _ErrorFromName("WinJS.UI.Menu.RequiresCommands", strings.requiresCommands); + } + + this._showCommands(commands, true); + }, + + hideCommands: function (commands) { + /// + /// + /// Hides the Menu. + /// + /// + /// Required. Command or Commands to hide, either String, DOM elements, or WinJS objects. + /// + /// + /// + if (!commands) { + throw new _ErrorFromName("WinJS.UI.Menu.RequiresCommands", strings.requiresCommands); + } + + this._hideCommands(commands, true); + }, + + showOnlyCommands: function (commands) { + /// + /// + /// Shows the specified commands of the Menu while hiding all other commands. + /// + /// + /// The commands to show. The array elements may be MenuCommand objects, or the string identifiers (IDs) of commands. + /// + /// + /// + if (!commands) { + throw new _ErrorFromName("WinJS.UI.Menu.RequiresCommands", strings.requiresCommands); + } + + this._showOnlyCommands(commands, true); + }, + + show: function (anchor, placement, alignment) { + /// + /// + /// Shows the Menu, if hidden, regardless of other states. + /// + /// + /// The DOM element, or ID of a DOM element, to anchor the Menu. This parameter overrides the anchor property for this method call only. + /// + /// + /// The placement of the Menu to the anchor: 'auto' (default), 'autohorizontal', 'autovertical', 'top', 'bottom', 'left', or 'right'. This parameter overrides the placement + /// property for this method call only. + /// + /// + /// For 'top' or 'bottom' placement, the alignment of the Menu to the anchor's edge: 'center' (default), 'left', or 'right'. This parameter + /// overrides the alignment property for this method call only. + /// + /// + /// + // Just call private version to make appbar flags happy + this._writeProfilerMark("show,StartTM"); // The corresponding "stop" profiler mark is handled in _Overlay._baseEndShow(). + this._show(anchor, placement, alignment); + }, + + _show: function Menu_show(anchor, placement, alignment) { + if (!_ElementUtilities.hasClass(this.element, _Constants.menuMouseSpacingClass) && !_ElementUtilities.hasClass(this.element, _Constants.menuTouchSpacingClass)) { + // The Menu's spacing shouldn't change while it is already shown. Only + // add a spacing class if it doesn't already have one. It will get + // removed after the Menu hides. + _ElementUtilities.addClass( + this.element, + Flyout.Flyout._cascadeManager.inputType === _KeyboardBehavior._InputTypes.mouse || Flyout.Flyout._cascadeManager.inputType === _KeyboardBehavior._InputTypes.keyboard ? + _Constants.menuMouseSpacingClass : + _Constants.menuTouchSpacingClass + ); + } + // Call flyout show + this._baseFlyoutShow(anchor, placement, alignment); + + // Menu will need to adjust MenuCommand layouts based on the various + // types of commands visible in our Menu, but only after we send the beforeshow + // event, so the developer has a chance to show or hide more commands. + // Flyout's _findPosition will make that call. + }, + + _hide: function Menu_hide() { + if (this._hoverPromise) { + this._hoverPromise.cancel(); + } + Flyout.Flyout.prototype._hide.call(this); + }, + + _beforeEndHide: function Menu_beforeEndHide() { + _ElementUtilities.removeClass(this.element, _Constants.menuMouseSpacingClass); + _ElementUtilities.removeClass(this.element, _Constants.menuTouchSpacingClass); + Flyout.Flyout.prototype._beforeEndHide.call(this); + }, + + _addCommand: function Menu_addCommand(command) { + if (!command) { + throw new _ErrorFromName("WinJS.UI.Menu.NullCommand", strings.nullCommand); + } + // See if it's a command already + if (!command._element) { + // Not a command, so assume it's options for a command + command = new _Command.MenuCommand(null, command); + } + // If we were attached somewhere else, detach us + if (command._element.parentElement) { + command._element.parentElement.removeChild(command._element); + } + + // Reattach us + this._element.appendChild(command._element); + }, + + _dispose: function Menu_dispose() { + if (this._hoverPromise) { + this._hoverPromise.cancel(); + } + Flyout.Flyout.prototype._dispose.call(this); + + }, + + _commandsUpdated: function Menu_commandsUpdated() { + if (!this.hidden) { + this._checkMenuCommands(); + } + }, + + // Called when we show/hide commands or by flyout's _findPosition when the Menu is showing. + _checkMenuCommands: function Menu_checkMenuCommands() { + var menuCommands = this._element.querySelectorAll(".win-command"), + hasToggleCommands = false, + hasFlyoutCommands = false; + if (menuCommands) { + for (var i = 0, len = menuCommands.length; i < len; i++) { + var menuCommand = menuCommands[i].winControl; + if (menuCommand && !menuCommand.hidden) { + if (!hasToggleCommands && menuCommand.type === _Constants.typeToggle) { + hasToggleCommands = true; + } + if (!hasFlyoutCommands && menuCommand.type === _Constants.typeFlyout) { + hasFlyoutCommands = true; + } + } + } + } + + _ElementUtilities[hasToggleCommands ? 'addClass' : 'removeClass'](this._element, _Constants.menuContainsToggleCommandClass); + _ElementUtilities[hasFlyoutCommands ? 'addClass' : 'removeClass'](this._element, _Constants.menuContainsFlyoutCommandClass); + }, + + _handleKeyDown: function Menu_handleKeyDown(event) { + if (event.keyCode === Key.upArrow) { + Menu._focusOnPreviousElement(this.element); + + // Prevent the page from scrolling + event.preventDefault(); + } else if (event.keyCode === Key.downArrow) { + Menu._focusOnNextElement(this.element); + + // Prevent the page from scrolling + event.preventDefault(); + } else if ((event.keyCode === Key.space || event.keyCode === Key.enter) + && (this.element === _Global.document.activeElement)) { + event.preventDefault(); + this.hide(); + } else if (event.keyCode === Key.tab) { + event.preventDefault(); + } + }, + + _handleFocusIn: function Menu_handleFocusIn(event) { + // Menu focuses commands on mouseover. We need to handle cases involving activated flyout commands + // to ensure that mousing over different commands in a menu closes that command's sub flyout. + var target = event.target; + if (isCommandInMenu(target)) { + var command = target.winControl; + if (_ElementUtilities.hasClass(command.element, _Constants.menuCommandFlyoutActivatedClass)) { + // If it's an activated 'flyout' typed command, move focus onto the command's subFlyout. + // We expect this will collapse all decendant Flyouts of the subFlyout from the cascade. + command.flyout.element.focus(); + } else { + // Deactivate any currently activated command in the Menu to subsequently trigger all subFlyouts descendants to collapse. + var activatedSiblingCommand = this.element.querySelector("." + _Constants.menuCommandFlyoutActivatedClass); + if (activatedSiblingCommand) { + _Command.MenuCommand._deactivateFlyoutCommand(activatedSiblingCommand); + } + } + } else if (target === this.element) { + // The Menu itself is receiving focus. Rely on the Flyout base implementation to notify the cascadeManager. + // We expect this will only happen when other Menu event handling code causes the Menu to focus itself. + Flyout.Flyout.prototype._handleFocusIn.call(this, event); + } + }, + + _handleCommandInvoked: function Menu_handleCommandInvoked(event) { + // Cascading Menus hide when invoking a command commits an action, not when invoking a command opens a subFlyout. + if (this._hoverPromise) { + // Prevent pending duplicate invoke triggered via hover. + this._hoverPromise.cancel(); + } + var command = event.detail.command; + if (command._type !== _Constants.typeFlyout && command._type !== _Constants.typeSeparator) { + this._lightDismiss(); // Collapse all Menus/Flyouts. + } + }, + + _hoverPromise: null, + _handleMouseOver: function Menu_handleMouseOver(event) { + var target = event.target; + if (isCommandInMenu(target)) { + var command = target.winControl, + that = this; + + if (target.focus) { + target.focus(); + // remove keyboard focus rect since focus has been triggered by mouse over. + _ElementUtilities.removeClass(target, "win-keyboard"); + + if (command.type === _Constants.typeFlyout && command.flyout && command.flyout.hidden) { + this._hoverPromise = this._hoverPromise || Promise.timeout(_Constants.menuCommandHoverDelay).then( + function () { + if (!that.hidden && !that._disposed) { + command._invoke(event); + } + that._hoverPromise = null; + }, + function () { + that._hoverPromise = null; + }); + } + } + } + }, + + _handleMouseOut: function Menu_handleMouseOut(event) { + var target = event.target; + if (isCommandInMenu(target) && !target.contains(event.relatedTarget)) { + if (target === _Global.document.activeElement) { + // Menu gives focus to the menu itself + this.element.focus(); + } + if (this._hoverPromise) { + this._hoverPromise.cancel(); + } + } + }, + + _writeProfilerMark: function Menu_writeProfilerMark(text) { + _WriteProfilerMark("WinJS.UI.Menu:" + this._id + ":" + text); + } + }); + + // Statics + + // Set focus to next focusable element in the menu (loop if necessary). + // Note: The loop works by first setting focus to the menu itself. If the menu is + // what had focus before, then we break. Otherwise we try the first child next. + // Focus remains on the menu if nothing is focusable. + Menu._focusOnNextElement = function (menu) { + var _currentElement = _Global.document.activeElement; + + do { + if (_currentElement === menu) { + _currentElement = _currentElement.firstElementChild; + } else { + _currentElement = _currentElement.nextElementSibling; + } + + if (_currentElement) { + _currentElement.focus(); + } else { + _currentElement = menu; + } + + } while (_currentElement !== _Global.document.activeElement); + }; + + // Set focus to previous focusable element in the menu (loop if necessary). + // Note: The loop works by first setting focus to the menu itself. If the menu is + // what had focus before, then we break. Otherwise we try the last child next. + // Focus remains on the menu if nothing is focusable. + Menu._focusOnPreviousElement = function (menu) { + var _currentElement = _Global.document.activeElement; + + do { + if (_currentElement === menu) { + _currentElement = _currentElement.lastElementChild; + } else { + _currentElement = _currentElement.previousElementSibling; + } + + if (_currentElement) { + _currentElement.focus(); + } else { + _currentElement = menu; + } + + } while (_currentElement !== _Global.document.activeElement); + }; + + return Menu; + }) + }); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('WinJS/Controls/AutoSuggestBox/_SearchSuggestionManagerShim',[ + 'exports', + '../../_Signal', + '../../Core/_Base', + '../../Core/_BaseUtils', + '../../Core/_Events', + '../../BindingList', +], function SearchSuggestionManagerShimInit(exports, _Signal, _Base, _BaseUtils, _Events, BindingList) { + "use strict"; + + var CollectionChange = { + reset: 0, + itemInserted: 1, + itemRemoved: 2, + itemChanged: 3 + }; + var SearchSuggestionKind = { + Query: 0, + Result: 1, + Separator: 2 + }; + + var SuggestionVectorShim = _Base.Class.derive(Array, function SuggestionVectorShim_ctor() { + }, { + reset: function () { + this.length = 0; + this.dispatchEvent("vectorchanged", { collectionChange: CollectionChange.reset, index: 0 }); + }, + + insert: function (index, data) { + this.splice(index, 0, data); + this.dispatchEvent("vectorchanged", { collectionChange: CollectionChange.itemInserted, index: index }); + }, + + remove: function (index) { + this.splice(index, 1); + this.dispatchEvent("vectorchanged", { collectionChange: CollectionChange.itemRemoved, index: index }); + }, + }); + _Base.Class.mix(SuggestionVectorShim, _Events.eventMixin); + + var SearchSuggestionCollectionShim = _Base.Class.define(function SearchSuggestionCollectionShim_ctor() { + this._data = []; + }, { + size: { + get: function () { + return this._data.length; + } + }, + + appendQuerySuggestion: function (text) { + this._data.push({ kind: SearchSuggestionKind.Query, text: text }); + }, + appendQuerySuggestions: function (suggestions) { + suggestions.forEach(this.appendQuerySuggestion.bind(this)); + }, + appendResultSuggestion: function (text, detailText, tag, imageUrl, imageAlternateText) { + // 'image' must be null (not undefined) for SearchBox to fallback to use imageUrl instead + this._data.push({ kind: SearchSuggestionKind.Result, text: text, detailText: detailText, tag: tag, imageUrl: imageUrl, imageAlternateText: imageAlternateText, image: null }); + }, + appendSearchSeparator: function (label) { + this._data.push({ kind: SearchSuggestionKind.Separator, text: label }); + } + }); + + var SuggestionsRequestedEventArgShim = _Base.Class.define(function SuggestionsRequestedEventArgShim_ctor(queryText, language, linguisticDetails) { + this._queryText = queryText; + this._language = language; + this._linguisticDetails = linguisticDetails; + this._searchSuggestionCollection = new SearchSuggestionCollectionShim(); + }, { + language: { + get: function () { + return this._language; + } + }, + linguisticDetails: { + get: function () { + return this._linguisticDetails; + } + }, + queryText: { + get: function () { + return this._queryText; + } + }, + searchSuggestionCollection: { + get: function () { + return this._searchSuggestionCollection; + } + }, + getDeferral: function () { + return this._deferralSignal || (this._deferralSignal = new _Signal()); + }, + + _deferralSignal: null, + }); + + var SearchSuggestionManagerShim = _Base.Class.define(function SearchSuggestionManagerShim_ctor() { + this._updateVector = this._updateVector.bind(this); + + this._suggestionVector = new SuggestionVectorShim(); + this._query = ""; + this._history = { "": [] }; + + this._dataSource = []; + + this.searchHistoryContext = ""; + this.searchHistoryEnabled = true; + }, { + addToHistory: function (queryText /*, language */) { + if (!queryText || !queryText.trim()) { + return; + } + + var history = this._history[this.searchHistoryContext]; + var dupeIndex = -1; + for (var i = 0, l = history.length; i < l; i++) { + var item = history[i]; + if (item.text.toLowerCase() === queryText.toLowerCase()) { + dupeIndex = i; + break; + } + } + if (dupeIndex >= 0) { + history.splice(dupeIndex, 1); + } + + history.splice(0, 0, { text: queryText, kind: SearchSuggestionKind.Query }); + this._updateVector(); + }, + + clearHistory: function () { + this._history[this.searchHistoryContext] = []; + this._updateVector(); + }, + + setLocalContentSuggestionSettings: function (settings) { + }, + + setQuery: function (queryText) { + var that = this; + function update(arr) { + that._dataSource = arr; + that._updateVector(); + } + + this._query = queryText; + var arg = new SuggestionsRequestedEventArgShim(queryText); + this.dispatchEvent("suggestionsrequested", { request: arg }); + if (arg._deferralSignal) { + arg._deferralSignal.promise.then(update.bind(this, arg.searchSuggestionCollection._data)); + } else { + update(arg.searchSuggestionCollection._data); + } + }, + + searchHistoryContext: { + get: function () { + return "" + this._searchHistoryContext; + }, + set: function (value) { + value = "" + value; + if (!this._history[value]) { + this._history[value] = []; + } + this._searchHistoryContext = value; + } + }, + + searchHistoryEnabled: { + get: function () { + return this._searchHistoryEnabled; + }, + set: function (value) { + this._searchHistoryEnabled = value; + } + }, + + suggestions: { + get: function () { + return this._suggestionVector; + } + }, + + _updateVector: function () { + // Can never clear the entire suggestions list or it will cause a visual flash because + // the SearchBox control removes the suggestions list UI when the SSM fires vectorChanged + // with size === 0, then re-renders it when the first suggestion is added. + // Workaround is to insert a dummy entry, remove all old entries, add the new set of + // eligible suggestions, then remove the dummy entry. + this.suggestions.insert(this.suggestions.length, { text: "", kind: SearchSuggestionKind.Query }); + + while (this.suggestions.length > 1) { + this.suggestions.remove(0); + } + + var index = 0; + var added = {}; + if (this.searchHistoryEnabled) { + var q = this._query.toLowerCase(); + this._history[this.searchHistoryContext].forEach(function (item) { + var text = item.text.toLowerCase(); + if (text.indexOf(q) === 0) { + this.suggestions.insert(index, item); + added[text] = true; + index++; + } + }, this); + } + this._dataSource.forEach(function (item) { + if (item.kind === SearchSuggestionKind.Query) { + if (!added[item.text.toLowerCase()]) { + this.suggestions.insert(index, item); + index++; + } + } else { + this.suggestions.insert(index, item); + index++; + } + }, this); + + this.suggestions.remove(this.suggestions.length - 1); + }, + }); + _Base.Class.mix(SearchSuggestionManagerShim, _Events.eventMixin); + + _Base.Namespace._moduleDefine(exports, null, { + _CollectionChange: CollectionChange, + _SearchSuggestionKind: SearchSuggestionKind, + _SearchSuggestionManagerShim: SearchSuggestionManagerShim, + }); +}); + +define('require-style!less/styles-autosuggestbox',[],function(){}); + +define('require-style!less/colors-autosuggestbox',[],function(){}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('WinJS/Controls/AutoSuggestBox',[ + "exports", + "../Core/_Global", + "../Core/_WinRT", + "../Core/_Base", + "../Core/_ErrorFromName", + "../Core/_Events", + "../Core/_Resources", + "../Utilities/_Control", + "../Utilities/_ElementListUtilities", + "../Utilities/_ElementUtilities", + '../Utilities/_Hoverable', + "../_Accents", + "../Animations", + "../BindingList", + "../Promise", + "./Repeater", + "./AutoSuggestBox/_SearchSuggestionManagerShim", + "require-style!less/styles-autosuggestbox", + "require-style!less/colors-autosuggestbox" +], function autoSuggestBoxInit(exports, _Global, _WinRT, _Base, _ErrorFromName, _Events, _Resources, _Control, _ElementListUtilities, _ElementUtilities, _Hoverable, _Accents, Animations, BindingList, Promise, Repeater, _SuggestionManagerShim) { + "use strict"; + + _Accents.createAccentRule("html.win-hoverable .win-autosuggestbox .win-autosuggestbox-suggestion-selected:hover", [{ name: "background-color", value: _Accents.ColorTypes.listSelectHover }]); + _Accents.createAccentRule(".win-autosuggestbox .win-autosuggestbox-suggestion-selected", [{ name: "background-color", value: _Accents.ColorTypes.listSelectRest }]); + _Accents.createAccentRule(".win-autosuggestbox .win-autosuggestbox-suggestion-selected.win-autosuggestbox-suggestion-selected:hover:active", [{ name: "background-color", value: _Accents.ColorTypes.listSelectPress }]); + + var ClassNames = { + asb: "win-autosuggestbox", + asbDisabled: "win-autosuggestbox-disabled", + asbFlyout: "win-autosuggestbox-flyout", + asbFlyoutAbove: "win-autosuggestbox-flyout-above", + asbBoxFlyoutHighlightText: "win-autosuggestbox-flyout-highlighttext", + asbHitHighlightSpan: "win-autosuggestbox-hithighlight-span", + asbInput: "win-autosuggestbox-input", + asbInputFocus: "win-autosuggestbox-input-focus", + asbSuggestionQuery: "win-autosuggestbox-suggestion-query", + asbSuggestionResult: "win-autosuggestbox-suggestion-result", + asbSuggestionResultText: "win-autosuggestbox-suggestion-result-text", + asbSuggestionResultDetailedText: "win-autosuggestbox-suggestion-result-detailed-text", + asbSuggestionSelected: "win-autosuggestbox-suggestion-selected", + asbSuggestionSeparator: "win-autosuggestbox-suggestion-separator", + }; + + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + /// + /// + /// A rich input box that provides suggestions as the user types. + /// + /// + /// + /// + /// + /// ]]> + /// Raised when user or app changes the query text. + /// Raised when user presses Enter. + /// Raised when user clicks one of the displayed suggestions. + /// Raised when the system requests suggestions from this app. + /// Styles the entire Auto Suggest Box control. + /// Styles the query input box. + /// Styles the result suggestions flyout. + /// Styles the query type suggestion. + /// Styles the result type suggestion. + /// Styles the currently selected suggestion. + /// Styles the separator type suggestion. + /// + /// + AutoSuggestBox: _Base.Namespace._lazy(function () { + var Key = _ElementUtilities.Key; + + var EventNames = { + querychanged: "querychanged", + querysubmitted: "querysubmitted", + resultsuggestionchosen: "resultsuggestionchosen", + suggestionsrequested: "suggestionsrequested" + }; + + var Strings = { + get duplicateConstruction() { return "Invalid argument: Controls may only be instantiated one time for each DOM element"; }, + get invalidSuggestionKind() { return "Error: Invalid suggestion kind."; }, + + get ariaLabel() { return _Resources._getWinJSString("ui/autoSuggestBoxAriaLabel").value; }, + get ariaLabelInputNoPlaceHolder() { return _Resources._getWinJSString("ui/autoSuggestBoxAriaLabelInputNoPlaceHolder").value; }, + get ariaLabelInputPlaceHolder() { return _Resources._getWinJSString("ui/autoSuggestBoxAriaLabelInputPlaceHolder").value; }, + get ariaLabelQuery() { return _Resources._getWinJSString("ui/autoSuggestBoxAriaLabelQuery").value; }, + get ariaLabelResult() { return _Resources._getWinJSString("ui/autoSuggestBoxAriaLabelResult").value; }, + get ariaLabelSeparator() { return _Resources._getWinJSString("ui/autoSuggestBoxAriaLabelSeparator").value; }, + }; + + var AutoSuggestBox = _Base.Class.define(function asb_ctor(element, options) { + /// + /// + /// Creates a new AutoSuggestBox. + /// + /// + /// The DOM element that hosts the AutoSuggestBox. + /// + /// + /// An object that contains one or more property/value pairs to apply to the new control. + /// Each property of the options object corresponds to one of the control's properties or events. + /// Event names must begin with "on". For example, to provide a handler for the querychanged event, + /// add a property named "onquerychanged" to the options object and set its value to the event handler. + /// This parameter is optional. + /// + /// + /// The new AutoSuggestBox. + /// + /// + /// + element = element || _Global.document.createElement("div"); + options = options || {}; + + if (element.winControl) { + throw new _ErrorFromName("WinJS.UI.AutoSuggestBox.DuplicateConstruction", Strings.duplicateConstruction); + } + + this._suggestionsChangedHandler = this._suggestionsChangedHandler.bind(this); + this._suggestionsRequestedHandler = this._suggestionsRequestedHandler.bind(this); + + this._element = element; + element.winControl = this; + element.classList.add(ClassNames.asb); + element.classList.add("win-disposable"); + + this._setupDOM(); + this._setupSSM(); + + this._chooseSuggestionOnEnter = false; + this._currentFocusedIndex = -1; + this._currentSelectedIndex = -1; + this._flyoutOpenPromise = Promise.wrap(); + this._lastKeyPressLanguage = ""; + this._prevLinguisticDetails = this._getLinguisticDetails(); + this._prevQueryText = ""; + + _Control.setOptions(this, options); + + this._hideFlyout(); + }, { + /// + /// Raised when user clicks on one of the suggestions displayed. + /// + /// + onresultsuggestionchosen: _Events._createEventProperty(EventNames.resultsuggestionchosen), + + /// + /// Raised when user or app changes the query text. + /// + /// + onquerychanged: _Events._createEventProperty(EventNames.querychanged), + + /// + /// Raised when user submits the current query. + /// + /// + onquerysubmitted: _Events._createEventProperty(EventNames.querysubmitted), + + /// + /// Raised when Windows requests search suggestions from the app. + /// + /// + onsuggestionsrequested: _Events._createEventProperty(EventNames.suggestionsrequested), + + /// + element: { + get: function () { + return this._element; + } + }, + + /// + /// Gets or sets whether the first suggestion is chosen when the user presses Enter. When set to true, as the user types in the input box, a + /// focus rectangle is drawn on the first suggestion (if present and no IME composition in progress). Pressing enter will behave the same as + /// if clicked on the focused suggestion, and the down arrow key press will put real focus to the second suggestion and the up arrow key will + /// remove focus. + /// + /// + chooseSuggestionOnEnter: { + get: function () { + return this._chooseSuggestionOnEnter; + }, + set: function (value) { + this._chooseSuggestionOnEnter = !!value; + } + }, + + /// + /// Gets or sets a value that specifies whether the AutoSuggestBox is disabled. + /// + /// + disabled: { + get: function () { + return this._inputElement.disabled; + }, + set: function (value) { + if (this._inputElement.disabled === !!value) { + return; + } + + if (!value) { + this._enableControl(); + } else { + this._disableControl(); + } + } + }, + + /// + /// Gets or sets the placeholder text for the AutoSuggestBox. This text is displayed if there is no other text in the input box. + /// + /// + placeholderText: { + get: function () { + return this._inputElement.placeholder; + }, + set: function (value) { + this._inputElement.placeholder = value; + this._updateInputElementAriaLabel(); + } + }, + + /// + /// Gets or sets the query text for the AutoSuggestBox. + /// + /// + queryText: { + get: function () { + return this._inputElement.value; + }, + set: function (value) { + this._inputElement.value = ""; // This finalizes the IME composition + this._inputElement.value = value; + } + }, + + /// + /// Gets or sets a value that specifies whether history is disabled for the AutoSuggestBox. The default value is false. + /// + /// + searchHistoryDisabled: { + get: function () { + return !this._suggestionManager.searchHistoryEnabled; + }, + set: function (value) { + this._suggestionManager.searchHistoryEnabled = !value; + } + }, + + /// + /// Gets or sets the search history context for the AutoSuggestBox. The search history context string is used as a secondary key for storing search history. + /// (The primary key is the AppId.) An app can use the search history context string to store different search histories based on the context of the application. + /// If you don't set this property, the system assumes that all searches in your app occur in the same context. + /// If you update this property while the search pane is open with suggestions showing, the changes won't take effect until the user enters the next character. + /// + /// + searchHistoryContext: { + get: function () { + return this._suggestionManager.searchHistoryContext; + }, + set: function (value) { + this._suggestionManager.searchHistoryContext = value; + } + }, + + dispose: function asb_dispose() { + /// + /// + /// Disposes this control. + /// + /// + /// + if (this._disposed) { + return; + } + + // Cancel pending promises. + this._flyoutOpenPromise.cancel(); + + this._suggestions.removeEventListener("vectorchanged", this._suggestionsChangedHandler); + this._suggestionManager.removeEventListener("suggestionsrequested", this._suggestionsRequestedHandler); + + this._suggestionManager = null; + this._suggestions = null; + this._hitFinder = null; + + this._disposed = true; + }, + + setLocalContentSuggestionSettings: function asb_setLocalContentSuggestionSettings(settings) { + /// + /// + /// Specifies whether suggestions based on local files are automatically displayed in the input field, and defines the criteria that + /// the system uses to locate and filter these suggestions. + /// + /// + /// The new settings for local content suggestions. + /// + /// + /// + this._suggestionManager.setLocalContentSuggestionSettings(settings); + }, + + // Constructor Helpers + _setupDOM: function asb_setupDOM() { + var flyoutPointerReleasedHandler = this._flyoutPointerReleasedHandler.bind(this); + var inputOrImeChangeHandler = this._inputOrImeChangeHandler.bind(this); + + // Root element + if (!this._element.getAttribute("aria-label")) { + this._element.setAttribute("aria-label", Strings.ariaLabel); + } + this._element.setAttribute("role", "group"); + + // Input element + this._inputElement = _Global.document.createElement("input"); + this._inputElement.autocorrect = "off"; + this._inputElement.type = "search"; + this._inputElement.classList.add(ClassNames.asbInput); + this._inputElement.classList.add("win-textbox"); + this._inputElement.setAttribute("role", "textbox"); + this._inputElement.addEventListener("keydown", this._keyDownHandler.bind(this)); + this._inputElement.addEventListener("keypress", this._keyPressHandler.bind(this)); + this._inputElement.addEventListener("keyup", this._keyUpHandler.bind(this)); + this._inputElement.addEventListener("focus", this._inputFocusHandler.bind(this)); + this._inputElement.addEventListener("blur", this._inputBlurHandler.bind(this)); + this._inputElement.addEventListener("input", inputOrImeChangeHandler); + this._inputElement.addEventListener("compositionstart", inputOrImeChangeHandler); + this._inputElement.addEventListener("compositionupdate", inputOrImeChangeHandler); + this._inputElement.addEventListener("compositionend", inputOrImeChangeHandler); + _ElementUtilities._addEventListener(this._inputElement, "pointerdown", this._inputPointerDownHandler.bind(this)); + this._updateInputElementAriaLabel(); + this._element.appendChild(this._inputElement); + var context = this._tryGetInputContext(); + if (context) { + context.addEventListener("MSCandidateWindowShow", this._msCandidateWindowShowHandler.bind(this)); + context.addEventListener("MSCandidateWindowHide", this._msCandidateWindowHideHandler.bind(this)); + } + + // Flyout element + this._flyoutElement = _Global.document.createElement("div"); + this._flyoutElement.classList.add(ClassNames.asbFlyout); + this._flyoutElement.addEventListener("blur", this._flyoutBlurHandler.bind(this)); + _ElementUtilities._addEventListener(this._flyoutElement, "pointerup", flyoutPointerReleasedHandler); + _ElementUtilities._addEventListener(this._flyoutElement, "pointercancel", flyoutPointerReleasedHandler); + _ElementUtilities._addEventListener(this._flyoutElement, "pointerout", flyoutPointerReleasedHandler); + _ElementUtilities._addEventListener(this._flyoutElement, "pointerdown", this._flyoutPointerDownHandler.bind(this)); + this._element.appendChild(this._flyoutElement); + + // Repeater + var that = this; + function repeaterTemplate(suggestion) { + return that._renderSuggestion(suggestion); + } + this._suggestionsData = new BindingList.List(); + this._repeaterElement = _Global.document.createElement("div"); + this._repeater = new Repeater.Repeater(this._repeaterElement, { + data: this._suggestionsData, + template: repeaterTemplate, + }); + _ElementUtilities._ensureId(this._repeaterElement); + this._repeaterElement.setAttribute("role", "listbox"); + this._repeaterElement.setAttribute("aria-live", "polite"); + this._flyoutElement.appendChild(this._repeaterElement); + }, + + _setupSSM: function asb_setupSSM() { + // Get the search suggestion provider if it is available + this._suggestionManager = new _SuggestionManagerShim._SearchSuggestionManagerShim(); + this._suggestions = this._suggestionManager.suggestions; + + this._suggestions.addEventListener("vectorchanged", this._suggestionsChangedHandler); + this._suggestionManager.addEventListener("suggestionsrequested", this._suggestionsRequestedHandler); + }, + + // Flyout functions + _hideFlyout: function asb_hideFlyout() { + if (this._isFlyoutShown()) { + this._flyoutElement.style.display = "none"; + } + }, + + _showFlyout: function asb_showFlyout() { + var prevNumSuggestions = this._prevNumSuggestions || 0; + this._prevNumSuggestions = this._suggestionsData.length; + + if (this._isFlyoutShown() && prevNumSuggestions === this._suggestionsData.length) { + return; + } + + if (this._suggestionsData.length === 0) { + return; + } + + this._flyoutElement.style.display = "block"; + + var inputRect = this._inputElement.getBoundingClientRect(); + var flyoutRect = this._flyoutElement.getBoundingClientRect(); + var documentClientWidth = _Global.document.documentElement.clientWidth; + + // Display above vs below - the ASB flyout always opens in the direction where there is more space + var spaceAbove = inputRect.top; + var spaceBelow = _Global.document.documentElement.clientHeight - inputRect.bottom; + this._flyoutBelowInput = spaceBelow >= spaceAbove; + if (this._flyoutBelowInput) { + this._flyoutElement.classList.remove(ClassNames.asbFlyoutAbove); + this._flyoutElement.scrollTop = 0; + } else { + this._flyoutElement.classList.add(ClassNames.asbFlyoutAbove); + this._flyoutElement.scrollTop = this._flyoutElement.scrollHeight - this._flyoutElement.clientHeight; + } + + this._addFlyoutIMEPaddingIfRequired(); + + // Align left vs right edge + var alignRight; + if (_Global.getComputedStyle(this._flyoutElement).direction === "rtl") { + // RTL: Align to the right edge if there is enough space to the left of the control's + // right edge, or if there is not enough space to fit the flyout aligned to either edge. + alignRight = ((inputRect.right - flyoutRect.width) >= 0) || ((inputRect.left + flyoutRect.width) > documentClientWidth); + + } else { + // LTR: Align to the right edge if there isn't enough space to the right of the control's + // left edge, but there is enough space to the left of the control's right edge. + alignRight = ((inputRect.left + flyoutRect.width) > documentClientWidth) && ((inputRect.right - flyoutRect.width) >= 0); + } + + if (alignRight) { + this._flyoutElement.style.left = (inputRect.width - flyoutRect.width - this._element.clientLeft) + "px"; + } else { + this._flyoutElement.style.left = "-" + this._element.clientLeft + "px"; + } + + // ms-scroll-chaining:none will still chain scroll parent element if child div does + // not have a scroll bar. Prevent this by setting and updating touch action + this._flyoutElement.style.touchAction = this._flyoutElement.scrollHeight > flyoutRect.height ? "pan-y" : "none"; + + this._flyoutOpenPromise.cancel(); + var animationKeyframe = this._flyoutBelowInput ? "WinJS-flyoutBelowASB-showPopup" : "WinJS-flyoutAboveASB-showPopup"; + this._flyoutOpenPromise = Animations.showPopup(this._flyoutElement, { top: "0px", left: "0px", keyframe: animationKeyframe }); + }, + + _addFlyoutIMEPaddingIfRequired: function asb_addFlyoutIMEPaddingIfRequired() { + // Check if we have InputContext APIs + var context = this._tryGetInputContext(); + if (!context) { + return; + } + + // Check if flyout is visible and below input + if (!this._isFlyoutShown() || !this._flyoutBelowInput) { + return; + } + + // Check if IME is occluding flyout + var flyoutRect = this._flyoutElement.getBoundingClientRect(); + var imeRect = context.getCandidateWindowClientRect(); + var inputRect = this._inputElement.getBoundingClientRect(); + var flyoutTop = inputRect.bottom; + var flyoutBottom = inputRect.bottom + flyoutRect.height; + if (imeRect.top > flyoutBottom || imeRect.bottom < flyoutTop) { + return; + } + + // Shift the flyout down or to the right depending on IME/ASB width ratio. + // When the IME width is less than 45% of the ASB's width, the flyout gets + // shifted right, otherwise shifted down. + var animation = Animations.createRepositionAnimation(this._flyoutElement); + if (imeRect.width < (inputRect.width * 0.45)) { + this._flyoutElement.style.marginLeft = imeRect.width + "px"; + } else { + this._flyoutElement.style.marginTop = (imeRect.bottom - imeRect.top + 4) + "px"; + } + animation.execute(); + }, + + _findNextSuggestionElementIndex: function asb_findNextSuggestionElementIndex(curIndex) { + // Returns -1 if there are no focusable elements after curIndex + // Returns first element if curIndex < 0 + var startIndex = curIndex < 0 ? 0 : curIndex + 1; + for (var i = startIndex; i < this._suggestionsData.length; i++) { + if ((this._repeater.elementFromIndex(i)) && (this._isSuggestionSelectable(this._suggestionsData.getAt(i)))) { + return i; + } + } + return -1; + }, + + _findPreviousSuggestionElementIndex: function asb_findPreviousSuggestionElementIndex(curIndex) { + // Returns -1 if there are no focusable elements before curIndex + // Returns last element if curIndex >= suggestionsdata.length + var startIndex = curIndex >= this._suggestionsData.length ? this._suggestionsData.length - 1 : curIndex - 1; + for (var i = startIndex; i >= 0; i--) { + if ((this._repeater.elementFromIndex(i)) && (this._isSuggestionSelectable(this._suggestionsData.getAt(i)))) { + return i; + } + } + return -1; + }, + + _isFlyoutShown: function asb_isFlyoutShown() { + return (this._flyoutElement.style.display !== "none"); + }, + + _isSuggestionSelectable: function asb_isSuggestionSelectable(suggestion) { + return ((suggestion.kind === _SuggestionManagerShim._SearchSuggestionKind.Query) || + (suggestion.kind === _SuggestionManagerShim._SearchSuggestionKind.Result)); + }, + + _processSuggestionChosen: function asb_processSuggestionChosen(item, event) { + this.queryText = item.text; + if (item.kind === _SuggestionManagerShim._SearchSuggestionKind.Query) { + this._submitQuery(item.text, false /*fillLinguisticDetails*/, event); // force empty linguistic details since explicitly chosen suggestion from list + } else if (item.kind === _SuggestionManagerShim._SearchSuggestionKind.Result) { + this._fireEvent(EventNames.resultsuggestionchosen, { + tag: item.tag, + keyModifiers: getKeyModifiers(event), + storageFile: null + }); + } + this._hideFlyout(); + }, + + _selectSuggestionAtIndex: function asb_selectSuggestionAtIndex(indexToSelect) { + var that = this; + function scrollToView(targetElement) { + var popupHeight = that._flyoutElement.getBoundingClientRect().bottom - that._flyoutElement.getBoundingClientRect().top; + if ((targetElement.offsetTop + targetElement.offsetHeight) > (that._flyoutElement.scrollTop + popupHeight)) { + // Element to scroll is below popup visible area + var scrollDifference = (targetElement.offsetTop + targetElement.offsetHeight) - (that._flyoutElement.scrollTop + popupHeight); + _ElementUtilities._zoomTo(that._flyoutElement, { contentX: 0, contentY: (that._flyoutElement.scrollTop + scrollDifference), viewportX: 0, viewportY: 0 }); + } else if (targetElement.offsetTop < that._flyoutElement.scrollTop) { + // Element to scroll is above popup visible area + _ElementUtilities._zoomTo(that._flyoutElement, { contentX: 0, contentY: targetElement.offsetTop, viewportX: 0, viewportY: 0 }); + } + } + + // Sets focus on the specified element and removes focus from others. + // Clears selection if index is outside of suggestiondata index range. + var curElement = null; + for (var i = 0; i < this._suggestionsData.length; i++) { + curElement = this._repeater.elementFromIndex(i); + if (i !== indexToSelect) { + curElement.classList.remove(ClassNames.asbSuggestionSelected); + curElement.setAttribute("aria-selected", "false"); + } else { + curElement.classList.add(ClassNames.asbSuggestionSelected); + scrollToView(curElement); + curElement.setAttribute("aria-selected", "true"); + } + } + this._currentSelectedIndex = indexToSelect; + if (curElement) { + this._inputElement.setAttribute("aria-activedescendant", this._repeaterElement.id + indexToSelect); + } else if (this._inputElement.hasAttribute("aria-activedescendant")) { + this._inputElement.removeAttribute("aria-activedescendant"); + } + }, + + _updateFakeFocus: function asb_updateFakeFocus() { + var firstElementIndex; + if (this._isFlyoutShown() && (this._chooseSuggestionOnEnter)) { + firstElementIndex = this._findNextSuggestionElementIndex(-1); + } else { + // This will clear the fake focus. + firstElementIndex = -1; + } + + this._selectSuggestionAtIndex(firstElementIndex); + }, + + _updateQueryTextWithSuggestionText: function asb_updateQueryTextWithSuggestionText(suggestionIndex) { + if ((suggestionIndex >= 0) && (suggestionIndex < this._suggestionsData.length)) { + this.queryText = this._suggestionsData.getAt(suggestionIndex).text; + } + }, + + // Helpers + _disableControl: function asb_disableControl() { + if (this._isFlyoutShown()) { + this._hideFlyout(); + } + this._element.disabled = true; + this._element.classList.add(ClassNames.asbDisabled); + this._inputElement.disabled = true; + }, + + _enableControl: function asb_enableControl() { + this._element.disabled = false; + this._element.classList.remove(ClassNames.asbDisabled); + this._inputElement.disabled = false; + if (_Global.document.activeElement === this._element) { + _ElementUtilities._setActive(this._inputElement); + } + }, + + _fireEvent: function asb_fireEvent(type, detail) { + // Returns true if ev.preventDefault() was not called + var event = _Global.document.createEvent("CustomEvent"); + event.initCustomEvent(type, true, true, detail); + return this._element.dispatchEvent(event); + }, + + _getLinguisticDetails: function asb_getLinguisticDetails(useCache, createFilled) { // createFilled=false always creates an empty linguistic details object, otherwise generate it or use the cache + function createQueryLinguisticDetails(compositionAlternatives, compositionStartOffset, compositionLength, queryTextPrefix, queryTextSuffix) { + var linguisticDetails = null; + + // The linguistic alternatives we receive are only for the composition string being composed. We need to provide the linguistic alternatives + // in the form of the full query text with alternatives embedded. + var fullCompositionAlternatives = []; + for (var i = 0; i < compositionAlternatives.length; i++) { + fullCompositionAlternatives[i] = queryTextPrefix + compositionAlternatives[i] + queryTextSuffix; + } + + if (_WinRT.Windows.ApplicationModel.Search.SearchQueryLinguisticDetails) { + try { + linguisticDetails = new _WinRT.Windows.ApplicationModel.Search.SearchQueryLinguisticDetails(fullCompositionAlternatives, compositionStartOffset, compositionLength); + } catch (e) { + // WP10 currently exposes SQLD API but throws on instantiation. + } + } + + if (!linguisticDetails) { + // If we're in web compartment, create a script version of the WinRT SearchQueryLinguisticDetails object + linguisticDetails = { + queryTextAlternatives: fullCompositionAlternatives, + queryTextCompositionStart: compositionStartOffset, + queryTextCompositionLength: compositionLength + }; + } + return linguisticDetails; + } + + var linguisticDetails = null; + if ((this._inputElement.value === this._prevQueryText) && useCache && this._prevLinguisticDetails && createFilled) { + linguisticDetails = this._prevLinguisticDetails; + } else { + var compositionAlternatives = []; + var compositionStartOffset = 0; + var compositionLength = 0; + var queryTextPrefix = ""; + var queryTextSuffix = ""; + if (createFilled) { + var context = this._tryGetInputContext(); + if (context && context.getCompositionAlternatives) { + compositionAlternatives = context.getCompositionAlternatives(); + compositionStartOffset = context.compositionStartOffset; + compositionLength = context.compositionEndOffset - context.compositionStartOffset; + + if ((this._inputElement.value !== this._prevQueryText) || (this._prevCompositionLength === 0) || (compositionLength > 0)) { + queryTextPrefix = this._inputElement.value.substring(0, compositionStartOffset); + queryTextSuffix = this._inputElement.value.substring(compositionStartOffset + compositionLength); + } else { + // composition ended, but alternatives have been kept, need to reuse the previous query prefix/suffix, but still report to the client that the composition has ended (start & length of composition of 0) + queryTextPrefix = this._inputElement.value.substring(0, this._prevCompositionStart); + queryTextSuffix = this._inputElement.value.substring(this._prevCompositionStart + this._prevCompositionLength); + } + } + } + linguisticDetails = createQueryLinguisticDetails(compositionAlternatives, compositionStartOffset, compositionLength, queryTextPrefix, queryTextSuffix); + } + return linguisticDetails; + }, + + _isElementInSearchControl: function asb_isElementInSearchControl(targetElement) { + return this.element.contains(targetElement) || (this.element === targetElement); + }, + + _renderSuggestion: function asb_renderSuggestion(suggestion) { + var root = null; + if (!suggestion) { + return root; + } + if (suggestion.kind === _SuggestionManagerShim._SearchSuggestionKind.Query) { + root = querySuggestionRenderer(this, suggestion); + } else if (suggestion.kind === _SuggestionManagerShim._SearchSuggestionKind.Separator) { + root = separatorSuggestionRenderer(suggestion); + } else if (suggestion.kind === _SuggestionManagerShim._SearchSuggestionKind.Result) { + root = resultSuggestionRenderer(this, suggestion); + } else { + throw new _ErrorFromName("WinJS.UI.AutoSuggestBox.invalidSuggestionKind", Strings.invalidSuggestionKind); + } + return root; + }, + + _shouldIgnoreInput: function asb_shouldIgnoreInput() { + var processingIMEFocusLossKey = this._isProcessingDownKey || this._isProcessingUpKey || this._isProcessingTabKey || this._isProcessingEnterKey; + return processingIMEFocusLossKey || this._isFlyoutPointerDown; + }, + + _submitQuery: function asb_submitQuery(queryText, fillLinguisticDetails, event) { + if (this._disposed) { + return; + } + + // get the most up to date value of the input langauge from WinRT if available + if (_WinRT.Windows.Globalization.Language) { + this._lastKeyPressLanguage = _WinRT.Windows.Globalization.Language.currentInputMethodLanguageTag; + } + + this._fireEvent(EventNames.querysubmitted, { + language: this._lastKeyPressLanguage, + linguisticDetails: this._getLinguisticDetails(true /*useCache*/, fillLinguisticDetails), // allow caching, but generate empty linguistic details if suggestion is used + queryText: queryText, + keyModifiers: getKeyModifiers(event) + }); + + if (this._suggestionManager) { + this._suggestionManager.addToHistory(this._inputElement.value, this._lastKeyPressLanguage); + } + }, + + _tryGetInputContext: function asb_tryGetInputContext() { + // On WP, msGetInputContext is defined but throws when invoked + if (this._inputElement.msGetInputContext) { + try { + return this._inputElement.msGetInputContext(); + } catch (e) { + return null; + } + } + return null; + }, + + _updateInputElementAriaLabel: function asb_updateInputElementAriaLabel() { + this._inputElement.setAttribute("aria-label", + this._inputElement.placeholder ? _Resources._formatString(Strings.ariaLabelInputPlaceHolder, this._inputElement.placeholder) : Strings.ariaLabelInputNoPlaceHolder + ); + }, + + // Event Handlers + _flyoutBlurHandler: function asb_flyoutBlurHandler(event) { + if (this._isElementInSearchControl(_Global.document.activeElement)) { + this._internalFocusMove = true; + } else { + this._element.classList.remove(ClassNames.asbInputFocus); + this._hideFlyout(); + } + }, + + _flyoutPointerDownHandler: function asb_flyoutPointerDownHandler(ev) { + var that = this; + var srcElement = ev.target; + function findSuggestionElementIndex() { + if (srcElement) { + for (var i = 0; i < that._suggestionsData.length; i++) { + if (that._repeater.elementFromIndex(i) === srcElement) { + return i; + } + } + } + return -1; + } + + this._isFlyoutPointerDown = true; + while (srcElement && (srcElement.parentNode !== this._repeaterElement)) { + srcElement = srcElement.parentNode; + } + var index = findSuggestionElementIndex(); + if ((index >= 0) && (index < this._suggestionsData.length) && (this._currentFocusedIndex !== index)) { + if (this._isSuggestionSelectable(this._suggestionsData.getAt(index))) { + this._currentFocusedIndex = index; + this._selectSuggestionAtIndex(index); + this._updateQueryTextWithSuggestionText(this._currentFocusedIndex); + } + } + // Prevent default so focus does not leave input element. + ev.preventDefault(); + }, + + _flyoutPointerReleasedHandler: function asb_flyoutPointerReleasedHandler() { + this._isFlyoutPointerDown = false; + + if (this._reflowImeOnPointerRelease) { + this._reflowImeOnPointerRelease = false; + var animation = Animations.createRepositionAnimation(this._flyoutElement); + this._flyoutElement.style.marginTop = ""; + this._flyoutElement.style.marginLeft = ""; + animation.execute(); + } + }, + + _inputBlurHandler: function asb_inputBlurHandler(event) { + // Hide flyout if focus is leaving the control + if (!this._isElementInSearchControl(_Global.document.activeElement)) { + this._element.classList.remove(ClassNames.asbInputFocus); + this._hideFlyout(); + } + this.queryText = this._prevQueryText; // Finalize IME composition + this._isProcessingDownKey = false; + this._isProcessingUpKey = false; + this._isProcessingTabKey = false; + this._isProcessingEnterKey = false; + }, + + _inputFocusHandler: function asb_inputFocusHandler(event) { + // Refresh hit highlighting if text has changed since focus was present + // This can happen if the user committed a suggestion previously. + if (this._inputElement.value !== this._prevQueryText) { + if (_WinRT.Windows.Data.Text.SemanticTextQuery) { + if (this._inputElement.value !== "") { + this._hitFinder = new _WinRT.Windows.Data.Text.SemanticTextQuery(this._inputElement.value, this._inputElement.lang); + } else { + this._hitFinder = null; + } + } + } + + // If focus is returning to the input box from outside the control, show the flyout and refresh the suggestions + if (event.target === this._inputElement && !this._internalFocusMove) { + this._showFlyout(); + if (this._currentFocusedIndex !== -1) { + // Focus is not in input + this._selectSuggestionAtIndex(this._currentFocusedIndex); + } else { + this._updateFakeFocus(); + } + + this._suggestionManager.setQuery( + this._inputElement.value, + this._lastKeyPressLanguage, + this._getLinguisticDetails(true /*useCache*/, true /*createFilled*/) + ); + } + + this._internalFocusMove = false; + this._element.classList.add(ClassNames.asbInputFocus); + }, + + _inputOrImeChangeHandler: function asb_inputImeChangeHandler() { + var that = this; + function hasLinguisticDetailsChanged(newLinguisticDetails) { + var hasLinguisticDetailsChanged = false; + if ((that._prevLinguisticDetails.queryTextCompositionStart !== newLinguisticDetails.queryTextCompositionStart) || + (that._prevLinguisticDetails.queryTextCompositionLength !== newLinguisticDetails.queryTextCompositionLength) || + (that._prevLinguisticDetails.queryTextAlternatives.length !== newLinguisticDetails.queryTextAlternatives.length)) { + hasLinguisticDetailsChanged = true; + } + that._prevLinguisticDetails = newLinguisticDetails; + return hasLinguisticDetailsChanged; + } + + // swallow the IME change event that gets fired when composition is ended due to keyboarding down to the suggestion list & mouse down on the button + if (!this._shouldIgnoreInput()) { + var linguisticDetails = this._getLinguisticDetails(false /*useCache*/, true /*createFilled*/); // never cache on explicit user changes + var hasLinguisticDetailsChanged = hasLinguisticDetailsChanged(linguisticDetails); // updates this._prevLinguisticDetails + + // Keep the previous composition cache up to date, execpt when composition ended with no text change and alternatives are kept. + // In that case, we need to use the cached values to correctly generate the query prefix/suffix for substituting alternatives, but still report to the client that the composition has ended (via start & length of composition of 0) + if ((this._inputElement.value !== this._prevQueryText) || (this._prevCompositionLength === 0) || (linguisticDetails.queryTextCompositionLength > 0)) { + this._prevCompositionStart = linguisticDetails.queryTextCompositionStart; + this._prevCompositionLength = linguisticDetails.queryTextCompositionLength; + } + + if ((this._prevQueryText === this._inputElement.value) && !hasLinguisticDetailsChanged) { + // Sometimes the input change is fired even if there is no change in input. + // Swallow event in those cases. + return; + } + this._prevQueryText = this._inputElement.value; + + // get the most up to date value of the input langauge from WinRT if available + if (_WinRT.Windows.Globalization.Language) { + this._lastKeyPressLanguage = _WinRT.Windows.Globalization.Language.currentInputMethodLanguageTag; + } + + if (_WinRT.Windows.Data.Text.SemanticTextQuery) { + if (this._inputElement.value !== "") { + this._hitFinder = new _WinRT.Windows.Data.Text.SemanticTextQuery(this._inputElement.value, this._lastKeyPressLanguage); + } else { + this._hitFinder = null; + } + } + + this._fireEvent(EventNames.querychanged, { + language: this._lastKeyPressLanguage, + queryText: this._inputElement.value, + linguisticDetails: linguisticDetails + }); + + this._suggestionManager.setQuery( + this._inputElement.value, + this._lastKeyPressLanguage, + linguisticDetails + ); + } + }, + + _inputPointerDownHandler: function asb_inputPointerDownHandler() { + if ((_Global.document.activeElement === this._inputElement) && (this._currentSelectedIndex !== -1)) { + this._currentFocusedIndex = -1; + this._selectSuggestionAtIndex(this._currentFocusedIndex); + } + }, + + _keyDownHandler: function asb_keyDownHandler(event) { + var that = this; + function setSelection(index) { + that._currentFocusedIndex = index; + that._selectSuggestionAtIndex(index); + event.preventDefault(); + event.stopPropagation(); + } + + this._lastKeyPressLanguage = event.locale; + if (event.keyCode === Key.tab) { + this._isProcessingTabKey = true; + } else if (event.keyCode === Key.upArrow) { + this._isProcessingUpKey = true; + } else if (event.keyCode === Key.downArrow) { + this._isProcessingDownKey = true; + } else if ((event.keyCode === Key.enter) && (event.locale === "ko")) { + this._isProcessingEnterKey = true; + } + // Ignore keys handled by ime. + if (event.keyCode !== Key.IME) { + if (event.keyCode === Key.tab) { + var closeFlyout = true; + if (event.shiftKey) { + if (this._currentFocusedIndex !== -1) { + // Focus is not in input + setSelection(-1); + closeFlyout = false; + } + } else if (this._currentFocusedIndex === -1) { + this._currentFocusedIndex = + this._flyoutBelowInput + ? this._findNextSuggestionElementIndex(this._currentFocusedIndex) + : this._findPreviousSuggestionElementIndex(this._suggestionsData.length); + if (this._currentFocusedIndex !== -1) { + // Found a selectable element + setSelection(this._currentFocusedIndex); + this._updateQueryTextWithSuggestionText(this._currentFocusedIndex); + closeFlyout = false; + } + } + + if (closeFlyout) { + this._hideFlyout(); + } + } else if (event.keyCode === Key.escape) { + if (this._currentFocusedIndex !== -1) { + // Focus is not in input + this.queryText = this._prevQueryText; + setSelection(-1); + } else if (this.queryText !== "") { + this.queryText = ""; + this._inputOrImeChangeHandler(null); + event.preventDefault(); + event.stopPropagation(); + } + } else if ((this._flyoutBelowInput && event.keyCode === Key.upArrow) || (!this._flyoutBelowInput && event.keyCode === Key.downArrow)) { + var prevIndex; + if (this._currentSelectedIndex !== -1) { + prevIndex = this._findPreviousSuggestionElementIndex(this._currentSelectedIndex); + // Restore user entered query when user navigates back to input. + if (prevIndex === -1) { + this.queryText = this._prevQueryText; + } + } else { + prevIndex = this._findPreviousSuggestionElementIndex(this._suggestionsData.length); + } + setSelection(prevIndex); + this._updateQueryTextWithSuggestionText(this._currentFocusedIndex); + } else if ((this._flyoutBelowInput && event.keyCode === Key.downArrow) || (!this._flyoutBelowInput && event.keyCode === Key.upArrow)) { + var nextIndex = this._findNextSuggestionElementIndex(this._currentSelectedIndex); + // Restore user entered query when user navigates back to input. + if ((this._currentSelectedIndex !== -1) && (nextIndex === -1)) { + this.queryText = this._prevQueryText; + } + setSelection(nextIndex); + this._updateQueryTextWithSuggestionText(this._currentFocusedIndex); + } else if (event.keyCode === Key.enter) { + if (this._currentSelectedIndex === -1) { + this._submitQuery(this._inputElement.value, true /*fillLinguisticDetails*/, event); + } else { + this._processSuggestionChosen(this._suggestionsData.getAt(this._currentSelectedIndex), event); + } + this._hideFlyout(); + } + } + }, + + _keyUpHandler: function asb_keyUpHandler(event) { + if (event.keyCode === Key.tab) { + this._isProcessingTabKey = false; + } else if (event.keyCode === Key.upArrow) { + this._isProcessingUpKey = false; + } else if (event.keyCode === Key.downArrow) { + this._isProcessingDownKey = false; + } else if (event.keyCode === Key.enter) { + this._isProcessingEnterKey = false; + } + }, + + _keyPressHandler: function asb_keyPressHandler(event) { + this._lastKeyPressLanguage = event.locale; + }, + + _msCandidateWindowHideHandler: function asb_msCandidateWindowHideHandler() { + if (!this._isFlyoutPointerDown) { + var animation = Animations.createRepositionAnimation(this._flyoutElement); + this._flyoutElement.style.marginTop = ""; + this._flyoutElement.style.marginLeft = ""; + animation.execute(); + } else { + this._reflowImeOnPointerRelease = true; + } + }, + + _msCandidateWindowShowHandler: function asb_msCandidateWindowShowHandler() { + this._addFlyoutIMEPaddingIfRequired(); + this._reflowImeOnPointerRelease = false; + }, + + _suggestionsChangedHandler: function asb_suggestionsChangedHandler(event) { + var collectionChange = event.collectionChange || event.detail.collectionChange; + var changeIndex = (+event.index === event.index) ? event.index : event.detail.index; + var ChangeEnum = _SuggestionManagerShim._CollectionChange; + if (collectionChange === ChangeEnum.reset) { + if (this._isFlyoutShown()) { + this._hideFlyout(); + } + this._suggestionsData.splice(0, this._suggestionsData.length); + } else if (collectionChange === ChangeEnum.itemInserted) { + var suggestion = this._suggestions[changeIndex]; + this._suggestionsData.splice(changeIndex, 0, suggestion); + + this._showFlyout(); + + } else if (collectionChange === ChangeEnum.itemRemoved) { + if ((this._suggestionsData.length === 1)) { + _ElementUtilities._setActive(this._inputElement); + + this._hideFlyout(); + } + this._suggestionsData.splice(changeIndex, 1); + } else if (collectionChange === ChangeEnum.itemChanged) { + var suggestion = this._suggestions[changeIndex]; + if (suggestion !== this._suggestionsData.getAt(changeIndex)) { + this._suggestionsData.setAt(changeIndex, suggestion); + } else { + // If the suggestions manager gives us an identical item, it means that only the hit highlighted text has changed. + var existingElement = this._repeater.elementFromIndex(changeIndex); + if (_ElementUtilities.hasClass(existingElement, ClassNames.asbSuggestionQuery)) { + addHitHighlightedText(existingElement, suggestion, suggestion.text); + } else { + var resultSuggestionDiv = existingElement.querySelector("." + ClassNames.asbSuggestionResultText); + if (resultSuggestionDiv) { + addHitHighlightedText(resultSuggestionDiv, suggestion, suggestion.text); + var resultSuggestionDetailDiv = existingElement.querySelector("." + ClassNames.asbSuggestionResultDetailedText); + if (resultSuggestionDetailDiv) { + addHitHighlightedText(resultSuggestionDetailDiv, suggestion, suggestion.detailText); + } + } + } + } + } + + if (_Global.document.activeElement === this._inputElement) { + this._updateFakeFocus(); + } + }, + + _suggestionsRequestedHandler: function asb_suggestionsRequestedHandler(event) { + // get the most up to date value of the input langauge from WinRT if available + if (_WinRT.Windows.Globalization.Language) { + this._lastKeyPressLanguage = _WinRT.Windows.Globalization.Language.currentInputMethodLanguageTag; + } + + var request = event.request || event.detail.request; + var deferral; + this._fireEvent(EventNames.suggestionsrequested, { + setPromise: function (promise) { + deferral = request.getDeferral(); + promise.then(function () { + deferral.complete(); + }); + }, + searchSuggestionCollection: request.searchSuggestionCollection, + language: this._lastKeyPressLanguage, + linguisticDetails: this._getLinguisticDetails(true /*useCache*/, true /*createFilled*/), + queryText: this._inputElement.value + }); + }, + }, { + createResultSuggestionImage: function asb_createResultSuggestionImage(url) { + /// + /// + /// Creates the image argument for SearchSuggestionCollection.appendResultSuggestion. + /// + /// + /// The url of the image. + /// + /// + /// + if (_WinRT.Windows.Foundation.Uri && _WinRT.Windows.Storage.Streams.RandomAccessStreamReference) { + return _WinRT.Windows.Storage.Streams.RandomAccessStreamReference.createFromUri(new _WinRT.Windows.Foundation.Uri(url)); + } + return url; + }, + + _EventNames: EventNames, + + _sortAndMergeHits: function asb_sortAndMergeHits(hitsProvided) { + function hitStartPositionAscendingSorter(firstHit, secondHit) { + var returnValue = 0; + if (firstHit.startPosition < secondHit.startPosition) { + returnValue = -1; + } else if (firstHit.startPosition > secondHit.startPosition) { + returnValue = 1; + } + return returnValue; + } + function hitIntersectionReducer(reducedHits, nextHit, currentIndex) { + if (currentIndex === 0) { + reducedHits.push(nextHit); + } else { + var curHit = reducedHits[reducedHits.length - 1]; + var curHitEndPosition = curHit.startPosition + curHit.length; + if (nextHit.startPosition <= curHitEndPosition) { + // The next hit intersects or is next to current hit. Merge it. + var nextHitEndPosition = nextHit.startPosition + nextHit.length; + if (nextHitEndPosition > curHitEndPosition) { + curHit.length = nextHitEndPosition - curHit.startPosition; + } + } else { + // No intersection, simply add to reduced list. + reducedHits.push(nextHit); + } + } + return reducedHits; + } + + var reducedHits = []; + if (hitsProvided) { + // Copy hitsprovided array as winrt objects are immutable. + var hits = new Array(hitsProvided.length); + for (var i = 0; i < hitsProvided.length; i++) { + hits.push({ startPosition: hitsProvided[i].startPosition, length: hitsProvided[i].length }); + } + hits.sort(hitStartPositionAscendingSorter); + hits.reduce(hitIntersectionReducer, reducedHits); + } + return reducedHits; + } + }); + + function addHitHighlightedText(element, item, text, hitFinder) { + function addNewSpan(element, textContent, insertBefore) { + // Adds new span element with specified inner text as child to element, placed before insertBefore + var spanElement = _Global.document.createElement("span"); + spanElement.textContent = textContent; + spanElement.setAttribute("aria-hidden", "true"); + spanElement.classList.add(ClassNames.asbHitHighlightSpan); + element.insertBefore(spanElement, insertBefore); + return spanElement; + } + + if (text) { + // Remove any existing hit highlighted text spans + _ElementListUtilities.query("." + ClassNames.asbHitHighlightSpan, element).forEach(function (childElement) { + childElement.parentNode.removeChild(childElement); + }); + + // Insert spans at the front of element + var firstChild = element.firstChild; + + var hitsProvided = item.hits; + if ((!hitsProvided) && (hitFinder) && (item.kind !== _SuggestionManagerShim._SearchSuggestionKind.Separator)) { + hitsProvided = hitFinder.find(text); + } + + var hits = AutoSuggestBox._sortAndMergeHits(hitsProvided); + + var lastPosition = 0; + for (var i = 0; i < hits.length; i++) { + var hit = hits[i]; + + // Add previous normal text + addNewSpan(element, text.substring(lastPosition, hit.startPosition), firstChild); + + lastPosition = hit.startPosition + hit.length; + + // Add hit highlighted text + var spanHitHighlightedText = addNewSpan(element, text.substring(hit.startPosition, lastPosition), firstChild); + _ElementUtilities.addClass(spanHitHighlightedText, ClassNames.asbBoxFlyoutHighlightText); + } + + // Add final normal text + if (lastPosition < text.length) { + addNewSpan(element, text.substring(lastPosition), firstChild); + } + } + } + + function getKeyModifiers(ev) { + // Returns the same value as http://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.system.virtualkeymodifiers + var VirtualKeys = { + ctrlKey: 1, + altKey: 2, + shiftKey: 4 + }; + + var keyModifiers = 0; + if (ev.ctrlKey) { + keyModifiers |= VirtualKeys.ctrlKey; + } + if (ev.altKey) { + keyModifiers |= VirtualKeys.altKey; + } + if (ev.shiftKey) { + keyModifiers |= VirtualKeys.shiftKey; + } + return keyModifiers; + } + + function resultSuggestionRenderer(asb, item) { + function handleInvoke(e) { + asb._internalFocusMove = true; + asb._inputElement.focus(); + asb._processSuggestionChosen(item, e); + } + + var root = _Global.document.createElement("div"); + var image = new _Global.Image(); + image.style.opacity = 0; + var loadImage = function (url) { + function onload() { + image.removeEventListener("load", onload, false); + Animations.fadeIn(image); + } + image.addEventListener("load", onload, false); + image.src = url; + }; + + if (item.image !== null) { + item.image.openReadAsync().then(function (streamWithContentType) { + if (streamWithContentType !== null) { + loadImage(_Global.URL.createObjectURL(streamWithContentType, { oneTimeOnly: true })); + } + }); + } else if (item.imageUrl !== null) { + loadImage(item.imageUrl); + } + image.setAttribute("aria-hidden", "true"); + root.appendChild(image); + + var divElement = _Global.document.createElement("div"); + _ElementUtilities.addClass(divElement, ClassNames.asbSuggestionResultText); + addHitHighlightedText(divElement, item, item.text); + divElement.title = item.text; + divElement.setAttribute("aria-hidden", "true"); + root.appendChild(divElement); + + var brElement = _Global.document.createElement("br"); + divElement.appendChild(brElement); + + var divDetailElement = _Global.document.createElement("span"); + _ElementUtilities.addClass(divDetailElement, ClassNames.asbSuggestionResultDetailedText); + addHitHighlightedText(divDetailElement, item, item.detailText); + divDetailElement.title = item.detailText; + divDetailElement.setAttribute("aria-hidden", "true"); + divElement.appendChild(divDetailElement); + + _ElementUtilities.addClass(root, ClassNames.asbSuggestionResult); + + _ElementUtilities._addEventListener(root, "click", function (e) { + if (!asb._isFlyoutPointerDown) { + handleInvoke(e); + } + }); + _ElementUtilities._addEventListener(root, "pointerup", handleInvoke); + + root.setAttribute("role", "option"); + var ariaLabel = _Resources._formatString(Strings.ariaLabelResult, item.text, item.detailText); + root.setAttribute("aria-label", ariaLabel); + return root; + } + + function querySuggestionRenderer(asb, item) { + function handleInvoke(e) { + asb._internalFocusMove = true; + asb._inputElement.focus(); + asb._processSuggestionChosen(item, e); + } + + var root = _Global.document.createElement("div"); + + addHitHighlightedText(root, item, item.text); + root.title = item.text; + + root.classList.add(ClassNames.asbSuggestionQuery); + + _ElementUtilities._addEventListener(root, "click", function (e) { + if (!asb._isFlyoutPointerDown) { + handleInvoke(e); + } + }); + _ElementUtilities._addEventListener(root, "pointerup", handleInvoke); + + var ariaLabel = _Resources._formatString(Strings.ariaLabelQuery, item.text); + root.setAttribute("role", "option"); + root.setAttribute("aria-label", ariaLabel); + + return root; + } + + function separatorSuggestionRenderer(item) { + var root = _Global.document.createElement("div"); + if (item.text.length > 0) { + var textElement = _Global.document.createElement("div"); + textElement.textContent = item.text; + textElement.title = item.text; + textElement.setAttribute("aria-hidden", "true"); + root.appendChild(textElement); + } + root.insertAdjacentHTML("beforeend", "
"); + _ElementUtilities.addClass(root, ClassNames.asbSuggestionSeparator); + root.setAttribute("role", "separator"); + var ariaLabel = _Resources._formatString(Strings.ariaLabelSeparator, item.text); + root.setAttribute("aria-label", ariaLabel); + return root; + } + + _Base.Class.mix(AutoSuggestBox, _Control.DOMEventMixin); + return AutoSuggestBox; + }) + }); + exports.ClassNames = ClassNames; +}); + + +define('require-style!less/styles-searchbox',[],function(){}); + +define('require-style!less/colors-searchbox',[],function(){}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('WinJS/Controls/SearchBox',[ + '../Core/_Global', + '../Core/_WinRT', + '../Core/_Base', + '../Core/_ErrorFromName', + '../Core/_Events', + '../Core/_Resources', + './AutoSuggestBox', + '../_Accents', + '../Utilities/_Control', + '../Utilities/_ElementUtilities', + './AutoSuggestBox/_SearchSuggestionManagerShim', + '../Application', + 'require-style!less/styles-searchbox', + 'require-style!less/colors-searchbox' +], function searchboxInit(_Global, _WinRT, _Base, _ErrorFromName, _Events, _Resources, AutoSuggestBox, _Accents, _Control, _ElementUtilities, _SuggestionManagerShim, Application) { + "use strict"; + + _Accents.createAccentRule("html.win-hoverable .win-searchbox-button:not(.win-searchbox-button-disabled):hover", [{ name: "color", value: _Accents.ColorTypes.accent }, ]); + _Accents.createAccentRule(".win-searchbox-button.win-searchbox-button:not(.win-searchbox-button-disabled):hover:active", [{ name: "background-color", value: _Accents.ColorTypes.accent }, ]); + + _Base.Namespace.define("WinJS.UI", { + /// + /// + /// Enables the user to perform search queries and select suggestions. + /// + /// + /// + /// + /// + /// ]]> + /// + /// Raised when the app automatically redirects focus to the search box. This event can only be raised when the focusOnKeyboardInput property is set to true. + /// + /// Styles the entire Search box control. + /// Styles the query input box. + /// Styles the search button. + /// Styles the result suggestions flyout. + /// Styles the result type suggestion. + /// Styles the query type suggestion. + /// + /// Styles the separator type suggestion. + /// + /// + /// Styles the currently selected suggestion. + /// + /// + /// + SearchBox: _Base.Namespace._lazy(function () { + + // Enums + var ClassName = { + searchBox: "win-searchbox", + searchBoxDisabled: "win-searchbox-disabled", + searchBoxInput: "win-searchbox-input", + searchBoxInputFocus: "win-searchbox-input-focus", + searchBoxButton: "win-searchbox-button", + searchBoxFlyout: "win-searchbox-flyout", + searchBoxFlyoutHighlightText: "win-searchbox-flyout-highlighttext", + searchBoxHitHighlightSpan: "win-searchbox-hithighlight-span", + searchBoxSuggestionResult: "win-searchbox-suggestion-result", + searchBoxSuggestionResultText: "win-searchbox-suggestion-result-text", + searchBoxSuggestionResultDetailedText: "win-searchbox-suggestion-result-detailed-text", + searchBoxSuggestionSelected: "win-searchbox-suggestion-selected", + searchBoxSuggestionQuery: "win-searchbox-suggestion-query", + searchBoxSuggestionSeparator: "win-searchbox-suggestion-separator", + searchBoxButtonInputFocus: "win-searchbox-button-input-focus", + searchBoxButtonDisabled: "win-searchbox-button-disabled" + }; + + var EventName = { + receivingfocusonkeyboardinput: "receivingfocusonkeyboardinput" + }; + + var strings = { + get invalidSearchBoxSuggestionKind() { return "Error: Invalid search suggestion kind."; }, + get ariaLabel() { return _Resources._getWinJSString("ui/searchBoxAriaLabel").value; }, + get ariaLabelInputNoPlaceHolder() { return _Resources._getWinJSString("ui/searchBoxAriaLabelInputNoPlaceHolder").value; }, + get ariaLabelInputPlaceHolder() { return _Resources._getWinJSString("ui/searchBoxAriaLabelInputPlaceHolder").value; }, + get searchBoxDeprecated() { return "SearchBox is deprecated and may not be available in future releases. Instead use AutoSuggestBox."; } + }; + + var SearchBox = _Base.Class.derive(AutoSuggestBox.AutoSuggestBox, function SearchBox_ctor(element, options) { + /// + /// + /// Creates a new SearchBox. + /// + /// + /// The DOM element that hosts the SearchBox. + /// + /// + /// An object that contains one or more property/value pairs to apply to the new control. + /// Each property of the options object corresponds to one of the control's properties or events. + /// Event names must begin with "on". For example, to provide a handler for the querychanged event, + /// add a property named "onquerychanged" to the options object and set its value to the event handler. + /// This parameter is optional. + /// + /// + /// The new SearchBox. + /// + /// + /// SearchBox is deprecated and may not be available in future releases. Instead use AutoSuggestBox. + /// + /// + /// + + _ElementUtilities._deprecated(strings.searchBoxDeprecated); + + this._requestingFocusOnKeyboardInputHandlerBind = this._requestingFocusOnKeyboardInputHandler.bind(this); + + // Elements + this._buttonElement = _Global.document.createElement("div"); + + // Variables + this._focusOnKeyboardInput = false; + + // Calling the super constructor - since the super constructor processes the options, + // any property setter at this point must be functional. + AutoSuggestBox.AutoSuggestBox.call(this, element, options); + + // Add SearchBox classes to DOM elements + this.element.classList.add(ClassName.searchBox); + this._flyoutElement.classList.add(ClassName.searchBoxFlyout); + + this._inputElement.classList.add(ClassName.searchBoxInput); + this._inputElement.addEventListener("blur", this._searchboxInputBlurHandler.bind(this)); + this._inputElement.addEventListener("focus", this._searchboxInputFocusHandler.bind(this)); + + this._buttonElement.tabIndex = -1; + this._buttonElement.classList.add(ClassName.searchBoxButton); + this._buttonElement.addEventListener("click", this._buttonClickHandler.bind(this)); + _ElementUtilities._addEventListener(this._buttonElement, "pointerdown", this._buttonPointerDownHandler.bind(this)); + this.element.appendChild(this._buttonElement); + }, { + /// + /// Enable automatically focusing the search box when the user types into the app window (off by default) While this is enabled, + /// input on the current thread will be intercepted and redirected to the search box. Only textual input will trigger the search box to focus. + /// The caller will continue to receive non-text keys (such as arrows, tab, etc + /// This will also not affect WIN/CTRL/ALT key combinations (except for Ctrl-V for paste). + /// If the client needs more to happen than just set focus in the box (make control visible, etc.), they will need to handle the event. + /// If enabled, the app must be sure to disable this if the user puts focus in some other edit field. + /// + /// + focusOnKeyboardInput: { + get: function () { + return this._focusOnKeyboardInput; + }, + set: function (value) { + if (this._focusOnKeyboardInput && !value) { + Application._applicationListener.removeEventListener(this.element, "requestingfocusonkeyboardinput", this._requestingFocusOnKeyboardInputHandlerBind); + } else if (!this._focusOnKeyboardInput && !!value) { + Application._applicationListener.addEventListener(this.element, "requestingfocusonkeyboardinput", this._requestingFocusOnKeyboardInputHandlerBind); + } + this._focusOnKeyboardInput = !!value; + } + }, + + // Methods + dispose: function SearchBox() { + /// + /// + /// Disposes this control. + /// + /// + /// + if (this._disposed) { + return; + } + AutoSuggestBox.AutoSuggestBox.prototype.dispose.call(this); + + if (this._focusOnKeyboardInput) { + Application._applicationListener.removeEventListener(this.element, "requestingfocusonkeyboardinput", this._requestingFocusOnKeyboardInputHandlerBind); + } + }, + + // Private methods + _disableControl: function SearchBox_disableControl() { + AutoSuggestBox.AutoSuggestBox.prototype._disableControl.call(this); + this._buttonElement.disabled = true; + this._buttonElement.classList.add(ClassName.searchBoxButtonDisabled); + this.element.classList.add(ClassName.searchBoxDisabled); + }, + + _enableControl: function SearchBox_enableControl() { + AutoSuggestBox.AutoSuggestBox.prototype._enableControl.call(this); + this._buttonElement.disabled = false; + this._buttonElement.classList.remove(ClassName.searchBoxButtonDisabled); + this.element.classList.remove(ClassName.searchBoxDisabled); + }, + + _renderSuggestion: function SearchBox_renderSuggestion(suggestion) { + // Overrides base class + var render = AutoSuggestBox.AutoSuggestBox.prototype._renderSuggestion.call(this, suggestion); + if (suggestion.kind === _SuggestionManagerShim._SearchSuggestionKind.Query) { + render.classList.add(ClassName.searchBoxSuggestionQuery); + } else if (suggestion.kind === _SuggestionManagerShim._SearchSuggestionKind.Separator) { + render.classList.add(ClassName.searchBoxSuggestionSeparator); + } else { + render.classList.add(ClassName.searchBoxSuggestionResult); + + var resultText = render.querySelector("." + AutoSuggestBox.ClassNames.asbSuggestionResultText); + resultText.classList.add(ClassName.searchBoxSuggestionResultText); + + var resultDetailText = render.querySelector("." + AutoSuggestBox.ClassNames.asbSuggestionResultDetailedText); + resultDetailText.classList.add(ClassName.searchBoxSuggestionResultDetailedText); + + var spans = render.querySelectorAll("." + AutoSuggestBox.ClassNames.asbHitHighlightSpan); + for (var i = 0, len = spans.length; i < len; i++) { + spans[i].classList.add(ClassName.searchBoxHitHighlightSpan); + } + var highlightTexts = render.querySelectorAll("." + AutoSuggestBox.ClassNames.asbBoxFlyoutHighlightText); + for (var i = 0, len = highlightTexts.length; i < len; i++) { + highlightTexts[i].classList.add(ClassName.searchBoxFlyoutHighlightText); + } + } + return render; + }, + + _selectSuggestionAtIndex: function SearchBox_selectSuggestionAtIndex(indexToSelect) { + // Overrides base class + AutoSuggestBox.AutoSuggestBox.prototype._selectSuggestionAtIndex.call(this, indexToSelect); + + var currentSelected = this.element.querySelector("." + ClassName.searchBoxSuggestionSelected); + currentSelected && currentSelected.classList.remove(ClassName.searchBoxSuggestionSelected); + var newSelected = this.element.querySelector("." + AutoSuggestBox.ClassNames.asbSuggestionSelected); + newSelected && newSelected.classList.add(ClassName.searchBoxSuggestionSelected); + }, + + _shouldIgnoreInput: function SearchBox_shouldIgnoreInput() { + // Overrides base class + var shouldIgnore = AutoSuggestBox.AutoSuggestBox.prototype._shouldIgnoreInput(); + var isButtonDown = _ElementUtilities._matchesSelector(this._buttonElement, ":active"); + + return shouldIgnore || isButtonDown; + }, + + _updateInputElementAriaLabel: function SearchBox_updateInputElementAriaLabel() { + // Override base class + this._inputElement.setAttribute("aria-label", + this._inputElement.placeholder ? _Resources._formatString(strings.ariaLabelInputPlaceHolder, this._inputElement.placeholder) : strings.ariaLabelInputNoPlaceHolder + ); + }, + + // Event Handlers + _buttonPointerDownHandler: function SearchBox_buttonPointerDownHandler(e) { + this._inputElement.focus(); + e.preventDefault(); + }, + + _buttonClickHandler: function SearchBox_buttonClickHandler(event) { + this._inputElement.focus(); + this._submitQuery(this._inputElement.value, true /*fillLinguisticDetails*/, event); + this._hideFlyout(); + }, + + _searchboxInputBlurHandler: function SearchBox_inputBlurHandler() { + _ElementUtilities.removeClass(this.element, ClassName.searchBoxInputFocus); + _ElementUtilities.removeClass(this._buttonElement, ClassName.searchBoxButtonInputFocus); + }, + + _searchboxInputFocusHandler: function SearchBox_inputFocusHandler() { + _ElementUtilities.addClass(this.element, ClassName.searchBoxInputFocus); + _ElementUtilities.addClass(this._buttonElement, ClassName.searchBoxButtonInputFocus); + }, + + // Type to search helpers + _requestingFocusOnKeyboardInputHandler: function SearchBox_requestingFocusOnKeyboardInputHandler() { + this._fireEvent(EventName.receivingfocusonkeyboardinput, null); + if (_Global.document.activeElement !== this._inputElement) { + try { + this._inputElement.focus(); + } catch (e) { + } + } + } + + }, { + createResultSuggestionImage: function SearchBox_createResultSuggestionImage(url) { + /// + /// + /// Creates the image argument for SearchSuggestionCollection.appendResultSuggestion. + /// + /// + /// The url of the image. + /// + /// + /// + if (_WinRT.Windows.Foundation.Uri && _WinRT.Windows.Storage.Streams.RandomAccessStreamReference) { + return _WinRT.Windows.Storage.Streams.RandomAccessStreamReference.createFromUri(new _WinRT.Windows.Foundation.Uri(url)); + } + return url; + }, + + _getKeyModifiers: function SearchBox_getKeyModifiers(ev) { + // Returns the same value as http://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.system.virtualkeymodifiers + var VirtualKeys = { + ctrlKey: 1, + altKey: 2, + shiftKey: 4 + }; + + var keyModifiers = 0; + if (ev.ctrlKey) { + keyModifiers |= VirtualKeys.ctrlKey; + } + if (ev.altKey) { + keyModifiers |= VirtualKeys.altKey; + } + if (ev.shiftKey) { + keyModifiers |= VirtualKeys.shiftKey; + } + return keyModifiers; + }, + + _isTypeToSearchKey: function searchBox__isTypeToSearchKey(event) { + if (event.shiftKey || event.ctrlKey || event.altKey) { + return false; + } + return true; + } + }); + _Base.Class.mix(SearchBox, _Control.DOMEventMixin); + return SearchBox; + }) + }); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// appbar,Flyout,Flyouts,registeredforsettings,SettingsFlyout,Statics,Syriac +define('WinJS/Controls/SettingsFlyout',[ + '../Core/_Global', + '../Core/_WinRT', + '../Core/_Base', + '../Core/_BaseUtils', + '../Core/_ErrorFromName', + '../Core/_Events', + '../Core/_Resources', + '../Core/_WriteProfilerMark', + '../Animations', + '../Pages', + '../Promise', + '../_LightDismissService', + '../Utilities/_Dispose', + '../Utilities/_ElementUtilities', + '../Utilities/_ElementListUtilities', + '../Utilities/_Hoverable', + './_LegacyAppBar/_Constants', + './Flyout/_Overlay' + ], function settingsFlyoutInit(_Global, _WinRT, _Base, _BaseUtils, _ErrorFromName, _Events, _Resources, _WriteProfilerMark, Animations, Pages, Promise, _LightDismissService, _Dispose, _ElementUtilities, _ElementListUtilities, _Hoverable, _Constants, _Overlay) { + "use strict"; + + _Base.Namespace.define("WinJS.UI", { + /// + /// Provides users with fast, in-context access to settings that affect the current app. + /// + /// + /// Settings Flyout + /// + /// + /// + ///
+ /// + ///
Custom Settings
+ ///
+ ///
+ /// {Your Content Here} + ///
+ /// ]]>
+ /// Raised just before showing a SettingsFlyout. + /// Raised immediately after a SettingsFlyout is fully shown. + /// Raised just before hiding a SettingsFlyout. + /// Raised immediately after a SettingsFlyout is fully hidden. + /// The SettingsFlyout control itself. + /// + /// + SettingsFlyout: _Base.Namespace._lazy(function () { + var Key = _ElementUtilities.Key; + + var createEvent = _Events._createEventProperty; + + var settingsPageIsFocusedOnce; + + // Constants for width + var settingsNarrow = "narrow", + settingsWide = "wide"; + + // Determine if the settings pane (system language) is RTL or not. + function _shouldAnimateFromLeft() { + if (_WinRT.Windows.UI.ApplicationSettings.SettingsEdgeLocation) { + var appSettings = _WinRT.Windows.UI.ApplicationSettings; + return (appSettings.SettingsPane.edge === appSettings.SettingsEdgeLocation.left); + } else { + return false; + } + } + + // Get the settings control by matching the settingsCommandId + // if no match we'll try to match element id + function _getChildSettingsControl(parentElement, id) { + var settingElements = parentElement.querySelectorAll("." + _Constants.settingsFlyoutClass); + var retValue, + control; + for (var i = 0; i < settingElements.length; i++) { + control = settingElements[i].winControl; + if (control) { + if (control.settingsCommandId === id) { + retValue = control; + break; + } + if (settingElements[i].id === id) { + retValue = retValue || control; + } + } + } + + return retValue; + } + + var SettingsFlyout = _Base.Class.derive(_Overlay._Overlay, function SettingsFlyout_ctor(element, options) { + /// + /// Creates a new SettingsFlyout control. + /// + /// The DOM element that will host the control. + /// + /// + /// The set of properties and values to apply to the new SettingsFlyout. + /// + /// The new SettingsFlyout control. + /// + /// SettingsFlyout is deprecated and may not be available in future releases. Instead, put + /// settings on their own page within the app. + /// + /// + /// + + _ElementUtilities._deprecated(strings.settingsFlyoutIsDeprecated); + + // Make sure there's an input element + this._element = element || _Global.document.createElement("div"); + this._id = this._element.id || _ElementUtilities._uniqueID(this._element); + this._writeProfilerMark("constructor,StartTM"); + + // Call the base overlay constructor helper + this._baseOverlayConstructor(this._element, options); + + this._addFirstDiv(); + this._addFinalDiv(); + + // Handle "esc" & "tab" key presses + this._element.addEventListener("keydown", this._handleKeyDown, true); + + // Start settings hidden + this._element.style.visibilty = "hidden"; + this._element.style.display = "none"; + + // Attach our css class + _ElementUtilities.addClass(this._element, _Constants.settingsFlyoutClass); + + var that = this; + this._dismissable = new _LightDismissService.LightDismissableElement({ + element: this._element, + tabIndex: this._element.hasAttribute("tabIndex") ? this._element.tabIndex : -1, + onLightDismiss: function () { + that.hide(); + }, + onTakeFocus: function (useSetActive) { + if (!that._dismissable.restoreFocus()) { + var firstDiv = that.element.querySelector("." + _Constants.firstDivClass); + if (firstDiv) { + if (!firstDiv.msSettingsFlyoutFocusOut) { + _ElementUtilities._addEventListener(firstDiv, "focusout", function () { settingsPageIsFocusedOnce = 1; }, false); + firstDiv.msSettingsFlyoutFocusOut = true; + } + + settingsPageIsFocusedOnce = 0; + _ElementUtilities._tryFocus(firstDiv, useSetActive); + } + } + }, + }); + + // apply the light theme styling to the win-content elements inside the SettingsFlyout + _ElementListUtilities.query("div.win-content", this._element). + forEach(function (e) { + if (!_ElementUtilities._matchesSelector(e, '.win-ui-dark, .win-ui-dark *')){ + _ElementUtilities.addClass(e, _Constants.flyoutLightClass); + } + }); + + // Make sure we have an ARIA role + var role = this._element.getAttribute("role"); + if (role === null || role === "" || role === undefined) { + this._element.setAttribute("role", "dialog"); + } + var label = this._element.getAttribute("aria-label"); + if (label === null || label === "" || label === undefined) { + this._element.setAttribute("aria-label", strings.ariaLabel); + } + + // Make sure animations are hooked up + this._currentAnimateIn = this._animateSlideIn; + this._currentAnimateOut = this._animateSlideOut; + this._writeProfilerMark("constructor,StopTM"); + }, { + // Public Properties + + /// + /// Width of the SettingsFlyout, "narrow", or "wide". + /// + /// SettingsFlyout.width may be altered or unavailable in future versions. Instead, style the CSS width property on elements with the .win-settingsflyout class. + /// + /// + /// + width: { + get: function () { + return this._width; + }, + + set: function (value) { + _ElementUtilities._deprecated(strings.widthDeprecationMessage); + if (value === this._width) { + return; + } + // Get rid of old class + if (this._width === settingsNarrow) { + _ElementUtilities.removeClass(this._element, _Constants.narrowClass); + } else if (this._width === settingsWide) { + _ElementUtilities.removeClass(this._element, _Constants.wideClass); + } + this._width = value; + + // Attach our new css class + if (this._width === settingsNarrow) { + _ElementUtilities.addClass(this._element, _Constants.narrowClass); + } else if (this._width === settingsWide) { + _ElementUtilities.addClass(this._element, _Constants.wideClass); + } + } + }, + + /// + /// Define the settings command Id for the SettingsFlyout control. + /// + /// + settingsCommandId: { + get: function () { + return this._settingsCommandId; + }, + + set: function (value) { + this._settingsCommandId = value; + } + }, + + /// Disable SettingsFlyout, setting or getting the HTML disabled attribute. When disabled the SettingsFlyout will no longer display with show(), and will hide if currently visible. + disabled: { + get: function () { + // Ensure it's a boolean because we're using the DOM element to keep in-sync + return !!this._element.disabled; + }, + set: function (value) { + // Force this check into a boolean because our current state could be a bit confused since we tie to the DOM element + value = !!value; + var oldValue = !!this._element.disabled; + if (oldValue !== value) { + this._element.disabled = value; + if (!this.hidden && this._element.disabled) { + this._dismiss(); + } + } + } + }, + + /// + /// Occurs immediately before the control is shown. + /// + onbeforeshow: createEvent(_Overlay._Overlay.beforeShow), + + /// + /// Occurs immediately after the control is shown. + /// + onaftershow: createEvent(_Overlay._Overlay.afterShow), + + /// + /// Occurs immediately before the control is hidden. + /// + onbeforehide: createEvent(_Overlay._Overlay.beforeHide), + + /// + /// Occurs immediately after the control is hidden. + /// + onafterhide: createEvent(_Overlay._Overlay.afterHide), + + show: function () { + /// + /// + /// Shows the SettingsFlyout, if hidden. + /// + /// + /// + // Just call private version to make appbar flags happy + + // Don't do anything if disabled + if (this.disabled) { + return; + } + this._writeProfilerMark("show,StartTM"); // The corresponding "stop" profiler mark is handled in _Overlay._baseEndShow(). + this._show(); + }, + + _dispose: function SettingsFlyout_dispose() { + _LightDismissService.hidden(this._dismissable); + _Dispose.disposeSubTree(this.element); + this._dismiss(); + }, + + _show: function SettingsFlyout_show() { + // We call our base "_baseShow" because SettingsFlyout overrides show + if (this._baseShow()) { + // Verify that the firstDiv and finalDiv are in the correct location. + // Move them to the correct location or add them if they are not. + if (!_ElementUtilities.hasClass(this.element.children[0], _Constants.firstDivClass)) { + var firstDiv = this.element.querySelectorAll("." + _Constants.firstDivClass); + if (firstDiv && firstDiv.length > 0) { + firstDiv.item(0).parentNode.removeChild(firstDiv.item(0)); + } + + this._addFirstDiv(); + } + + if (!_ElementUtilities.hasClass(this.element.children[this.element.children.length - 1], _Constants.finalDivClass)) { + var finalDiv = this.element.querySelectorAll("." + _Constants.finalDivClass); + if (finalDiv && finalDiv.length > 0) { + finalDiv.item(0).parentNode.removeChild(finalDiv.item(0)); + } + + this._addFinalDiv(); + } + + this._setBackButtonsAriaLabel(); + + _LightDismissService.shown(this._dismissable); + } + }, + + _setBackButtonsAriaLabel: function SettingsFlyout_setBackButtonsAriaLabel() { + var backbuttons = this.element.querySelectorAll(".win-backbutton"); + var label; + for (var i = 0; i < backbuttons.length; i++) { + label = backbuttons[i].getAttribute("aria-label"); + if (label === null || label === "" || label === undefined) { + backbuttons[i].setAttribute("aria-label", strings.backbuttonAriaLabel); + } + } + }, + + hide: function () { + /// + /// + /// Hides the SettingsFlyout, if visible, regardless of other state. + /// + /// + /// + // Just call private version to make appbar flags happy + this._writeProfilerMark("hide,StartTM"); // The corresponding "stop" profiler mark is handled in _Overlay._baseEndHide(). + this._hide(); + }, + + _hide: function SettingsFlyout_hide() { + this._baseHide(); + }, + + _beforeEndHide: function SettingsFlyout_beforeEndHide() { + _LightDismissService.hidden(this._dismissable); + }, + + // SettingsFlyout animations + _animateSlideIn: function SettingsFlyout_animateSlideIn() { + var animateFromLeft = _shouldAnimateFromLeft(); + var offset = animateFromLeft ? "-100px" : "100px"; + _ElementListUtilities.query("div.win-content", this._element). + forEach(function (e) { Animations.enterPage(e, { left: offset }); }); + + var where, + width = this._element.offsetWidth; + // Slide in from right side or left side? + if (animateFromLeft) { + // RTL + where = { top: "0px", left: "-" + width + "px" }; + this._element.style.right = "auto"; + this._element.style.left = "0px"; + } else { + // From right side + where = { top: "0px", left: width + "px" }; + this._element.style.right = "0px"; + this._element.style.left = "auto"; + } + + this._element.style.opacity = 1; + this._element.style.visibility = "visible"; + + return Animations.showPanel(this._element, where); + }, + + _animateSlideOut: function SettingsFlyout_animateSlideOut() { + var where, + width = this._element.offsetWidth; + if (_shouldAnimateFromLeft()) { + // RTL + where = { top: "0px", left: width + "px" }; + this._element.style.right = "auto"; + this._element.style.left = "-" + width + "px"; + } else { + // From right side + where = { top: "0px", left: "-" + width + "px" }; + this._element.style.right = "-" + width + "px"; + this._element.style.left = "auto"; + } + + return Animations.showPanel(this._element, where); + }, + + _fragmentDiv: { + get: function SettingsFlyout_fragmentDiv_get() { + return this._fragDiv; + }, + + set: function SettingsFlyout_fragmentDiv_set(value) { + this._fragDiv = value; + } + }, + + _unloadPage: function SettingsFlyout_unloadPage(event) { + var settingsControl = event.currentTarget.winControl; + settingsControl.removeEventListener(_Overlay._Overlay.afterHide, this._unloadPage, false); + + Promise.as().then(function () { + if (settingsControl._fragmentDiv) { + _Global.document.body.removeChild(settingsControl._fragmentDiv); + settingsControl._fragmentDiv = null; + } + }); + }, + + _dismiss: function SettingsFlyout_dismiss() { + this.addEventListener(_Overlay._Overlay.afterHide, this._unloadPage, false); + this._hide(); + }, + + _handleKeyDown: function SettingsFlyout_handleKeyDown(event) { + if ((event.keyCode === Key.space || event.keyCode === Key.enter) + && (this.children[0] === _Global.document.activeElement)) { + event.preventDefault(); + event.stopPropagation(); + this.winControl._dismiss(); + } else if (event.shiftKey && event.keyCode === Key.tab + && this.children[0] === _Global.document.activeElement) { + event.preventDefault(); + event.stopPropagation(); + var _elms = this.getElementsByTagName("*"); + + for (var i = _elms.length - 2; i >= 0; i--) { + _elms[i].focus(); + + if (_elms[i] === _Global.document.activeElement) { + break; + } + } + } + }, + + _focusOnLastFocusableElementFromParent: function SettingsFlyout_focusOnLastFocusableElementFromParent() { + var active = _Global.document.activeElement; + if (!settingsPageIsFocusedOnce || !active || !_ElementUtilities.hasClass(active, _Constants.firstDivClass)) { + return; + } + + var _elms = this.parentElement.getElementsByTagName("*"); + + // There should be at least 1 element in addition to the firstDiv & finalDiv + if (_elms.length <= 2) { + return; + } + + // Get the tabIndex set to the finalDiv (which is the highest) + var _highestTabIndex = _elms[_elms.length - 1].tabIndex; + + // If there are positive tabIndices, set focus to the element with the highest tabIndex. + // Otherwise set focus to the last focusable element in DOM order. + var i; + if (_highestTabIndex) { + for (i = _elms.length - 2; i > 0; i--) { + if (_elms[i].tabIndex === _highestTabIndex) { + _elms[i].focus(); + break; + } + } + } else { + for (i = _elms.length - 2; i > 0; i--) { + // Skip
with undefined tabIndex (To work around Win8 bug #622245) + if ((_elms[i].tagName !== "DIV") || (_elms[i].getAttribute("tabIndex") !== null)) { + _elms[i].focus(); + + if (_elms[i] === _Global.document.activeElement) { + break; + } + } + } + } + }, + + _focusOnFirstFocusableElementFromParent: function SettingsFlyout_focusOnFirstFocusableElementFromParent() { + var active = _Global.document.activeElement; + if (!active || !_ElementUtilities.hasClass(active, _Constants.finalDivClass)) { + return; + } + var _elms = this.parentElement.getElementsByTagName("*"); + + // There should be at least 1 element in addition to the firstDiv & finalDiv + if (_elms.length <= 2) { + return; + } + + // Get the tabIndex set to the firstDiv (which is the lowest) + var _lowestTabIndex = _elms[0].tabIndex; + + // If there are positive tabIndices, set focus to the element with the lowest tabIndex. + // Otherwise set focus to the first focusable element in DOM order. + var i; + if (_lowestTabIndex) { + for (i = 1; i < _elms.length - 1; i++) { + if (_elms[i].tabIndex === _lowestTabIndex) { + _elms[i].focus(); + break; + } + } + } else { + for (i = 1; i < _elms.length - 1; i++) { + // Skip
with undefined tabIndex (To work around Win8 bug #622245) + if ((_elms[i].tagName !== "DIV") || (_elms[i].getAttribute("tabIndex") !== null)) { + _elms[i].focus(); + + if (_elms[i] === _Global.document.activeElement) { + break; + } + } + } + } + }, + + // Create and add a new first div to the beginning of the list + _addFirstDiv: function SettingsFlyout_addFirstDiv() { + var _elms = this._element.getElementsByTagName("*"); + var _minTab = 0; + for (var i = 0; i < _elms.length; i++) { + if ((0 < _elms[i].tabIndex) && (_minTab === 0 || _elms[i].tabIndex < _minTab)) { + _minTab = _elms[i].tabIndex; + } + } + var firstDiv = _Global.document.createElement("div"); + firstDiv.className = _Constants.firstDivClass; + firstDiv.style.display = "inline"; + firstDiv.setAttribute("role", "menuitem"); + firstDiv.setAttribute("aria-hidden", "true"); + firstDiv.tabIndex = _minTab; + _ElementUtilities._addEventListener(firstDiv, "focusin", this._focusOnLastFocusableElementFromParent, false); + + // add to beginning + if (this._element.children[0]) { + this._element.insertBefore(firstDiv, this._element.children[0]); + } else { + this._element.appendChild(firstDiv); + } + }, + + // Create and add a new final div to the end of the list + _addFinalDiv: function SettingsFlyout_addFinalDiv() { + var _elms = this._element.getElementsByTagName("*"); + var _maxTab = 0; + for (var i = 0; i < _elms.length; i++) { + if (_elms[i].tabIndex > _maxTab) { + _maxTab = _elms[i].tabIndex; + } + } + var finalDiv = _Global.document.createElement("div"); + finalDiv.className = _Constants.finalDivClass; + finalDiv.style.display = "inline"; + finalDiv.setAttribute("role", "menuitem"); + finalDiv.setAttribute("aria-hidden", "true"); + finalDiv.tabIndex = _maxTab; + _ElementUtilities._addEventListener(finalDiv, "focusin", this._focusOnFirstFocusableElementFromParent, false); + + this._element.appendChild(finalDiv); + }, + + _writeProfilerMark: function SettingsFlyout_writeProfilerMark(text) { + _WriteProfilerMark("WinJS.UI.SettingsFlyout:" + this._id + ":" + text); + } + }); + + // Statics + SettingsFlyout.show = function () { + /// + /// + /// Shows the SettingsPane UI, if hidden, regardless of other states. + /// + /// + /// + /// Show the main settings pane + if (_WinRT.Windows.UI.ApplicationSettings.SettingsPane) { + _WinRT.Windows.UI.ApplicationSettings.SettingsPane.show(); + } + // And hide the WWA one + var elements = _Global.document.querySelectorAll('div[data-win-control="WinJS.UI.SettingsFlyout"]'); + var len = elements.length; + for (var i = 0; i < len; i++) { + var settingsFlyout = elements[i].winControl; + if (settingsFlyout) { + settingsFlyout._dismiss(); + } + } + }; + + var _settingsEvent = { event: undefined }; + SettingsFlyout.populateSettings = function (e) { + /// + /// + /// Loads a portion of the SettingsFlyout. Your app calls this when the user invokes a settings command and the WinJS.Application.onsettings event occurs. + /// + /// + /// An object that contains information about the event, received from the WinJS.Application.onsettings event. The detail property of this object contains + /// the applicationcommands sub-property that you set to an array of settings commands. + /// + /// + /// + _settingsEvent.event = e.detail; + + if (_settingsEvent.event.applicationcommands) { + var n = _WinRT.Windows.UI.ApplicationSettings; + Object.keys(_settingsEvent.event.applicationcommands).forEach(function (name) { + var setting = _settingsEvent.event.applicationcommands[name]; + if (!setting.title) { setting.title = name; } + var command = new n.SettingsCommand(name, setting.title, SettingsFlyout._onSettingsCommand); + _settingsEvent.event.e.request.applicationCommands.append(command); + }); + } + }; + + SettingsFlyout._onSettingsCommand = function (command) { + var id = command.id; + if (_settingsEvent.event.applicationcommands && _settingsEvent.event.applicationcommands[id]) { + SettingsFlyout.showSettings(id, _settingsEvent.event.applicationcommands[id].href); + } + }; + + SettingsFlyout.showSettings = function (id, path) { + /// + /// + /// Show the SettingsFlyout using the settings element identifier (ID) and the path of the page that contains the settings element. + /// + /// + /// The ID of the settings element. + /// + /// + /// The path of the page that contains the settings element. + /// + /// + /// + var control = _getChildSettingsControl(_Global.document, id); + if (control) { + control.show(); + } else if (path) { + var divElement = _Global.document.createElement("div"); + divElement = _Global.document.body.appendChild(divElement); + Pages.render(path, divElement).then(function () { + control = _getChildSettingsControl(divElement, id); + if (control) { + control._fragmentDiv = divElement; + control.show(); + } else { + _Global.document.body.removeChild(divElement); + } + }); + } else { + throw new _ErrorFromName("WinJS.UI.SettingsFlyout.BadReference", strings.badReference); + } + }; + + var strings = { + get ariaLabel() { return _Resources._getWinJSString("ui/settingsFlyoutAriaLabel").value; }, + get badReference() { return "Invalid argument: Invalid href to settings flyout fragment"; }, + get backbuttonAriaLabel() { return _Resources._getWinJSString("ui/backbuttonarialabel").value; }, + get widthDeprecationMessage() { return "SettingsFlyout.width may be altered or unavailable in future versions. Instead, style the CSS width property on elements with the .win-settingsflyout class."; }, + get settingsFlyoutIsDeprecated() { return "SettingsFlyout is deprecated and may not be available in future releases. Instead, put settings on their own page within the app."; } + }; + + return SettingsFlyout; + }) + }); + + +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('WinJS/Controls/NavBar/_Command',[ + 'exports', + '../../Core/_Global', + '../../Core/_Base', + '../../Core/_ErrorFromName', + '../../Core/_Resources', + '../../ControlProcessor', + '../../Navigation', + '../../Utilities/_Control', + '../../Utilities/_ElementUtilities', + '../AppBar/_Icon' + ], function NavBarCommandInit(exports, _Global, _Base, _ErrorFromName, _Resources, ControlProcessor, Navigation, _Control, _ElementUtilities, _Icon) { + "use strict"; + + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + _WinPressed: _Base.Namespace._lazy(function () { + var WinPressed = _Base.Class.define(function _WinPressed_ctor(element) { + // WinPressed is the combination of :hover:active + // :hover is delayed by trident for touch by 300ms so if you want :hover:active to work quickly you need to + // use this behavior. + // :active does not bubble to its parent like :hover does so this is also useful for that scenario. + this._element = element; + _ElementUtilities._addEventListener(this._element, "pointerdown", this._MSPointerDownButtonHandler.bind(this)); + }, { + _MSPointerDownButtonHandler: function _WinPressed_MSPointerDownButtonHandler(ev) { + if (!this._pointerUpBound) { + this._pointerUpBound = this._MSPointerUpHandler.bind(this); + this._pointerCancelBound = this._MSPointerCancelHandler.bind(this); + this._pointerOverBound = this._MSPointerOverHandler.bind(this); + this._pointerOutBound = this._MSPointerOutHandler.bind(this); + } + + if (ev.isPrimary) { + if (this._pointerId) { + this._resetPointer(); + } + + if (!_ElementUtilities._matchesSelector(ev.target, ".win-interactive, .win-interactive *")) { + this._pointerId = ev.pointerId; + + _ElementUtilities._addEventListener(_Global, "pointerup", this._pointerUpBound, true); + _ElementUtilities._addEventListener(_Global, "pointercancel", this._pointerCancelBound), true; + _ElementUtilities._addEventListener(this._element, "pointerover", this._pointerOverBound, true); + _ElementUtilities._addEventListener(this._element, "pointerout", this._pointerOutBound, true); + + _ElementUtilities.addClass(this._element, WinPressed.winPressed); + } + } + }, + + _MSPointerOverHandler: function _WinPressed_MSPointerOverHandler(ev) { + if (this._pointerId === ev.pointerId) { + _ElementUtilities.addClass(this._element, WinPressed.winPressed); + } + }, + + _MSPointerOutHandler: function _WinPressed_MSPointerOutHandler(ev) { + if (this._pointerId === ev.pointerId) { + _ElementUtilities.removeClass(this._element, WinPressed.winPressed); + } + }, + + _MSPointerCancelHandler: function _WinPressed_MSPointerCancelHandler(ev) { + if (this._pointerId === ev.pointerId) { + this._resetPointer(); + } + }, + + _MSPointerUpHandler: function _WinPressed_MSPointerUpHandler(ev) { + if (this._pointerId === ev.pointerId) { + this._resetPointer(); + } + }, + + _resetPointer: function _WinPressed_resetPointer() { + this._pointerId = null; + + _ElementUtilities._removeEventListener(_Global, "pointerup", this._pointerUpBound, true); + _ElementUtilities._removeEventListener(_Global, "pointercancel", this._pointerCancelBound, true); + _ElementUtilities._removeEventListener(this._element, "pointerover", this._pointerOverBound, true); + _ElementUtilities._removeEventListener(this._element, "pointerout", this._pointerOutBound, true); + + _ElementUtilities.removeClass(this._element, WinPressed.winPressed); + }, + + dispose: function _WinPressed_dispose() { + if (this._disposed) { + return; + } + this._disposed = true; + + this._resetPointer(); + } + }, { + winPressed: "win-pressed" + }); + + return WinPressed; + }), + /// + /// + /// Represents a navigation command in an NavBarContainer. + /// + /// + /// + /// + /// + ///
]]> + /// Styles the entire NavBarCommand control. + /// Styles the main button in a NavBarCommand. + /// Styles the split button in a NavBarCommand + /// Styles the icon in the main button of a NavBarCommand. + /// Styles the label in the main button of a NavBarCommand. + /// + /// + NavBarCommand: _Base.Namespace._lazy(function () { + var Key = _ElementUtilities.Key; + + var strings = { + get duplicateConstruction() { return "Invalid argument: Controls may only be instantiated one time for each DOM element"; } + }; + + var NavBarCommand = _Base.Class.define(function NavBarCommand_ctor(element, options) { + /// + /// + /// Creates a new NavBarCommand. + /// + /// + /// The DOM element that will host the new NavBarCommand control. + /// + /// + /// An object that contains one or more property/value pairs to apply to the new control. + /// Each property of the options object corresponds to one of the control's properties or events. + /// Event names must begin with "on". + /// + /// + /// The new NavBarCommand. + /// + /// + /// + element = element || _Global.document.createElement("DIV"); + options = options || {}; + + if (element.winControl) { + throw new _ErrorFromName("WinJS.UI.NavBarCommand.DuplicateConstruction", strings.duplicateConstruction); + } + + // Attaching JS control to DOM element + element.winControl = this; + this._element = element; + _ElementUtilities.addClass(this.element, NavBarCommand._ClassName.navbarcommand); + _ElementUtilities.addClass(this.element, "win-disposable"); + + this._tooltip = null; + this._splitOpened = false; + this._buildDom(); + element.addEventListener('keydown', this._keydownHandler.bind(this)); + + _Control.setOptions(this, options); + }, { + /// + element: { + get: function () { + return this._element; + } + }, + + /// + /// Gets or sets the label of the NavBarCommand. + /// + /// + label: { + get: function () { + return this._label; + }, + set: function (value) { + this._label = value; + this._labelEl.textContent = value; + } + }, + + /// + /// Gets or sets the tooltip of the NavBarCommand. + /// + /// + tooltip: { + get: function () { + return this._tooltip; + }, + set: function (value) { + this._tooltip = value; + if (this._tooltip || this._tooltip === "") { + this._element.setAttribute('title', this._tooltip); + } else { + this._element.removeAttribute('title'); + } + } + }, + + /// + /// Gets or sets the icon of the NavBarCommand. This value is either one of the values of the AppBarIcon enumeration or the path of a custom PNG file. + /// + /// + icon: { + get: function () { + return this._icon; + }, + set: function (value) { + this._icon = (_Icon[value] || value); + + // If the icon's a single character, presume a glyph + if (this._icon && this._icon.length === 1) { + // Set the glyph + this._imageSpan.textContent = this._icon; + this._imageSpan.style.backgroundImage = ""; + this._imageSpan.style.msHighContrastAdjust = ""; + this._imageSpan.style.display = ""; + } else if (this._icon && this._icon.length > 1) { + // Must be an image, set that + this._imageSpan.textContent = ""; + this._imageSpan.style.backgroundImage = this._icon; + this._imageSpan.style.msHighContrastAdjust = "none"; + this._imageSpan.style.display = ""; + } else { + this._imageSpan.textContent = ""; + this._imageSpan.style.backgroundImage = ""; + this._imageSpan.style.msHighContrastAdjust = ""; + this._imageSpan.style.display = "none"; + } + } + }, + + /// + /// Gets or sets the command's target location. + /// + /// + location: { + get: function () { + return this._location; + }, + set: function (value) { + this._location = value; + } + }, + + /// + /// Gets or sets the state value used for navigation. The command passes this object to the WinJS.Navigation.navigate function. + /// + /// + state: { + get: function () { + return this._state; + }, + set: function (value) { + this._state = value; + } + }, + + /// + /// Gets or sets a value that specifies whether the NavBarCommand has a split button. + /// + /// + splitButton: { + get: function () { + return this._split; + }, + set: function (value) { + this._split = value; + if (this._split) { + this._splitButtonEl.style.display = ""; + } else { + this._splitButtonEl.style.display = "none"; + } + } + }, + + /// + splitOpened: { + get: function () { + return this._splitOpened; + }, + set: function (value) { + if (this._splitOpened !== !!value) { + this._toggleSplit(); + } + } + }, + + _toggleSplit: function NavBarCommand_toggleSplit() { + this._splitOpened = !this._splitOpened; + if (this._splitOpened) { + _ElementUtilities.addClass(this._splitButtonEl, NavBarCommand._ClassName.navbarcommandsplitbuttonopened); + this._splitButtonEl.setAttribute("aria-expanded", "true"); + } else { + _ElementUtilities.removeClass(this._splitButtonEl, NavBarCommand._ClassName.navbarcommandsplitbuttonopened); + this._splitButtonEl.setAttribute("aria-expanded", "false"); + } + this._fireEvent(NavBarCommand._EventName._splitToggle); + }, + + _rtl: { + get: function () { + return _Global.getComputedStyle(this.element).direction === "rtl"; + } + }, + + _keydownHandler: function NavBarCommand_keydownHandler(ev) { + if (_ElementUtilities._matchesSelector(ev.target, ".win-interactive, .win-interactive *")) { + return; + } + + var leftStr = this._rtl ? Key.rightArrow : Key.leftArrow; + var rightStr = this._rtl ? Key.leftArrow : Key.rightArrow; + + if (!ev.altKey && (ev.keyCode === leftStr || ev.keyCode === Key.home || ev.keyCode === Key.end) && ev.target === this._splitButtonEl) { + _ElementUtilities._setActive(this._buttonEl); + if (ev.keyCode === leftStr) { + ev.stopPropagation(); + } + ev.preventDefault(); + } else if (!ev.altKey && ev.keyCode === rightStr && this.splitButton && (ev.target === this._buttonEl || this._buttonEl.contains(ev.target))) { + _ElementUtilities._setActive(this._splitButtonEl); + if (ev.keyCode === rightStr) { + ev.stopPropagation(); + } + ev.preventDefault(); + } else if ((ev.keyCode === Key.space || ev.keyCode === Key.enter) && (ev.target === this._buttonEl || this._buttonEl.contains(ev.target))) { + if (this.location) { + Navigation.navigate(this.location, this.state); + } + this._fireEvent(NavBarCommand._EventName._invoked); + } else if ((ev.keyCode === Key.space || ev.keyCode === Key.enter) && ev.target === this._splitButtonEl) { + this._toggleSplit(); + } + }, + + _getFocusInto: function NavBarCommand_getFocusInto(keyCode) { + var leftStr = this._rtl ? Key.rightArrow : Key.leftArrow; + if ((keyCode === leftStr) && this.splitButton) { + return this._splitButtonEl; + } else { + return this._buttonEl; + } + }, + + _buildDom: function NavBarCommand_buildDom() { + var markup = + '' + + ''; + this.element.insertAdjacentHTML("afterBegin", markup); + + this._buttonEl = this.element.firstElementChild; + this._buttonPressedBehavior = new exports._WinPressed(this._buttonEl); + this._contentEl = this._buttonEl.firstElementChild; + this._imageSpan = this._contentEl.firstElementChild; + this._imageSpan.style.display = "none"; + this._labelEl = this._imageSpan.nextElementSibling; + this._splitButtonEl = this._buttonEl.nextElementSibling; + this._splitButtonPressedBehavior = new exports._WinPressed(this._splitButtonEl); + this._splitButtonEl.style.display = "none"; + + _ElementUtilities._ensureId(this._buttonEl); + this._splitButtonEl.setAttribute("aria-labelledby", this._buttonEl.id); + + this._buttonEl.addEventListener("click", this._handleButtonClick.bind(this)); + + var mutationObserver = new _ElementUtilities._MutationObserver(this._splitButtonAriaExpandedPropertyChangeHandler.bind(this)); + mutationObserver.observe(this._splitButtonEl, { attributes: true, attributeFilter: ["aria-expanded"] }); + this._splitButtonEl.addEventListener("click", this._handleSplitButtonClick.bind(this)); + + // reparent any other elements. + var tempEl = this._splitButtonEl.nextSibling; + while (tempEl) { + this._buttonEl.insertBefore(tempEl, this._contentEl); + if (tempEl.nodeName !== "#text") { + ControlProcessor.processAll(tempEl); + } + tempEl = this._splitButtonEl.nextSibling; + } + }, + + _handleButtonClick: function NavBarCommand_handleButtonClick(ev) { + var srcElement = ev.target; + if (!_ElementUtilities._matchesSelector(srcElement, ".win-interactive, .win-interactive *")) { + if (this.location) { + Navigation.navigate(this.location, this.state); + } + this._fireEvent(NavBarCommand._EventName._invoked); + } + }, + + _splitButtonAriaExpandedPropertyChangeHandler: function NavBarCommand_splitButtonAriaExpandedPropertyChangeHandler() { + if ((this._splitButtonEl.getAttribute("aria-expanded") === "true") !== this._splitOpened) { + this._toggleSplit(); + } + }, + + _handleSplitButtonClick: function NavBarCommand_handleSplitButtonClick() { + this._toggleSplit(); + }, + + _fireEvent: function NavBarCommand_fireEvent(type, detail) { + var event = _Global.document.createEvent("CustomEvent"); + event.initCustomEvent(type, true, false, detail); + this.element.dispatchEvent(event); + }, + + dispose: function NavBarCommand_dispose() { + /// + /// + /// Disposes this control. + /// + /// + /// + if (this._disposed) { + return; + } + this._disposed = true; + + this._buttonPressedBehavior.dispose(); + this._splitButtonPressedBehavior.dispose(); + } + }, { + _ClassName: { + navbarcommand: "win-navbarcommand", + navbarcommandbutton: "win-navbarcommand-button", + navbarcommandbuttoncontent: "win-navbarcommand-button-content", + navbarcommandsplitbutton: "win-navbarcommand-splitbutton", + navbarcommandsplitbuttonopened: "win-navbarcommand-splitbutton-opened", + navbarcommandicon: "win-navbarcommand-icon", + navbarcommandlabel: "win-navbarcommand-label" + }, + _EventName: { + _invoked: "_invoked", + _splitToggle: "_splittoggle" + } + }); + _Base.Class.mix(NavBarCommand, _Control.DOMEventMixin); + return NavBarCommand; + }) + }); + +}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('WinJS/Controls/NavBar/_Container',[ + 'exports', + '../../Core/_Global', + '../../Core/_Base', + '../../Core/_BaseUtils', + '../../Core/_ErrorFromName', + '../../Core/_Events', + '../../Core/_Log', + '../../Core/_Resources', + '../../Core/_WriteProfilerMark', + '../../Animations', + '../../Animations/_TransitionAnimation', + '../../BindingList', + '../../ControlProcessor', + '../../Navigation', + '../../Promise', + '../../Scheduler', + '../../Utilities/_Control', + '../../Utilities/_ElementUtilities', + '../../Utilities/_KeyboardBehavior', + '../../Utilities/_UI', + '../_LegacyAppBar/_Constants', + '../Repeater', + './_Command' +], function NavBarContainerInit(exports, _Global, _Base, _BaseUtils, _ErrorFromName, _Events, _Log, _Resources, _WriteProfilerMark, Animations, _TransitionAnimation, BindingList, ControlProcessor, Navigation, Promise, Scheduler, _Control, _ElementUtilities, _KeyboardBehavior, _UI, _Constants, Repeater, _Command) { + "use strict"; + + function nobodyHasFocus() { + return _Global.document.activeElement === null || _Global.document.activeElement === _Global.document.body; + } + + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + /// + /// + /// Contains a group of NavBarCommand objects in a NavBar. + /// + /// + /// + /// + /// + /// + ///
+ ///
]]> + /// Raised when a NavBarCommand is invoked. + /// Raised when the split button on a NavBarCommand is toggled. + /// Styles the entire NavBarContainer control. + /// + /// Styles the page indication for the NavBarContainer. + /// + /// Styles the page indication for each page. + /// + /// Styles the indication of the current page. + /// + /// Styles the area that contains items for the NavBarContainer. + /// Styles left and right navigation arrows. + /// Styles the left navigation arrow. + /// Styles the right navigation arrow. + /// + /// + NavBarContainer: _Base.Namespace._lazy(function () { + var Key = _ElementUtilities.Key; + + var buttonFadeDelay = 3000; + var PT_TOUCH = _ElementUtilities._MSPointerEvent.MSPOINTER_TYPE_TOUCH || "touch"; + var MS_MANIPULATION_STATE_STOPPED = 0; + + var createEvent = _Events._createEventProperty; + var eventNames = { + invoked: "invoked", + splittoggle: "splittoggle" + }; + + var strings = { + get duplicateConstruction() { return "Invalid argument: Controls may only be instantiated one time for each DOM element"; }, + get navBarContainerViewportAriaLabel() { return _Resources._getWinJSString("ui/navBarContainerViewportAriaLabel").value; } + }; + + var NavBarContainer = _Base.Class.define(function NavBarContainer_ctor(element, options) { + /// + /// + /// Creates a new NavBarContainer. + /// + /// + /// The DOM element that will host the NavBarContainer control. + /// + /// + /// An object that contains one or more property/value pairs to apply to the new control. + /// Each property of the options object corresponds to one of the control's properties or events. + /// Event names must begin with "on". + /// + /// + /// The new NavBarContainer. + /// + /// + /// + + element = element || _Global.document.createElement("DIV"); + this._id = element.id || _ElementUtilities._uniqueID(element); + this._writeProfilerMark("constructor,StartTM"); + + options = options || {}; + + if (element.winControl) { + throw new _ErrorFromName("WinJS.UI.NavBarContainer.DuplicateConstruction", strings.duplicateConstruction); + } + + // Attaching JS control to DOM element + element.winControl = this; + this._element = element; + _ElementUtilities.addClass(this.element, NavBarContainer._ClassName.navbarcontainer); + _ElementUtilities.addClass(this.element, "win-disposable"); + if (!element.getAttribute("tabIndex")) { + element.tabIndex = -1; + } + + this._focusCurrentItemPassivelyBound = this._focusCurrentItemPassively.bind(this); + this._closeSplitAndResetBound = this._closeSplitAndReset.bind(this); + this._currentManipulationState = MS_MANIPULATION_STATE_STOPPED; + + this._panningDisabled = !_ElementUtilities._supportsSnapPoints; + this._fixedSize = false; + this._maxRows = 1; + this._sizes = {}; + + this._setupTree(); + + this._duringConstructor = true; + + this._dataChangingBound = this._dataChanging.bind(this); + this._dataChangedBound = this._dataChanged.bind(this); + + Navigation.addEventListener('navigated', this._closeSplitAndResetBound); + + // Don't use set options for the properties so we can control the ordering to avoid rendering multiple times. + this.layout = options.layout || _UI.Orientation.horizontal; + if (options.maxRows) { + this.maxRows = options.maxRows; + } + if (options.template) { + this.template = options.template; + } + if (options.data) { + this.data = options.data; + } + if (options.fixedSize) { + this.fixedSize = options.fixedSize; + } + + // Events only + _Control._setOptions(this, options, true); + + this._duringConstructor = false; + + if (options.currentIndex) { + this.currentIndex = options.currentIndex; + } + + this._updatePageUI(); + + Scheduler.schedule(function NavBarContainer_async_initialize() { + this._updateAppBarReference(); + }, Scheduler.Priority.normal, this, "WinJS.UI.NavBarContainer_async_initialize"); + + this._writeProfilerMark("constructor,StopTM"); + }, { + /// + element: { + get: function () { + return this._element; + } + }, + + /// + /// Gets or sets a Template or custom rendering function that defines the HTML of each item within the NavBarContainer. + /// + /// + template: { + get: function () { + return this._template; + }, + set: function (value) { + this._template = value; + if (this._repeater) { + var hadFocus = this.element.contains(_Global.document.activeElement); + + if (!this._duringConstructor) { + this._closeSplitIfOpen(); + } + + // the repeater's template is wired up to this._render() so just resetting it will rebuild the tree. + this._repeater.template = this._repeater.template; + + if (!this._duringConstructor) { + this._measured = false; + this._sizes.itemMeasured = false; + this._reset(); + if (hadFocus) { + this._keyboardBehavior._focus(0); + } + } + } + } + }, + + _render: function NavBarContainer_render(item) { + var navbarCommandEl = _Global.document.createElement('div'); + + var template = this._template; + if (template) { + if (template.render) { + template.render(item, navbarCommandEl); + } else if (template.winControl && template.winControl.render) { + template.winControl.render(item, navbarCommandEl); + } else { + navbarCommandEl.appendChild(template(item)); + } + } + + // Create the NavBarCommand after calling render so that the reparenting in navbarCommand works. + var navbarCommand = new _Command.NavBarCommand(navbarCommandEl, item); + return navbarCommand._element; + }, + + /// + /// Gets or sets the WinJS.Binding.List that provides the NavBarContainer with items to display. + /// + /// + data: { + get: function () { + return this._repeater && this._repeater.data; + }, + set: function (value) { + if (!value) { + value = new BindingList.List(); + } + + if (!this._duringConstructor) { + this._closeSplitIfOpen(); + } + + this._removeDataChangingEvents(); + this._removeDataChangedEvents(); + + var hadFocus = this.element.contains(_Global.document.activeElement); + + if (!this._repeater) { + this._surfaceEl.innerHTML = ""; + this._repeater = new Repeater.Repeater(this._surfaceEl, { + template: this._render.bind(this) + }); + } + + this._addDataChangingEvents(value); + this._repeater.data = value; + this._addDataChangedEvents(value); + + if (!this._duringConstructor) { + this._measured = false; + this._sizes.itemMeasured = false; + this._reset(); + if (hadFocus) { + this._keyboardBehavior._focus(0); + } + } + } + }, + + /// + /// Gets or sets the number of rows allowed to be used before items are placed on additional pages. + /// + /// + maxRows: { + get: function () { + return this._maxRows; + }, + set: function (value) { + value = (+value === value) ? value : 1; + this._maxRows = Math.max(1, value); + + if (!this._duringConstructor) { + this._closeSplitIfOpen(); + + this._measured = false; + this._reset(); + } + } + }, + + /// + /// Gets or sets a value that specifies whether the NavBarContainer has a horizontal or vertical layout. The default is "horizontal". + /// + /// + layout: { + get: function () { + return this._layout; + }, + set: function (value) { + if (value === _UI.Orientation.vertical) { + this._layout = _UI.Orientation.vertical; + _ElementUtilities.removeClass(this.element, NavBarContainer._ClassName.horizontal); + _ElementUtilities.addClass(this.element, NavBarContainer._ClassName.vertical); + } else { + this._layout = _UI.Orientation.horizontal; + _ElementUtilities.removeClass(this.element, NavBarContainer._ClassName.vertical); + _ElementUtilities.addClass(this.element, NavBarContainer._ClassName.horizontal); + } + + this._viewportEl.style.msScrollSnapType = ""; + this._zooming = false; + + if (!this._duringConstructor) { + this._measured = false; + this._sizes.itemMeasured = false; + this._ensureVisible(this._keyboardBehavior.currentIndex, true); + this._updatePageUI(); + this._closeSplitIfOpen(); + } + } + }, + + /// + currentIndex: { + get: function () { + return this._keyboardBehavior.currentIndex; + }, + set: function (value) { + if (value === +value) { + var hadFocus = this.element.contains(_Global.document.activeElement); + + this._keyboardBehavior.currentIndex = value; + + this._ensureVisible(this._keyboardBehavior.currentIndex, true); + + if (hadFocus) { + this._keyboardBehavior._focus(); + } + } + } + }, + + /// + /// Gets or sets a value that specifies whether child NavBarCommand objects should be a fixed width when there are multiple pages. A value of true indicates + /// that the NavBarCommand objects use a fixed width; a value of false indicates that they use a dynamic width. + /// + /// + fixedSize: { + get: function () { + return this._fixedSize; + }, + set: function (value) { + this._fixedSize = !!value; + + if (!this._duringConstructor) { + this._closeSplitIfOpen(); + + if (!this._measured) { + this._measure(); + } else if (this._surfaceEl.children.length > 0) { + this._updateGridStyles(); + } + } + } + }, + + /// + /// Raised when a NavBarCommand has been invoked. + /// + /// + oninvoked: createEvent(eventNames.invoked), + + /// + /// Raised when the split button on a NavBarCommand is toggled. + /// + /// + onsplittoggle: createEvent(eventNames.splittoggle), + + forceLayout: function NavBarContainer_forceLayout() { + /// + /// + /// Forces the NavBarContainer to update scroll positions and if the NavBar has changed size, it will also re-measure. + /// Use this function when making the NavBarContainer visible again after you set its style.display property to "none". + /// + /// + /// + this._resizeHandler(); + if (this._measured) { + this._scrollPosition = _ElementUtilities.getScrollPosition(this._viewportEl)[(this.layout === _UI.Orientation.horizontal ? "scrollLeft" : "scrollTop")]; + } + + this._duringForceLayout = true; + this._ensureVisible(this._keyboardBehavior.currentIndex, true); + this._updatePageUI(); + this._duringForceLayout = false; + }, + + _updateAppBarReference: function NavBarContainer_updateAppBarReference() { + if (!this._appBarEl || !this._appBarEl.contains(this.element)) { + if (this._appBarEl) { + this._appBarEl.removeEventListener('beforeopen', this._closeSplitAndResetBound); + this._appBarEl.removeEventListener('beforeopen', this._resizeImplBound); + this._appBarEl.removeEventListener('afteropen', this._focusCurrentItemPassivelyBound); + } + + var appBarEl = this.element.parentNode; + while (appBarEl && !_ElementUtilities.hasClass(appBarEl, _Constants.appBarClass)) { + appBarEl = appBarEl.parentNode; + } + this._appBarEl = appBarEl; + + if (this._appBarEl) { + this._appBarEl.addEventListener('beforeopen', this._closeSplitAndResetBound); + this._appBarEl.addEventListener('afteropen', this._focusCurrentItemPassivelyBound); + } + } + }, + + _closeSplitAndReset: function NavBarContainer_closeSplitAndReset() { + this._closeSplitIfOpen(); + this._reset(); + }, + + _dataChanging: function NavBarContainer_dataChanging(ev) { + // Store the element that was active so that we can detect + // if the focus went away because of the data change. + this._elementHadFocus = _Global.document.activeElement; + + if (this._currentSplitNavItem && this._currentSplitNavItem.splitOpened) { + if (ev.type === "itemremoved") { + if (this._surfaceEl.children[ev.detail.index].winControl === this._currentSplitNavItem) { + this._closeSplitIfOpen(); + } + } else if (ev.type === "itemchanged") { + if (this._surfaceEl.children[ev.detail.index].winControl === this._currentSplitNavItem) { + this._closeSplitIfOpen(); + } + } else if (ev.type === "itemmoved") { + if (this._surfaceEl.children[ev.detail.oldIndex].winControl === this._currentSplitNavItem) { + this._closeSplitIfOpen(); + } + } else if (ev.type === "reload") { + this._closeSplitIfOpen(); + } + } + }, + + _dataChanged: function NavBarContainer_dataChanged(ev) { + this._measured = false; + + if (ev.type === "itemremoved") { + if (ev.detail.index < this._keyboardBehavior.currentIndex) { + this._keyboardBehavior.currentIndex--; + } else if (ev.detail.index === this._keyboardBehavior.currentIndex) { + // This clamps if the item being removed was the last item in the list + this._keyboardBehavior.currentIndex = this._keyboardBehavior.currentIndex; + if (nobodyHasFocus() && this._elementHadFocus) { + this._keyboardBehavior._focus(); + } + } + } else if (ev.type === "itemchanged") { + if (ev.detail.index === this._keyboardBehavior.currentIndex) { + if (nobodyHasFocus() && this._elementHadFocus) { + this._keyboardBehavior._focus(); + } + } + } else if (ev.type === "iteminserted") { + if (ev.detail.index <= this._keyboardBehavior.currentIndex) { + this._keyboardBehavior.currentIndex++; + } + } else if (ev.type === "itemmoved") { + if (ev.detail.oldIndex === this._keyboardBehavior.currentIndex) { + this._keyboardBehavior.currentIndex = ev.detail.newIndex; + if (nobodyHasFocus() && this._elementHadFocus) { + this._keyboardBehavior._focus(); + } + } + } else if (ev.type === "reload") { + this._keyboardBehavior.currentIndex = 0; + if (nobodyHasFocus() && this._elementHadFocus) { + this._keyboardBehavior._focus(); + } + } + + this._ensureVisible(this._keyboardBehavior.currentIndex, true); + this._updatePageUI(); + }, + + _focusCurrentItemPassively: function NavBarContainer_focusCurrentItemPassively() { + if (this.element.contains(_Global.document.activeElement)) { + this._keyboardBehavior._focus(); + } + }, + + _reset: function NavBarContainer_reset() { + this._keyboardBehavior.currentIndex = 0; + + if (this.element.contains(_Global.document.activeElement)) { + this._keyboardBehavior._focus(0); + } + + this._viewportEl.style.msScrollSnapType = ""; + this._zooming = false; + + this._ensureVisible(0, true); + this._updatePageUI(); + }, + + _removeDataChangedEvents: function NavBarContainer_removeDataChangedEvents() { + if (this._repeater) { + this._repeater.data.removeEventListener("itemchanged", this._dataChangedBound); + this._repeater.data.removeEventListener("iteminserted", this._dataChangedBound); + this._repeater.data.removeEventListener("itemmoved", this._dataChangedBound); + this._repeater.data.removeEventListener("itemremoved", this._dataChangedBound); + this._repeater.data.removeEventListener("reload", this._dataChangedBound); + } + }, + + _addDataChangedEvents: function NavBarContainer_addDataChangedEvents() { + if (this._repeater) { + this._repeater.data.addEventListener("itemchanged", this._dataChangedBound); + this._repeater.data.addEventListener("iteminserted", this._dataChangedBound); + this._repeater.data.addEventListener("itemmoved", this._dataChangedBound); + this._repeater.data.addEventListener("itemremoved", this._dataChangedBound); + this._repeater.data.addEventListener("reload", this._dataChangedBound); + } + }, + + _removeDataChangingEvents: function NavBarContainer_removeDataChangingEvents() { + if (this._repeater) { + this._repeater.data.removeEventListener("itemchanged", this._dataChangingBound); + this._repeater.data.removeEventListener("iteminserted", this._dataChangingBound); + this._repeater.data.removeEventListener("itemmoved", this._dataChangingBound); + this._repeater.data.removeEventListener("itemremoved", this._dataChangingBound); + this._repeater.data.removeEventListener("reload", this._dataChangingBound); + } + }, + + _addDataChangingEvents: function NavBarContainer_addDataChangingEvents(bindingList) { + bindingList.addEventListener("itemchanged", this._dataChangingBound); + bindingList.addEventListener("iteminserted", this._dataChangingBound); + bindingList.addEventListener("itemmoved", this._dataChangingBound); + bindingList.addEventListener("itemremoved", this._dataChangingBound); + bindingList.addEventListener("reload", this._dataChangingBound); + }, + + _mouseleave: function NavBarContainer_mouseleave() { + if (this._mouseInViewport) { + this._mouseInViewport = false; + this._updateArrows(); + } + }, + + _MSPointerDown: function NavBarContainer_MSPointerDown(ev) { + if (ev.pointerType === PT_TOUCH) { + if (this._mouseInViewport) { + this._mouseInViewport = false; + this._updateArrows(); + } + } + }, + + _MSPointerMove: function NavBarContainer_MSPointerMove(ev) { + if (ev.pointerType !== PT_TOUCH) { + if (!this._mouseInViewport) { + this._mouseInViewport = true; + this._updateArrows(); + } + } + }, + + _setupTree: function NavBarContainer_setupTree() { + this._animateNextPreviousButtons = Promise.wrap(); + this._element.addEventListener('mouseleave', this._mouseleave.bind(this)); + _ElementUtilities._addEventListener(this._element, 'pointerdown', this._MSPointerDown.bind(this)); + _ElementUtilities._addEventListener(this._element, 'pointermove', this._MSPointerMove.bind(this)); + _ElementUtilities._addEventListener(this._element, "focusin", this._focusHandler.bind(this), false); + + this._pageindicatorsEl = _Global.document.createElement('div'); + _ElementUtilities.addClass(this._pageindicatorsEl, NavBarContainer._ClassName.pageindicators); + this._element.appendChild(this._pageindicatorsEl); + + this._ariaStartMarker = _Global.document.createElement("div"); + this._element.appendChild(this._ariaStartMarker); + + this._viewportEl = _Global.document.createElement('div'); + _ElementUtilities.addClass(this._viewportEl, NavBarContainer._ClassName.viewport); + this._element.appendChild(this._viewportEl); + this._viewportEl.setAttribute("role", "group"); + this._viewportEl.setAttribute("aria-label", strings.navBarContainerViewportAriaLabel); + + this._boundResizeHandler = this._resizeHandler.bind(this); + _ElementUtilities._resizeNotifier.subscribe(this._element, this._boundResizeHandler); + this._viewportEl.addEventListener("mselementresize", this._resizeHandler.bind(this)); + this._viewportEl.addEventListener("scroll", this._scrollHandler.bind(this)); + this._viewportEl.addEventListener("MSManipulationStateChanged", this._MSManipulationStateChangedHandler.bind(this)); + + this._ariaEndMarker = _Global.document.createElement("div"); + this._element.appendChild(this._ariaEndMarker); + + this._surfaceEl = _Global.document.createElement('div'); + _ElementUtilities.addClass(this._surfaceEl, NavBarContainer._ClassName.surface); + this._viewportEl.appendChild(this._surfaceEl); + + this._surfaceEl.addEventListener("_invoked", this._navbarCommandInvokedHandler.bind(this)); + this._surfaceEl.addEventListener("_splittoggle", this._navbarCommandSplitToggleHandler.bind(this)); + _ElementUtilities._addEventListener(this._surfaceEl, "focusin", this._itemsFocusHandler.bind(this), false); + this._surfaceEl.addEventListener("keydown", this._keyDownHandler.bind(this)); + + // Reparent NavBarCommands which were in declarative markup + var tempEl = this.element.firstElementChild; + while (tempEl !== this._pageindicatorsEl) { + this._surfaceEl.appendChild(tempEl); + ControlProcessor.process(tempEl); + tempEl = this.element.firstElementChild; + } + + this._leftArrowEl = _Global.document.createElement('div'); + _ElementUtilities.addClass(this._leftArrowEl, NavBarContainer._ClassName.navleftarrow); + _ElementUtilities.addClass(this._leftArrowEl, NavBarContainer._ClassName.navarrow); + this._element.appendChild(this._leftArrowEl); + this._leftArrowEl.addEventListener('click', this._goLeft.bind(this)); + this._leftArrowEl.style.opacity = 0; + this._leftArrowEl.style.visibility = 'hidden'; + this._leftArrowFadeOut = Promise.wrap(); + + this._rightArrowEl = _Global.document.createElement('div'); + _ElementUtilities.addClass(this._rightArrowEl, NavBarContainer._ClassName.navrightarrow); + _ElementUtilities.addClass(this._rightArrowEl, NavBarContainer._ClassName.navarrow); + this._element.appendChild(this._rightArrowEl); + this._rightArrowEl.addEventListener('click', this._goRight.bind(this)); + this._rightArrowEl.style.opacity = 0; + this._rightArrowEl.style.visibility = 'hidden'; + this._rightArrowFadeOut = Promise.wrap(); + + this._keyboardBehavior = new _KeyboardBehavior._KeyboardBehavior(this._surfaceEl, { + scroller: this._viewportEl + }); + this._winKeyboard = new _KeyboardBehavior._WinKeyboard(this._surfaceEl); + }, + + _goRight: function NavBarContainer_goRight() { + if (this._sizes.rtl) { + this._goPrev(); + } else { + this._goNext(); + } + }, + + _goLeft: function NavBarContainer_goLeft() { + if (this._sizes.rtl) { + this._goNext(); + } else { + this._goPrev(); + } + }, + + _goNext: function NavBarContainer_goNext() { + this._measure(); + var itemsPerPage = this._sizes.rowsPerPage * this._sizes.columnsPerPage; + var targetPage = Math.min(Math.floor(this._keyboardBehavior.currentIndex / itemsPerPage) + 1, this._sizes.pages - 1); + this._keyboardBehavior.currentIndex = Math.min(itemsPerPage * targetPage, this._surfaceEl.children.length); + this._keyboardBehavior._focus(); + }, + + _goPrev: function NavBarContainer_goPrev() { + this._measure(); + var itemsPerPage = this._sizes.rowsPerPage * this._sizes.columnsPerPage; + var targetPage = Math.max(0, Math.floor(this._keyboardBehavior.currentIndex / itemsPerPage) - 1); + this._keyboardBehavior.currentIndex = Math.max(itemsPerPage * targetPage, 0); + this._keyboardBehavior._focus(); + }, + + _currentPage: { + get: function () { + if (this.layout === _UI.Orientation.horizontal) { + this._measure(); + if (this._sizes.viewportOffsetWidth > 0) { + return Math.min(this._sizes.pages - 1, Math.round(this._scrollPosition / this._sizes.viewportOffsetWidth)); + } + } + return 0; + } + }, + + _resizeHandler: function NavBarContainer_resizeHandler() { + if (this._disposed) { return; } + if (!this._measured) { return; } + var viewportResized = this.layout === _UI.Orientation.horizontal + ? this._sizes.viewportOffsetWidth !== parseFloat(_Global.getComputedStyle(this._viewportEl).width) + : this._sizes.viewportOffsetHeight !== parseFloat(_Global.getComputedStyle(this._viewportEl).height); + if (!viewportResized) { return; } + + this._measured = false; + + if (!this._pendingResize) { + this._pendingResize = true; + + this._resizeImplBound = this._resizeImplBound || this._resizeImpl.bind(this); + + this._updateAppBarReference(); + + if (this._appBarEl && this._appBarEl.winControl && !this._appBarEl.winControl.opened) { + // Do resize lazily. + Scheduler.schedule(this._resizeImplBound, Scheduler.Priority.idle, null, "WinJS.UI.NavBarContainer._resizeImpl"); + this._appBarEl.addEventListener('beforeopen', this._resizeImplBound); + } else { + // Do resize now + this._resizeImpl(); + } + } + }, + + _resizeImpl: function NavBarContainer_resizeImpl() { + if (!this._disposed && this._pendingResize) { + this._pendingResize = false; + if (this._appBarEl) { + this._appBarEl.removeEventListener('beforeopen', this._resizeImplBound); + } + + this._keyboardBehavior.currentIndex = 0; + if (this.element.contains(_Global.document.activeElement)) { + this._keyboardBehavior._focus(this._keyboardBehavior.currentIndex); + } + this._closeSplitIfOpen(); + this._ensureVisible(this._keyboardBehavior.currentIndex, true); + this._updatePageUI(); + } + }, + + _keyDownHandler: function NavBarContainer_keyDownHandler(ev) { + var keyCode = ev.keyCode; + if (!ev.altKey && (keyCode === Key.pageUp || keyCode === Key.pageDown)) { + var srcElement = ev.target; + if (_ElementUtilities._matchesSelector(srcElement, ".win-interactive, .win-interactive *")) { + return; + } + + var index = this._keyboardBehavior.currentIndex; + this._measure(); + + var sizes = this._sizes; + var page = Math.floor(index / (sizes.columnsPerPage * sizes.rowsPerPage)); + + var scrollPositionTarget = null; + if (keyCode === Key.pageUp) { + if (this.layout === _UI.Orientation.horizontal) { + var indexOfFirstItemOnPage = page * sizes.columnsPerPage * sizes.rowsPerPage; + if (index === indexOfFirstItemOnPage && this._surfaceEl.children[index].winControl._buttonEl === _Global.document.activeElement) { + // First item on page so go back 1 page. + index = index - sizes.columnsPerPage * sizes.rowsPerPage; + } else { + // Not first item on page so go to the first item on page. + index = indexOfFirstItemOnPage; + } + } else { + var currentItem = this._surfaceEl.children[index]; + var top = currentItem.offsetTop; + var bottom = top + currentItem.offsetHeight; + var scrollPosition = this._zooming ? this._zoomPosition : this._scrollPosition; + + if (top >= scrollPosition && bottom < scrollPosition + sizes.viewportOffsetHeight) { + // current item is fully on screen. + while (index > 0 && + this._surfaceEl.children[index - 1].offsetTop > scrollPosition) { + index--; + } + } + + if (this._keyboardBehavior.currentIndex === index) { + var scrollPositionForOnePageAboveItem = bottom - sizes.viewportOffsetHeight; + index = Math.max(0, index - 1); + while (index > 0 && + this._surfaceEl.children[index - 1].offsetTop > scrollPositionForOnePageAboveItem) { + index--; + } + if (index > 0) { + scrollPositionTarget = this._surfaceEl.children[index].offsetTop - this._sizes.itemMarginTop; + } else { + scrollPositionTarget = 0; + } + } + } + + index = Math.max(index, 0); + this._keyboardBehavior.currentIndex = index; + + var element = this._surfaceEl.children[index].winControl._buttonEl; + + if (scrollPositionTarget !== null) { + this._scrollTo(scrollPositionTarget); + } + + _ElementUtilities._setActive(element, this._viewportEl); + } else { + if (this.layout === _UI.Orientation.horizontal) { + var indexOfLastItemOnPage = (page + 1) * sizes.columnsPerPage * sizes.rowsPerPage - 1; + + if (index === indexOfLastItemOnPage) { + // Last item on page so go forward 1 page. + index = index + sizes.columnsPerPage * sizes.rowsPerPage; + } else { + // Not Last item on page so go to last item on page. + index = indexOfLastItemOnPage; + } + } else { + var currentItem = this._surfaceEl.children[this._keyboardBehavior.currentIndex]; + var top = currentItem.offsetTop; + var bottom = top + currentItem.offsetHeight; + var scrollPosition = this._zooming ? this._zoomPosition : this._scrollPosition; + + if (top >= scrollPosition && bottom < scrollPosition + sizes.viewportOffsetHeight) { + // current item is fully on screen. + while (index < this._surfaceEl.children.length - 1 && + this._surfaceEl.children[index + 1].offsetTop + this._surfaceEl.children[index + 1].offsetHeight < scrollPosition + sizes.viewportOffsetHeight) { + index++; + } + } + + if (index === this._keyboardBehavior.currentIndex) { + var scrollPositionForOnePageBelowItem = top + sizes.viewportOffsetHeight; + index = Math.min(this._surfaceEl.children.length - 1, index + 1); + while (index < this._surfaceEl.children.length - 1 && + this._surfaceEl.children[index + 1].offsetTop + this._surfaceEl.children[index + 1].offsetHeight < scrollPositionForOnePageBelowItem) { + index++; + } + + if (index < this._surfaceEl.children.length - 1) { + scrollPositionTarget = this._surfaceEl.children[index + 1].offsetTop - this._sizes.viewportOffsetHeight; + } else { + scrollPositionTarget = this._scrollLength - this._sizes.viewportOffsetHeight; + } + } + } + + index = Math.min(index, this._surfaceEl.children.length - 1); + this._keyboardBehavior.currentIndex = index; + + var element = this._surfaceEl.children[index].winControl._buttonEl; + + if (scrollPositionTarget !== null) { + this._scrollTo(scrollPositionTarget); + } + + try { + _ElementUtilities._setActive(element, this._viewportEl); + } catch (e) { + } + } + } + }, + + _focusHandler: function NavBarContainer_focusHandler(ev) { + var srcElement = ev.target; + if (!this._surfaceEl.contains(srcElement)) { + // Forward focus from NavBarContainer, viewport or surface to the currentIndex. + this._skipEnsureVisible = true; + this._keyboardBehavior._focus(this._keyboardBehavior.currentIndex); + } + }, + + _itemsFocusHandler: function NavBarContainer_itemsFocusHandler(ev) { + // Find the item which is being focused and scroll it to view. + var srcElement = ev.target; + if (srcElement === this._surfaceEl) { + return; + } + + while (srcElement.parentNode !== this._surfaceEl) { + srcElement = srcElement.parentNode; + } + + var index = -1; + while (srcElement) { + index++; + srcElement = srcElement.previousSibling; + } + + if (this._skipEnsureVisible) { + this._skipEnsureVisible = false; + } else { + this._ensureVisible(index); + } + }, + + _ensureVisible: function NavBarContainer_ensureVisible(index, withoutAnimation) { + this._measure(); + + if (this.layout === _UI.Orientation.horizontal) { + var page = Math.floor(index / (this._sizes.rowsPerPage * this._sizes.columnsPerPage)); + this._scrollTo(page * this._sizes.viewportOffsetWidth, withoutAnimation); + } else { + var element = this._surfaceEl.children[index]; + var maxScrollPosition; + if (index > 0) { + maxScrollPosition = element.offsetTop - this._sizes.itemMarginTop; + } else { + maxScrollPosition = 0; + } + var minScrollPosition; + if (index < this._surfaceEl.children.length - 1) { + minScrollPosition = this._surfaceEl.children[index + 1].offsetTop - this._sizes.viewportOffsetHeight; + } else { + minScrollPosition = this._scrollLength - this._sizes.viewportOffsetHeight; + } + + var newScrollPosition = this._zooming ? this._zoomPosition : this._scrollPosition; + newScrollPosition = Math.max(newScrollPosition, minScrollPosition); + newScrollPosition = Math.min(newScrollPosition, maxScrollPosition); + this._scrollTo(newScrollPosition, withoutAnimation); + } + }, + + _scrollTo: function NavBarContainer_scrollTo(targetScrollPosition, withoutAnimation) { + this._measure(); + if (this.layout === _UI.Orientation.horizontal) { + targetScrollPosition = Math.max(0, Math.min(this._scrollLength - this._sizes.viewportOffsetWidth, targetScrollPosition)); + } else { + targetScrollPosition = Math.max(0, Math.min(this._scrollLength - this._sizes.viewportOffsetHeight, targetScrollPosition)); + } + + if (withoutAnimation) { + if (Math.abs(this._scrollPosition - targetScrollPosition) > 1) { + this._zooming = false; + + this._scrollPosition = targetScrollPosition; + this._updatePageUI(); + if (!this._duringForceLayout) { + this._closeSplitIfOpen(); + } + + var newScrollPos = {}; + newScrollPos[(this.layout === _UI.Orientation.horizontal ? "scrollLeft" : "scrollTop")] = targetScrollPosition; + _ElementUtilities.setScrollPosition(this._viewportEl, newScrollPos); + } + } else { + if ((!this._zooming && Math.abs(this._scrollPosition - targetScrollPosition) > 1) || (this._zooming && Math.abs(this._zoomPosition - targetScrollPosition) > 1)) { + this._zoomPosition = targetScrollPosition; + + this._zooming = true; + + if (this.layout === _UI.Orientation.horizontal) { + this._viewportEl.style.msScrollSnapType = "none"; + _ElementUtilities._zoomTo(this._viewportEl, { contentX: targetScrollPosition, contentY: 0, viewportX: 0, viewportY: 0 }); + } else { + _ElementUtilities._zoomTo(this._viewportEl, { contentX: 0, contentY: targetScrollPosition, viewportX: 0, viewportY: 0 }); + } + + this._closeSplitIfOpen(); + } + } + }, + + _MSManipulationStateChangedHandler: function NavBarContainer_MSManipulationStateChangedHandler(e) { + this._currentManipulationState = e.currentState; + + if (e.currentState === e.MS_MANIPULATION_STATE_ACTIVE) { + this._viewportEl.style.msScrollSnapType = ""; + this._zooming = false; + } + + _Global.clearTimeout(this._manipulationStateTimeoutId); + // The extra stop event is firing when an zoomTo is called during another zoomTo and + // also the first zoomTo after a resize. + if (e.currentState === e.MS_MANIPULATION_STATE_STOPPED) { + this._manipulationStateTimeoutId = _Global.setTimeout(function () { + this._viewportEl.style.msScrollSnapType = ""; + this._zooming = false; + this._updateCurrentIndexIfPageChanged(); + }.bind(this), 100); + } + }, + + _scrollHandler: function NavBarContainer_scrollHandler() { + if (this._disposed) { return; } + + this._measured = false; + if (!this._checkingScroll) { + var that = this; + this._checkingScroll = _BaseUtils._requestAnimationFrame(function () { + if (that._disposed) { return; } + that._checkingScroll = null; + + var newScrollPosition = _ElementUtilities.getScrollPosition(that._viewportEl)[(that.layout === _UI.Orientation.horizontal ? "scrollLeft" : "scrollTop")]; + if (newScrollPosition !== that._scrollPosition) { + that._scrollPosition = newScrollPosition; + that._closeSplitIfOpen(); + } + that._updatePageUI(); + + if (!that._zooming && that._currentManipulationState === MS_MANIPULATION_STATE_STOPPED) { + that._updateCurrentIndexIfPageChanged(); + } + }); + } + }, + + _updateCurrentIndexIfPageChanged: function NavBarContainer_updateCurrentIndexIfPageChanged() { + // If you change pages via pagination arrows, mouse wheel, or panning we need to update the current + // item to be the first item on the new page. + if (this.layout === _UI.Orientation.horizontal) { + this._measure(); + var currentPage = this._currentPage; + var firstIndexOnPage = currentPage * this._sizes.rowsPerPage * this._sizes.columnsPerPage; + var lastIndexOnPage = (currentPage + 1) * this._sizes.rowsPerPage * this._sizes.columnsPerPage - 1; + + if (this._keyboardBehavior.currentIndex < firstIndexOnPage || this._keyboardBehavior.currentIndex > lastIndexOnPage) { + // Page change occurred. + this._keyboardBehavior.currentIndex = firstIndexOnPage; + + if (this.element.contains(_Global.document.activeElement)) { + this._keyboardBehavior._focus(this._keyboardBehavior.currentIndex); + } + } + } + }, + + _measure: function NavBarContainer_measure() { + if (!this._measured) { + this._resizeImpl(); + this._writeProfilerMark("measure,StartTM"); + + var sizes = this._sizes; + + sizes.rtl = _Global.getComputedStyle(this._element).direction === "rtl"; + + var itemCount = this._surfaceEl.children.length; + if (itemCount > 0) { + if (!this._sizes.itemMeasured) { + this._writeProfilerMark("measureItem,StartTM"); + + var elementToMeasure = this._surfaceEl.firstElementChild; + // Clear inline margins set by NavBarContainer before measuring. + elementToMeasure.style.margin = ""; + elementToMeasure.style.width = ""; + var elementComputedStyle = _Global.getComputedStyle(elementToMeasure); + sizes.itemOffsetWidth = parseFloat(_Global.getComputedStyle(elementToMeasure).width); + if (elementToMeasure.offsetWidth === 0) { + sizes.itemOffsetWidth = 0; + } + sizes.itemMarginLeft = parseFloat(elementComputedStyle.marginLeft); + sizes.itemMarginRight = parseFloat(elementComputedStyle.marginRight); + sizes.itemWidth = sizes.itemOffsetWidth + sizes.itemMarginLeft + sizes.itemMarginRight; + sizes.itemOffsetHeight = parseFloat(_Global.getComputedStyle(elementToMeasure).height); + if (elementToMeasure.offsetHeight === 0) { + sizes.itemOffsetHeight = 0; + } + sizes.itemMarginTop = parseFloat(elementComputedStyle.marginTop); + sizes.itemMarginBottom = parseFloat(elementComputedStyle.marginBottom); + sizes.itemHeight = sizes.itemOffsetHeight + sizes.itemMarginTop + sizes.itemMarginBottom; + if (sizes.itemOffsetWidth > 0 && sizes.itemOffsetHeight > 0) { + sizes.itemMeasured = true; + } + this._writeProfilerMark("measureItem,StopTM"); + } + + sizes.viewportOffsetWidth = parseFloat(_Global.getComputedStyle(this._viewportEl).width); + if (this._viewportEl.offsetWidth === 0) { + sizes.viewportOffsetWidth = 0; + } + sizes.viewportOffsetHeight = parseFloat(_Global.getComputedStyle(this._viewportEl).height); + if (this._viewportEl.offsetHeight === 0) { + sizes.viewportOffsetHeight = 0; + } + + if (sizes.viewportOffsetWidth === 0 || sizes.itemOffsetHeight === 0) { + this._measured = false; + } else { + this._measured = true; + } + + if (this.layout === _UI.Orientation.horizontal) { + this._scrollPosition = _ElementUtilities.getScrollPosition(this._viewportEl).scrollLeft; + + sizes.leadingEdge = this._leftArrowEl.offsetWidth + parseInt(_Global.getComputedStyle(this._leftArrowEl).marginLeft) + parseInt(_Global.getComputedStyle(this._leftArrowEl).marginRight); + var usableSpace = sizes.viewportOffsetWidth - sizes.leadingEdge * 2; + sizes.maxColumns = sizes.itemWidth ? Math.max(1, Math.floor(usableSpace / sizes.itemWidth)) : 1; + sizes.rowsPerPage = Math.min(this.maxRows, Math.ceil(itemCount / sizes.maxColumns)); + sizes.columnsPerPage = Math.min(sizes.maxColumns, itemCount); + sizes.pages = Math.ceil(itemCount / (sizes.columnsPerPage * sizes.rowsPerPage)); + sizes.trailingEdge = sizes.leadingEdge; + sizes.extraSpace = usableSpace - (sizes.columnsPerPage * sizes.itemWidth); + + this._scrollLength = sizes.viewportOffsetWidth * sizes.pages; + + this._keyboardBehavior.fixedSize = sizes.rowsPerPage; + this._keyboardBehavior.fixedDirection = _KeyboardBehavior._KeyboardBehavior.FixedDirection.height; + + this._surfaceEl.style.height = (sizes.itemHeight * sizes.rowsPerPage) + "px"; + this._surfaceEl.style.width = this._scrollLength + "px"; + } else { + this._scrollPosition = this._viewportEl.scrollTop; + + sizes.leadingEdge = 0; + sizes.rowsPerPage = itemCount; + sizes.columnsPerPage = 1; + sizes.pages = 1; + sizes.trailingEdge = 0; + + // Reminder there is margin collapsing so just use scrollHeight instead of itemHeight * itemCount + this._scrollLength = this._viewportEl.scrollHeight; + + this._keyboardBehavior.fixedSize = sizes.columnsPerPage; + this._keyboardBehavior.fixedDirection = _KeyboardBehavior._KeyboardBehavior.FixedDirection.width; + + this._surfaceEl.style.height = ""; + this._surfaceEl.style.width = ""; + } + + this._updateGridStyles(); + } else { + sizes.pages = 1; + this._hasPreviousContent = false; + this._hasNextContent = false; + this._surfaceEl.style.height = ""; + this._surfaceEl.style.width = ""; + } + + this._writeProfilerMark("measure,StopTM"); + } + }, + + _updateGridStyles: function NavBarContainer_updateGridStyles() { + var sizes = this._sizes; + var itemCount = this._surfaceEl.children.length; + + for (var index = 0; index < itemCount; index++) { + var itemEl = this._surfaceEl.children[index]; + + var marginRight; + var marginLeft; + var width = ""; + + if (this.layout === _UI.Orientation.horizontal) { + var column = Math.floor(index / sizes.rowsPerPage); + var isFirstColumnOnPage = column % sizes.columnsPerPage === 0; + var isLastColumnOnPage = column % sizes.columnsPerPage === sizes.columnsPerPage - 1; + + var extraTrailingMargin = sizes.trailingEdge; + if (this.fixedSize) { + extraTrailingMargin += sizes.extraSpace; + } else { + var spaceToDistribute = sizes.extraSpace - (sizes.maxColumns - sizes.columnsPerPage) * sizes.itemWidth; + width = (sizes.itemOffsetWidth + (spaceToDistribute / sizes.maxColumns)) + "px"; + } + + var extraMarginRight; + var extraMarginLeft; + + if (sizes.rtl) { + extraMarginRight = (isFirstColumnOnPage ? sizes.leadingEdge : 0); + extraMarginLeft = (isLastColumnOnPage ? extraTrailingMargin : 0); + } else { + extraMarginRight = (isLastColumnOnPage ? extraTrailingMargin : 0); + extraMarginLeft = (isFirstColumnOnPage ? sizes.leadingEdge : 0); + } + + marginRight = extraMarginRight + sizes.itemMarginRight + "px"; + marginLeft = extraMarginLeft + sizes.itemMarginLeft + "px"; + } else { + marginRight = ""; + marginLeft = ""; + } + + if (itemEl.style.marginRight !== marginRight) { + itemEl.style.marginRight = marginRight; + } + if (itemEl.style.marginLeft !== marginLeft) { + itemEl.style.marginLeft = marginLeft; + } + if (itemEl.style.width !== width) { + itemEl.style.width = width; + } + } + }, + + _updatePageUI: function NavBarContainer_updatePageUI() { + this._measure(); + var currentPage = this._currentPage; + + this._hasPreviousContent = (currentPage !== 0); + this._hasNextContent = (currentPage < this._sizes.pages - 1); + this._updateArrows(); + + // Always output the pagination indicators so they reserves up space. + if (this._indicatorCount !== this._sizes.pages) { + this._indicatorCount = this._sizes.pages; + this._pageindicatorsEl.innerHTML = new Array(this._sizes.pages + 1).join(''); + } + + for (var i = 0; i < this._pageindicatorsEl.children.length; i++) { + if (i === currentPage) { + _ElementUtilities.addClass(this._pageindicatorsEl.children[i], NavBarContainer._ClassName.currentindicator); + } else { + _ElementUtilities.removeClass(this._pageindicatorsEl.children[i], NavBarContainer._ClassName.currentindicator); + } + } + + if (this._sizes.pages > 1) { + this._viewportEl.style.overflowX = this._panningDisabled ? "hidden" : ""; + this._pageindicatorsEl.style.visibility = ""; + } else { + this._viewportEl.style.overflowX = "hidden"; + this._pageindicatorsEl.style.visibility = "hidden"; + } + + if (this._sizes.pages <= 1 || this._layout !== _UI.Orientation.horizontal) { + this._ariaStartMarker.removeAttribute("aria-flowto"); + this._ariaEndMarker.removeAttribute("x-ms-aria-flowfrom"); + } else { + var firstIndexOnCurrentPage = currentPage * this._sizes.rowsPerPage * this._sizes.columnsPerPage; + var firstItem = this._surfaceEl.children[firstIndexOnCurrentPage].winControl._buttonEl; + _ElementUtilities._ensureId(firstItem); + this._ariaStartMarker.setAttribute("aria-flowto", firstItem.id); + + var lastIndexOnCurrentPage = Math.min(this._surfaceEl.children.length - 1, (currentPage + 1) * this._sizes.rowsPerPage * this._sizes.columnsPerPage - 1); + var lastItem = this._surfaceEl.children[lastIndexOnCurrentPage].winControl._buttonEl; + _ElementUtilities._ensureId(lastItem); + this._ariaEndMarker.setAttribute("x-ms-aria-flowfrom", lastItem.id); + } + }, + + _closeSplitIfOpen: function NavBarContainer_closeSplitIfOpen() { + if (this._currentSplitNavItem) { + if (this._currentSplitNavItem.splitOpened) { + this._currentSplitNavItem._toggleSplit(); + } + this._currentSplitNavItem = null; + } + }, + + _updateArrows: function NavBarContainer_updateArrows() { + var hasLeftContent = this._sizes.rtl ? this._hasNextContent : this._hasPreviousContent; + var hasRightContent = this._sizes.rtl ? this._hasPreviousContent : this._hasNextContent; + + var that = this; + // Previous and next are the arrows, not states. On mouse hover the arrows fade in immediately. If you + // mouse out the arrows fade out after a delay. When you reach the last/first page, the corresponding + // arrow fades out immediately as well. + if ((this._mouseInViewport || this._panningDisabled) && hasLeftContent) { + this._leftArrowWaitingToFadeOut && this._leftArrowWaitingToFadeOut.cancel(); + this._leftArrowWaitingToFadeOut = null; + this._leftArrowFadeOut && this._leftArrowFadeOut.cancel(); + this._leftArrowFadeOut = null; + this._leftArrowEl.style.visibility = ''; + this._leftArrowFadeIn = this._leftArrowFadeIn || Animations.fadeIn(this._leftArrowEl); + } else { + if (hasLeftContent) { + // If we need a delayed fade out and we are already running a delayed fade out just use that one, don't extend it. + // Otherwise create a delayed fade out. + this._leftArrowWaitingToFadeOut = this._leftArrowWaitingToFadeOut || Promise.timeout(_TransitionAnimation._animationTimeAdjustment(buttonFadeDelay)); + } else { + // If we need a immediate fade out and already have a delayed fade out cancel that one and create an immediate one. + this._leftArrowWaitingToFadeOut && this._leftArrowWaitingToFadeOut.cancel(); + this._leftArrowWaitingToFadeOut = Promise.wrap(); + } + this._leftArrowWaitingToFadeOut.then(function () { + // After the delay cancel any fade in if running. If we already were fading out continue it otherwise start the fade out. + this._leftArrowFadeIn && this._leftArrowFadeIn.cancel(); + this._leftArrowFadeIn = null; + this._leftArrowFadeOut = this._leftArrowFadeOut || Animations.fadeOut(this._leftArrowEl).then(function () { + that._leftArrowEl.style.visibility = 'hidden'; + }); + }.bind(this)); + } + + // Same pattern for Next arrow. + if ((this._mouseInViewport || this._panningDisabled) && hasRightContent) { + this._rightArrowWaitingToFadeOut && this._rightArrowWaitingToFadeOut.cancel(); + this._rightArrowWaitingToFadeOut = null; + this._rightArrowFadeOut && this._rightArrowFadeOut.cancel(); + this._rightArrowFadeOut = null; + this._rightArrowEl.style.visibility = ''; + this._rightArrowFadeIn = this._rightArrowFadeIn || Animations.fadeIn(this._rightArrowEl); + } else { + if (hasRightContent) { + this._rightArrowWaitingToFadeOut = this._rightArrowWaitingToFadeOut || Promise.timeout(_TransitionAnimation._animationTimeAdjustment(buttonFadeDelay)); + } else { + this._rightArrowWaitingToFadeOut && this._rightArrowWaitingToFadeOut.cancel(); + this._rightArrowWaitingToFadeOut = Promise.wrap(); + } + this._rightArrowWaitingToFadeOut.then(function () { + this._rightArrowFadeIn && this._rightArrowFadeIn.cancel(); + this._rightArrowFadeIn = null; + this._rightArrowFadeOut = this._rightArrowFadeOut || Animations.fadeOut(this._rightArrowEl).then(function () { + that._rightArrowEl.style.visibility = 'hidden'; + }); + }.bind(this)); + } + }, + + _navbarCommandInvokedHandler: function NavBarContainer_navbarCommandInvokedHandler(ev) { + var srcElement = ev.target; + var index = -1; + while (srcElement) { + index++; + srcElement = srcElement.previousSibling; + } + + this._fireEvent(NavBarContainer._EventName.invoked, { + index: index, + navbarCommand: ev.target.winControl, + data: this._repeater ? this._repeater.data.getAt(index) : null + }); + }, + + _navbarCommandSplitToggleHandler: function NavBarContainer_navbarCommandSplitToggleHandler(ev) { + var srcElement = ev.target; + var index = -1; + while (srcElement) { + index++; + srcElement = srcElement.previousSibling; + } + + var navbarCommand = ev.target.winControl; + + this._closeSplitIfOpen(); + + if (navbarCommand.splitOpened) { + this._currentSplitNavItem = navbarCommand; + } + + this._fireEvent(NavBarContainer._EventName.splitToggle, { + opened: navbarCommand.splitOpened, + index: index, + navbarCommand: navbarCommand, + data: this._repeater ? this._repeater.data.getAt(index) : null + }); + }, + + _fireEvent: function NavBarContainer_fireEvent(type, detail) { + var event = _Global.document.createEvent("CustomEvent"); + event.initCustomEvent(type, true, false, detail); + this.element.dispatchEvent(event); + }, + + _writeProfilerMark: function NavBarContainer_writeProfilerMark(text) { + var message = "WinJS.UI.NavBarContainer:" + this._id + ":" + text; + _WriteProfilerMark(message); + _Log.log && _Log.log(message, null, "navbarcontainerprofiler"); + }, + + dispose: function NavBarContainer_dispose() { + /// + /// + /// Disposes this control. + /// + /// + /// + if (this._disposed) { + return; + } + this._disposed = true; + + if (this._appBarEl) { + this._appBarEl.removeEventListener('beforeopen', this._closeSplitAndResetBound); + this._appBarEl.removeEventListener('beforeopen', this._resizeImplBound); + } + + Navigation.removeEventListener('navigated', this._closeSplitAndResetBound); + + this._leftArrowWaitingToFadeOut && this._leftArrowWaitingToFadeOut.cancel(); + this._leftArrowFadeOut && this._leftArrowFadeOut.cancel(); + this._leftArrowFadeIn && this._leftArrowFadeIn.cancel(); + this._rightArrowWaitingToFadeOut && this._rightArrowWaitingToFadeOut.cancel(); + this._rightArrowFadeOut && this._rightArrowFadeOut.cancel(); + this._rightArrowFadeIn && this._rightArrowFadeIn.cancel(); + + _ElementUtilities._resizeNotifier.unsubscribe(this._element, this._boundResizeHandler); + + this._removeDataChangingEvents(); + this._removeDataChangedEvents(); + } + }, { + // Names of classes used by the NavBarContainer. + _ClassName: { + navbarcontainer: "win-navbarcontainer", + pageindicators: "win-navbarcontainer-pageindicator-box", + indicator: "win-navbarcontainer-pageindicator", + currentindicator: "win-navbarcontainer-pageindicator-current", + vertical: "win-navbarcontainer-vertical", + horizontal: "win-navbarcontainer-horizontal", + viewport: "win-navbarcontainer-viewport", + surface: "win-navbarcontainer-surface", + navarrow: "win-navbarcontainer-navarrow", + navleftarrow: "win-navbarcontainer-navleft", + navrightarrow: "win-navbarcontainer-navright" + }, + _EventName: { + invoked: eventNames.invoked, + splitToggle: eventNames.splittoggle + } + }); + _Base.Class.mix(NavBarContainer, _Control.DOMEventMixin); + return NavBarContainer; + }) + }); + +}); + + +define('require-style!less/styles-navbar',[],function(){}); + +define('require-style!less/colors-navbar',[],function(){}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('WinJS/Controls/NavBar',[ + '../Core/_Global', + '../Core/_WinRT', + '../Core/_Base', + '../Core/_BaseUtils', + '../Core/_Events', + '../Core/_WriteProfilerMark', + '../Promise', + '../Scheduler', + '../Utilities/_ElementUtilities', + '../Utilities/_Hoverable', + "../_Accents", + './_LegacyAppBar', + './NavBar/_Command', + './NavBar/_Container', + 'require-style!less/styles-navbar', + 'require-style!less/colors-navbar' +], function NavBarInit(_Global,_WinRT, _Base, _BaseUtils, _Events, _WriteProfilerMark, Promise, Scheduler, _ElementUtilities, _Hoverable, _Accents, _LegacyAppBar, _Command, _Container) { + "use strict"; + + _Accents.createAccentRule("html.win-hoverable .win-navbarcommand-splitbutton.win-navbarcommand-splitbutton-opened:hover", [{ name: "background-color", value: _Accents.ColorTypes.listSelectHover }]); + _Accents.createAccentRule("html.win-hoverable .win-navbarcommand-splitbutton.win-navbarcommand-splitbutton-opened:hover.win-pressed", [{ name: "background-color", value: _Accents.ColorTypes.listSelectPress }]); + _Accents.createAccentRule(".win-navbarcommand-splitbutton.win-navbarcommand-splitbutton-opened", [{ name: "background-color", value: _Accents.ColorTypes.listSelectRest }]); + _Accents.createAccentRule(".win-navbarcommand-splitbutton.win-navbarcommand-splitbutton-opened.win-pressed", [{ name: "background-color", value: _Accents.ColorTypes.listSelectPress }]); + + var customLayout = "custom"; + + _Base.Namespace.define("WinJS.UI", { + /// + /// + /// Displays navigation commands in a toolbar that the user can open or close. + /// + /// + /// + /// + /// + /// + ///
+ ///
+ ///
+ /// ]]>
+ /// Raised just before opening the NavBar. + /// Raised immediately after an NavBar is fully opened. + /// Raised just before closing the NavBar. + /// Raised immediately after the NavBar is fully closed. + /// Fired when children of NavBar control have been processed from a WinJS.UI.processAll call. + /// Styles the entire NavBar. + /// + /// + NavBar: _Base.Namespace._lazy(function () { + var childrenProcessedEventName = "childrenprocessed"; + var createEvent = _Events._createEventProperty; + + var NavBar = _Base.Class.derive(_LegacyAppBar._LegacyAppBar, function NavBar_ctor(element, options) { + /// + /// + /// Creates a new NavBar. + /// + /// + /// The DOM element that will host the new NavBar control. + /// + /// + /// An object that contains one or more property/value pairs to apply to the new control. Each property of the options object corresponds to one of the control's + /// properties or events. + /// + /// + /// The new NavBar control. + /// + /// + /// + + options = options || {}; + + // Shallow copy object so we can modify it. + options = _BaseUtils._shallowCopy(options); + + // Default to Placement = Top and Layout = Custom + options.placement = options.placement || "top"; + options.layout = customLayout; + options.closedDisplayMode = options.closedDisplayMode || "minimal"; + + _LegacyAppBar._LegacyAppBar.call(this, element, options); + + this._element.addEventListener("beforeopen", this._handleBeforeShow.bind(this)); + + _ElementUtilities.addClass(this.element, NavBar._ClassName.navbar); + + if (_WinRT.Windows.ApplicationModel.DesignMode.designModeEnabled) { + this._processChildren(); + } else { + Scheduler.schedule(this._processChildren.bind(this), Scheduler.Priority.idle, null, "WinJS.UI.NavBar.processChildren"); + } + }, { + + // Restrict values of closedDisplayMode to 'none' or 'minimal' + + /// + /// Gets/Sets how NavBar will display itself while hidden. Values are "none" and "minimal". + /// + closedDisplayMode: { + get: function () { + return this._closedDisplayMode; + }, + set: function (value) { + var newValue = (value === "none" ? "none" : "minimal"); + Object.getOwnPropertyDescriptor(_LegacyAppBar._LegacyAppBar.prototype, "closedDisplayMode").set.call(this, newValue); + this._closedDisplayMode = newValue; + }, + }, + + /// + /// Raised when children of NavBar control have been processed by a WinJS.UI.processAll call. + /// + /// + onchildrenprocessed: createEvent(childrenProcessedEventName), + + _processChildren: function NavBar_processChildren() { + // The NavBar control schedules processAll on its children at idle priority to avoid hurting startup + // performance. If the NavBar is shown before the scheduler gets to the idle job, the NavBar will + // immediately call processAll on its children. If your app needs the children to be processed before + // the scheduled job executes, you may call processChildren to force the processAll call. + if (!this._processed) { + this._processed = true; + + this._writeProfilerMark("processChildren,StartTM"); + var that = this; + var processed = Promise.as(); + if (this._processors) { + this._processors.forEach(function (processAll) { + for (var i = 0, len = that.element.children.length; i < len; i++) { + (function (child) { + processed = processed.then(function () { + processAll(child); + }); + }(that.element.children[i])); + } + }); + } + return processed.then( + function () { + that._writeProfilerMark("processChildren,StopTM"); + that._fireEvent(NavBar._EventName.childrenProcessed); + }, + function () { + that._writeProfilerMark("processChildren,StopTM"); + that._fireEvent(NavBar._EventName.childrenProcessed); + } + ); + } + return Promise.wrap(); + }, + + _show: function NavBar_show() { + // Override _show to call processChildren first. + // + if (this.disabled) { + return; + } + var that = this; + this._processChildren().then(function () { + _LegacyAppBar._LegacyAppBar.prototype._show.call(that); + }); + }, + + _handleBeforeShow: function NavBar_handleBeforeShow() { + // Navbar needs to ensure its elements to have their correct height and width after _LegacyAppBar changes display="none" + // to display="" and _LegacyAppBar needs the elements to have their final height before it measures its own element height + // to do the slide in animation over the correct amount of pixels. + if (this._disposed) { + return; + } + + var navbarcontainerEls = this.element.querySelectorAll('.win-navbarcontainer'); + for (var i = 0; i < navbarcontainerEls.length; i++) { + navbarcontainerEls[i].winControl.forceLayout(); + } + }, + + _fireEvent: function NavBar_fireEvent(type, detail) { + var event = _Global.document.createEvent("CustomEvent"); + event.initCustomEvent(type, true, false, detail || {}); + this.element.dispatchEvent(event); + }, + + _writeProfilerMark: function NavBar_writeProfilerMark(text) { + _WriteProfilerMark("WinJS.UI.NavBar:" + this._id + ":" + text); + } + }, { + _ClassName: { + navbar: "win-navbar" + }, + _EventName: { + childrenProcessed: childrenProcessedEventName + }, + isDeclarativeControlContainer: _BaseUtils.markSupportedForProcessing(function (navbar, callback) { + if (navbar._processed) { + for (var i = 0, len = navbar.element.children.length; i < len; i++) { + callback(navbar.element.children[i]); + } + } else { + navbar._processors = navbar._processors || []; + navbar._processors.push(callback); + } + }) + }); + + return NavBar; + }) + }); + +}); + +define('require-style!less/styles-viewbox',[],function(){}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +// ViewBox control +define('WinJS/Controls/ViewBox',[ + '../Core/_Global', + '../Core/_Base', + '../Core/_BaseUtils', + '../Core/_ErrorFromName', + '../Core/_Resources', + '../Scheduler', + '../Utilities/_Control', + '../Utilities/_Dispose', + '../Utilities/_ElementUtilities', + '../Utilities/_Hoverable', + 'require-style!less/styles-viewbox' + ], function viewboxInit(_Global, _Base, _BaseUtils, _ErrorFromName, _Resources, Scheduler, _Control, _Dispose, _ElementUtilities, _Hoverable) { + "use strict"; + + _Base.Namespace.define("WinJS.UI", { + /// + /// + /// Scales a single child element to fill the available space without + /// resizing it. This control reacts to changes in the size of the container as well as + /// changes in size of the child element. For example, a media query may result in + /// a change in aspect ratio. + /// + /// + /// View Box + /// + /// + ///
ViewBox
]]>
+ /// + /// + ViewBox: _Base.Namespace._lazy(function () { + + var strings = { + get invalidViewBoxChildren() { return "ViewBox expects to only have one child element"; }, + }; + + function onresize(control) { + if (control && !control._resizing) { + control._resizing = control._resizing || 0; + control._resizing++; + try { + control._updateLayout(); + } finally { + control._resizing--; + } + } + } + + function onresizeBox(ev) { + if (ev.target) { + onresize(ev.target.winControl); + } + } + + function onresizeSizer(ev) { + if (ev.target) { + onresize(ev.target.parentElement.winControl); + } + } + + var ViewBox = _Base.Class.define(function ViewBox_ctor(element) { + /// + /// Initializes a new instance of the ViewBox control + /// + /// The DOM element that functions as the scaling box. This element fills 100% of the width and height allotted to it. + /// + /// + /// The set of options to be applied initially to the ViewBox control. + /// + /// A constructed ViewBox control. + /// + this._disposed = false; + + this._element = element || _Global.document.createElement("div"); + var box = this.element; + box.winControl = this; + _ElementUtilities.addClass(box, "win-disposable"); + _ElementUtilities.addClass(box, "win-viewbox"); + this.forceLayout(); + }, { + _sizer: null, + _element: null, + + /// + element: { + get: function () { return this._element; } + }, + + _rtl: { + get: function () { + return _Global.getComputedStyle(this.element).direction === "rtl"; + } + }, + + _initialize: function () { + var box = this.element; + if (box.firstElementChild !== this._sizer) { + if (_BaseUtils.validation) { + if (box.childElementCount !== 1) { + throw new _ErrorFromName("WinJS.UI.ViewBox.InvalidChildren", strings.invalidViewBoxChildren); + } + } + if (this._sizer) { + this._sizer.onresize = null; + } + var sizer = box.firstElementChild; + this._sizer = sizer; + if (sizer) { + _ElementUtilities._resizeNotifier.subscribe(box, onresizeBox); + box.addEventListener("mselementresize", onresizeBox); + _ElementUtilities._resizeNotifier.subscribe(sizer, onresizeSizer); + sizer.addEventListener("mselementresize", onresizeSizer); + } + if (box.clientWidth === 0 && box.clientHeight === 0) { + var that = this; + // Wait for the viewbox to get added to the DOM. It should be added + // in the synchronous block in which _initialize was called. + Scheduler.schedule(function ViewBox_async_initialize() { + that._updateLayout(); + }, Scheduler.Priority.normal, null, "WinJS.UI.ViewBox._updateLayout"); + } + } + }, + _updateLayout: function () { + var sizer = this._sizer; + if (sizer) { + var box = this.element; + var w = sizer.clientWidth; + var h = sizer.clientHeight; + var bw = box.clientWidth; + var bh = box.clientHeight; + var wRatio = bw / w; + var hRatio = bh / h; + var mRatio = Math.min(wRatio, hRatio); + var transX = Math.abs(bw - (w * mRatio)) / 2; + var transY = Math.abs(bh - (h * mRatio)) / 2; + var rtl = this._rtl; + this._sizer.style[_BaseUtils._browserStyleEquivalents["transform"].scriptName] = "translate(" + (rtl ? "-" : "") + transX + "px," + transY + "px) scale(" + mRatio + ")"; + this._sizer.style[_BaseUtils._browserStyleEquivalents["transform-origin"].scriptName] = rtl ? "top right" : "top left"; + } + }, + + dispose: function () { + /// + /// + /// Disposes this ViewBox. + /// + /// + if (this._disposed) { + return; + } + + if (this.element) { + _ElementUtilities._resizeNotifier.unsubscribe(this.element, onresizeBox); + } + if (this._sizer) { + _ElementUtilities._resizeNotifier.unsubscribe(this._sizer, onresizeSizer); + } + + this._disposed = true; + _Dispose.disposeSubTree(this._element); + }, + + forceLayout: function () { + this._initialize(); + this._updateLayout(); + } + }); + _Base.Class.mix(ViewBox, _Control.DOMEventMixin); + return ViewBox; + }) + }); + +}); + + +define('require-style!less/styles-contentdialog',[],function(){}); + +define('require-style!less/colors-contentdialog',[],function(){}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('WinJS/Controls/ContentDialog',[ + '../Application', + '../Utilities/_Dispose', + '../_Accents', + '../Promise', + '../_Signal', + '../_LightDismissService', + '../Core/_BaseUtils', + '../Core/_Global', + '../Core/_WinRT', + '../Core/_Base', + '../Core/_Events', + '../Core/_ErrorFromName', + '../Core/_Resources', + '../Utilities/_Control', + '../Utilities/_ElementUtilities', + '../Utilities/_Hoverable', + '../Animations', + 'require-style!less/styles-contentdialog', + 'require-style!less/colors-contentdialog' +], function contentDialogInit(Application, _Dispose, _Accents, Promise, _Signal, _LightDismissService, _BaseUtils, _Global, _WinRT, _Base, _Events, _ErrorFromName, _Resources, _Control, _ElementUtilities, _Hoverable, _Animations) { + "use strict"; + + _Accents.createAccentRule(".win-contentdialog-dialog", [{ name: "outline-color", value: _Accents.ColorTypes.accent }]); + + _Base.Namespace.define("WinJS.UI", { + /// + /// + /// Displays a modal dialog which can display arbitrary HTML content. + /// + /// + /// + /// + /// ]]> + /// Raised just before showing a dialog. Call preventDefault on this event to stop the dialog from being shown. + /// Raised immediately after a dialog is fully shown. + /// Raised just before hiding a dialog. Call preventDefault on this event to stop the dialog from being hidden. + /// Raised immediately after a dialog is fully hidden. + /// The entire ContentDialog control. + /// The full screen element which dims the content that is behind the dialog. + /// The main element of the dialog which holds the dialog's title, content, and commands. + /// The element which displays the dialog's title. + /// The element which contains the dialog's custom content. + /// The element which contains the dialog's primary and secondary commands. + /// The dialog's primary button. + /// The dialog's secondary button. + /// + /// + ContentDialog: _Base.Namespace._lazy(function () { + var Strings = { + get duplicateConstruction() { return "Invalid argument: Controls may only be instantiated one time for each DOM element"; }, + get controlDisposed() { return "Cannot interact with the control after it has been disposed"; }, + get contentDialogAlreadyShowing() { return "Cannot show a ContentDialog if there is already a ContentDialog that is showing"; } + }; + var DismissalResult = { + /// + /// The dialog was dismissed without the user selecting any of the commands. The user may have + /// dismissed the dialog by hitting the escape key or pressing the hardware back button. + /// + none: "none", + /// + /// The user dismissed the dialog by pressing the primary command. + /// + primary: "primary", + /// + /// The user dismissed the dialog by pressing the secondary command. + /// + secondary: "secondary" + }; + var ClassNames = { + contentDialog: "win-contentdialog", + backgroundOverlay: "win-contentdialog-backgroundoverlay", + dialog: "win-contentdialog-dialog", + title: "win-contentdialog-title", + content: "win-contentdialog-content", + commands: "win-contentdialog-commands", + primaryCommand: "win-contentdialog-primarycommand", + secondaryCommand: "win-contentdialog-secondarycommand", + + _verticalAlignment: "win-contentdialog-verticalalignment", + _scroller: "win-contentdialog-scroller", + _column0or1: "win-contentdialog-column0or1", + _visible: "win-contentdialog-visible", + _tabStop: "win-contentdialog-tabstop", + _commandSpacer: "win-contentdialog-commandspacer" + }; + var EventNames = { + beforeShow: "beforeshow", + afterShow: "aftershow", + beforeHide: "beforehide", + afterHide: "afterhide", + }; + var minContentHeightWithInputPane = 96; + + // WinJS animation promises always complete successfully. This + // helper allows an animation promise to complete in the canceled state + // so that the success handler can be skipped when the animation is + // interrupted. + function cancelablePromise(animationPromise) { + return Promise._cancelBlocker(animationPromise, function () { + animationPromise.cancel(); + }); + } + + function onInputPaneShown(eventObject) { + /*jshint validthis: true */ + eventObject.ensuredFocusedElementInView = true; + this.dialog._renderForInputPane(eventObject.occludedRect.height); + } + + function onInputPaneHidden() { + /*jshint validthis: true */ + this.dialog._clearInputPaneRendering(); + } + + // Noop function, used in the various states to indicate that they don't support a given + // message. Named with the somewhat cute name '_' because it reads really well in the states. + + function _() { } + + // Implementing the control as a state machine helps us correctly handle: + // - re-entrancy while firing events + // - calls into the control during asynchronous operations (e.g. animations) + // + // Many of the states do their "enter" work within a promise chain. The idea is that if + // the state is interrupted and exits, the rest of its work can be skipped by canceling + // the promise chain. + // An interesting detail is that anytime the state may call into app code (e.g. due to + // firing an event), the current promise must end and a new promise must be chained off of it. + // This is necessary because the app code may interact with the ContentDialog and cause it to + // change states. If we didn't create a new promise, then the very next line of code that runs + // after calling into app code may not be valid because the state may have exited. Starting a + // new promise after each call into app code prevents us from having to worry about this + // problem. In this configuration, when a promise's success handler runs, it guarantees that + // the state hasn't exited. + // For similar reasons, each of the promise chains created in "enter" starts off with a _Signal + // which is completed at the end of the "enter" function (this boilerplate is abstracted away by + // the "interruptible" function). The reason is that we don't want any of the code in "enter" + // to run until the promise chain has been stored in a variable. If we didn't do this (e.g. instead, + // started the promise chain with Promise.wrap()), then the "enter" code could trigger the "exit" + // function (via app code) before the promise chain had been stored in a variable. Under these + // circumstances, the promise chain would be uncancelable and so the "enter" work would be + // unskippable. This wouldn't be good when we needed the state to exit early. + + // These two functions manage interruptible work promises (one creates them the other cancels + // them). They communicate with each other thru the _interruptibleWorkPromises property which + // "interruptible" creates on your object. + + function interruptible(object, workFn) { + object._interruptibleWorkPromises = object._interruptibleWorkPromises || []; + var workStoredSignal = new _Signal(); + object._interruptibleWorkPromises.push(workFn(object, workStoredSignal.promise)); + workStoredSignal.complete(); + } + + function cancelInterruptibles() { + /*jshint validthis: true */ + (this._interruptibleWorkPromises || []).forEach(function (workPromise) { + workPromise.cancel(); + }); + } + + // Transitions: + // When created, the control will take the following initialization transition: + // Init -> Hidden + // Following that, the life of the dialog will be dominated by the following 3 + // sequences of transitions. In geneneral, these sequences are uninterruptible. + // Hidden -> BeforeShow -> Hidden (when preventDefault is called on beforeshow event) + // Hidden -> BeforeShow -> Showing -> Shown + // Shown -> BeforeHide -> Hiding -> Hidden + // Shown -> BeforeHide -> Shown (when preventDefault is called on beforehide event) + // However, any state can be interrupted to go to the Disposed state: + // * -> Disposed + // + // interface IContentDialogState { + // // Debugging + // name: string; + // // State lifecycle + // enter(arg0); + // exit(); + // // ContentDialog's public API surface + // hidden: boolean; + // show(); + // hide(dismissalResult); + // // Events + // onCommandClicked(dismissalResult); + // onInputPaneShown(eventObject); + // onInputPaneHidden(); + // // Provided by _setState for use within the state + // dialog: WinJS.UI.ContentDialog; + // } + + var States = { + // Initial state. Initializes state on the dialog shared by the various states. + Init: _Base.Class.define(null, { + name: "Init", + hidden: true, + enter: function ContentDialog_InitState_enter() { + var dialog = this.dialog; + dialog._dismissable = new _LightDismissService.ModalElement({ + element: dialog._dom.root, + tabIndex: dialog._dom.root.hasAttribute("tabIndex") ? dialog._dom.root.tabIndex : -1, + onLightDismiss: function () { + dialog.hide(DismissalResult.none); + }, + onTakeFocus: function (useSetActive) { + dialog._dismissable.restoreFocus() || + _ElementUtilities._focusFirstFocusableElement(dialog._dom.content) || + _ElementUtilities._tryFocusOnAnyElement(dialog._dom.dialog, useSetActive); + } + }); + this.dialog._dismissedSignal = null; // The signal will be created on demand when show() is called + this.dialog._setState(States.Hidden, false); + }, + exit: _, + show: function ContentDialog_InitState_show() { + throw "It's illegal to call show on the Init state"; + }, + hide: _, + onCommandClicked: _, + onInputPaneShown: _, + onInputPaneHidden: _ + }), + // A rest state. The dialog is hidden and is waiting for the app to call show. + Hidden: _Base.Class.define(null, { + name: "Hidden", + hidden: true, + enter: function ContentDialog_HiddenState_enter(showIsPending) { + if (showIsPending) { + this.show(); + } + }, + exit: _, + show: function ContentDialog_HiddenState_show() { + var dismissedSignal = this.dialog._dismissedSignal = new _Signal(); // save the signal in case it changes when switching states + this.dialog._setState(States.BeforeShow); + return dismissedSignal.promise; + }, + hide: _, + onCommandClicked: _, + onInputPaneShown: _, + onInputPaneHidden: _ + }), + // An event state. The dialog fires the beforeshow event. + BeforeShow: _Base.Class.define(null, { + name: "BeforeShow", + hidden: true, + enter: function ContentDialog_BeforeShowState_enter() { + interruptible(this, function (that, ready) { + return ready.then(function () { + return that.dialog._fireBeforeShow(); // Give opportunity for chain to be canceled when calling into app code + }).then(function (shouldShow) { + if (!shouldShow) { + that.dialog._cancelDismissalPromise(null); // Give opportunity for chain to be canceled when calling into app code + } + return shouldShow; + }).then(function (shouldShow) { + if (shouldShow) { + that.dialog._setState(States.Showing); + } else { + that.dialog._setState(States.Hidden, false); + } + }); + }); + }, + exit: cancelInterruptibles, + show: function ContentDialog_BeforeShowState_show() { + return Promise.wrapError(new _ErrorFromName("WinJS.UI.ContentDialog.ContentDialogAlreadyShowing", Strings.contentDialogAlreadyShowing)); + }, + hide: _, + onCommandClicked: _, + onInputPaneShown: _, + onInputPaneHidden: _ + }), + // An animation/event state. The dialog plays its entrance animation and fires aftershow. + Showing: _Base.Class.define(null, { + name: "Showing", + hidden: { + get: function ContentDialog_ShowingState_hidden_get() { + return !!this._pendingHide; + } + }, + enter: function ContentDialog_ShowingState_enter() { + interruptible(this, function (that, ready) { + return ready.then(function () { + that._pendingHide = null; + _ElementUtilities.addClass(that.dialog._dom.root, ClassNames._visible); + that.dialog._addExternalListeners(); + if (_WinRT.Windows.UI.ViewManagement.InputPane) { + var inputPaneHeight = _WinRT.Windows.UI.ViewManagement.InputPane.getForCurrentView().occludedRect.height; + if (inputPaneHeight > 0) { + that.dialog._renderForInputPane(inputPaneHeight); + } + } + _LightDismissService.shown(that.dialog._dismissable); + return that.dialog._playEntranceAnimation(); + }).then(function () { + that.dialog._fireEvent(EventNames.afterShow); // Give opportunity for chain to be canceled when calling into app code + }).then(function () { + that.dialog._setState(States.Shown, that._pendingHide); + }); + }); + }, + exit: cancelInterruptibles, + show: function ContentDialog_ShowingState_show() { + if (this._pendingHide) { + var dismissalResult = this._pendingHide.dismissalResult; + this._pendingHide = null; + return this.dialog._resetDismissalPromise(dismissalResult, new _Signal()).promise; + } else { + return Promise.wrapError(new _ErrorFromName("WinJS.UI.ContentDialog.ContentDialogAlreadyShowing", Strings.contentDialogAlreadyShowing)); + } + }, + hide: function ContentDialog_ShowingState_hide(dismissalResult) { + this._pendingHide = { dismissalResult: dismissalResult }; + }, + onCommandClicked: _, + onInputPaneShown: onInputPaneShown, + onInputPaneHidden: onInputPaneHidden + }), + // A rest state. The dialog is shown and is waiting for the user or the app to trigger hide. + Shown: _Base.Class.define(null, { + name: "Shown", + hidden: false, + enter: function ContentDialog_ShownState_enter(pendingHide) { + if (pendingHide) { + this.hide(pendingHide.dismissalResult); + } + }, + exit: _, + show: function ContentDialog_ShownState_show() { + return Promise.wrapError(new _ErrorFromName("WinJS.UI.ContentDialog.ContentDialogAlreadyShowing", Strings.contentDialogAlreadyShowing)); + }, + hide: function ContentDialog_ShownState_hide(dismissalResult) { + this.dialog._setState(States.BeforeHide, dismissalResult); + }, + onCommandClicked: function ContentDialog_ShownState_onCommandClicked(dismissalResult) { + this.hide(dismissalResult); + }, + onInputPaneShown: onInputPaneShown, + onInputPaneHidden: onInputPaneHidden + }), + // An event state. The dialog fires the beforehide event. + BeforeHide: _Base.Class.define(null, { + name: "BeforeHide", + hidden: false, + enter: function ContentDialog_BeforeHideState_enter(dismissalResult) { + interruptible(this, function (that, ready) { + return ready.then(function () { + return that.dialog._fireBeforeHide(dismissalResult); // Give opportunity for chain to be canceled when calling into app code + }).then(function (shouldHide) { + if (shouldHide) { + that.dialog._setState(States.Hiding, dismissalResult); + } else { + that.dialog._setState(States.Shown, null); + } + }); + }); + }, + exit: cancelInterruptibles, + show: function ContentDialog_BeforeHideState_show() { + return Promise.wrapError(new _ErrorFromName("WinJS.UI.ContentDialog.ContentDialogAlreadyShowing", Strings.contentDialogAlreadyShowing)); + }, + hide: _, + onCommandClicked: _, + onInputPaneShown: onInputPaneShown, + onInputPaneHidden: onInputPaneHidden + }), + // An animation/event state. The dialog plays the exit animation and fires the afterhide event. + Hiding: _Base.Class.define(null, { + name: "Hiding", + hidden: { + get: function ContentDialog_HidingState_hidden_get() { + return !this._showIsPending; + } + }, + enter: function ContentDialog_HidingState_enter(dismissalResult) { + interruptible(this, function (that, ready) { + return ready.then(function () { + that._showIsPending = false; + that.dialog._resetDismissalPromise(dismissalResult, null); // Give opportunity for chain to be canceled when calling into app code + }).then(function () { + return that.dialog._playExitAnimation(); + }).then(function () { + that.dialog._removeExternalListeners(); + _LightDismissService.hidden(that.dialog._dismissable); + _ElementUtilities.removeClass(that.dialog._dom.root, ClassNames._visible); + that.dialog._clearInputPaneRendering(); + that.dialog._fireAfterHide(dismissalResult); // Give opportunity for chain to be canceled when calling into app code + }).then(function () { + that.dialog._setState(States.Hidden, that._showIsPending); + }); + }); + }, + exit: cancelInterruptibles, + show: function ContentDialog_HidingState_show() { + if (this._showIsPending) { + return Promise.wrapError(new _ErrorFromName("WinJS.UI.ContentDialog.ContentDialogAlreadyShowing", Strings.contentDialogAlreadyShowing)); + } else { + this._showIsPending = true; + this.dialog._dismissedSignal = new _Signal(); + return this.dialog._dismissedSignal.promise; + } + }, + hide: function ContentDialog_HidingState_hide(dismissalResult) { + if (this._showIsPending) { + this._showIsPending = false; + this.dialog._resetDismissalPromise(dismissalResult, null); + } + }, + onCommandClicked: _, + onInputPaneShown: _, + onInputPaneHidden: _ + }), + Disposed: _Base.Class.define(null, { + name: "Disposed", + hidden: true, + enter: function ContentDialog_DisposedState_enter() { + _LightDismissService.hidden(this.dialog._dismissable); + this.dialog._removeExternalListeners(); + if (this.dialog._dismissedSignal) { + this.dialog._dismissedSignal.error(new _ErrorFromName("WinJS.UI.ContentDialog.ControlDisposed", Strings.controlDisposed)); + } + }, + exit: _, + show: function ContentDialog_DisposedState_show() { + return Promise.wrapError(new _ErrorFromName("WinJS.UI.ContentDialog.ControlDisposed", Strings.controlDisposed)); + }, + hide: _, + onCommandClicked: _, + onInputPaneShown: _, + onInputPaneHidden: _ + }), + }; + + var ContentDialog = _Base.Class.define(function ContentDialog_ctor(element, options) { + /// + /// + /// Creates a new ContentDialog control. + /// + /// + /// The DOM element that hosts the ContentDialog control. + /// + /// + /// An object that contains one or more property/value pairs to apply to the new control. + /// Each property of the options object corresponds to one of the control's properties or events. + /// Event names must begin with "on". For example, to provide a handler for the beforehide event, + /// add a property named "onbeforehide" to the options object and set its value to the event handler. + /// + /// + /// The new ContentDialog. + /// + /// + + // Check to make sure we weren't duplicated + if (element && element.winControl) { + throw new _ErrorFromName("WinJS.UI.ContentDialog.DuplicateConstruction", Strings.duplicateConstruction); + } + options = options || {}; + + this._onInputPaneShownBound = this._onInputPaneShown.bind(this); + this._onInputPaneHiddenBound = this._onInputPaneHidden.bind(this); + + this._disposed = false; + this._resizedForInputPane = false; + this._currentFocus = null; + + this._initializeDom(element || _Global.document.createElement("div")); + this._setState(States.Init); + + this.title = ""; + this.primaryCommandText = ""; + this.primaryCommandDisabled = false; + this.secondaryCommandText = ""; + this.secondaryCommandDisabled = false; + + _Control.setOptions(this, options); + }, { + /// + element: { + get: function ContentDialog_element_get() { + return this._dom.root; + } + }, + + /// + /// The text displayed as the title of the dialog. + /// + title: { + get: function ContentDialog_title_get() { + return this._title; + }, + set: function ContentDialog_title_set(value) { + value = value || ""; + if (this._title !== value) { + this._title = value; + this._dom.title.textContent = value; + this._dom.title.style.display = value ? "" : "none"; + } + } + }, + + /// + /// The text displayed on the primary command's button. + /// + primaryCommandText: { + get: function ContentDialog_primaryCommandText_get() { + return this._primaryCommandText; + }, + set: function ContentDialog_primaryCommandText_set(value) { + value = value || ""; + if (this._primaryCommandText !== value) { + this._primaryCommandText = value; + this._dom.commands[0].textContent = value; + this._updateCommandsUI(); + } + } + }, + + /// + /// The text displayed on the secondary command's button. + /// + secondaryCommandText: { + get: function ContentDialog_secondaryCommandText_get() { + return this._secondaryCommandText; + }, + set: function ContentDialog_secondaryCommandText_set(value) { + value = value || ""; + if (this._secondaryCommandText !== value) { + this._secondaryCommandText = value; + this._dom.commands[1].textContent = value; + this._updateCommandsUI(); + } + } + }, + + /// + /// Indicates whether the button representing the primary command is currently disabled. + /// + primaryCommandDisabled: { + get: function ContentDialog_primaryCommandDisabled_get() { + return this._primaryCommandDisabled; + }, + set: function ContentDialog_primaryCommandDisabled_set(value) { + value = !!value; + if (this._primaryCommandDisabled !== value) { + this._primaryCommandDisabled = value; + this._dom.commands[0].disabled = value; + } + } + }, + + /// + /// Indicates whether the button representing the secondary command is currently disabled. + /// + secondaryCommandDisabled: { + get: function ContentDialog_secondaryCommandDisabled_get() { + return this._secondaryCommandDisabled; + }, + set: function ContentDialog_secondaryCommandDisabled_set(value) { + value = !!value; + if (this._secondaryCommandDisabled !== value) { + this._secondaryCommandDisabled = value; + this._dom.commands[1].disabled = value; + } + } + }, + + /// + hidden: { + get: function ContentDialog_hidden_get() { + return this._state.hidden; + }, + set: function ContentDialog_hidden_set(hidden) { + if (!hidden && this._state.hidden) { + var nop = function () { + }; + // Show returns a promise. If hidden is set while the ContentDialog is disposed, show will return a promise + // error which will be impossible to handle and it'll cause the app to terminate. We'll eat the promise returned by show + // to stop that from happening. + this.show().done(nop, nop); + } else if (hidden && !this._state.hidden) { + this.hide(DismissalResult.none); + } + } + }, + + dispose: function ContentDialog_dispose() { + /// + /// + /// Disposes this control. + /// + /// + if (this._disposed) { + return; + } + this._setState(States.Disposed); + this._disposed = true; + _Dispose._disposeElement(this._dom.content); + }, + + show: function ContentDialog_show() { + /// + /// + /// Shows the ContentDialog. Only one ContentDialog may be shown at a time. If another + /// ContentDialog is already shown, this ContentDialog will remain hidden. + /// + /// + /// A promise which is successfully fulfilled when the dialog is dismissed. The + /// completion value indicates the dialog's dismissal result. This may + /// be 'primary', 'secondary', 'none', or whatever custom value was passed to hide. + /// If this ContentDialog cannot be shown because a ContentDialog is already showing + /// or the ContentDialog is disposed, then the return value is a promise which is in + /// an error state. If preventDefault() is called on the beforeshow event, then this + /// promise will be canceled. + /// + /// + return this._state.show(); + }, + + hide: function ContentDialog_hide(result) { + /// + /// + /// Hides the ContentDialog. + /// + /// + /// A value indicating why the dialog is being hidden. The promise returned + /// by show will be fulfilled with this value. + /// + /// + this._state.hide(result === undefined ? DismissalResult.none : result); + }, + + _initializeDom: function ContentDialog_initializeDom(root) { + // Reparent the children of the root element into the content element. + var contentEl = _Global.document.createElement("div"); + contentEl.className = ClassNames.content; + _ElementUtilities._reparentChildren(root, contentEl); + + root.winControl = this; + _ElementUtilities.addClass(root, ClassNames.contentDialog); + _ElementUtilities.addClass(root, ClassNames._verticalAlignment); + _ElementUtilities.addClass(root, "win-disposable"); + root.innerHTML = + '
' + + '
' + + '' + + '
' + + '
'; + + var dom = {}; + dom.root = root; + dom.backgroundOverlay = dom.root.firstElementChild; + dom.startBodyTab = dom.backgroundOverlay.nextElementSibling; + dom.dialog = dom.startBodyTab.nextElementSibling; + dom.title = dom.dialog.firstElementChild; + dom.scroller = dom.title.nextElementSibling; + dom.commandContainer = dom.scroller.nextElementSibling; + dom.commandSpacer = dom.commandContainer.firstElementChild; + dom.commands = []; + dom.commands.push(dom.commandSpacer.nextElementSibling); + dom.commands.push(dom.commands[0].nextElementSibling); + dom.endBodyTab = dom.dialog.nextElementSibling; + dom.content = contentEl; + this._dom = dom; + + // Put the developer's content into the scroller + dom.scroller.appendChild(dom.content); + + _ElementUtilities._ensureId(dom.title); + _ElementUtilities._ensureId(dom.startBodyTab); + _ElementUtilities._ensureId(dom.endBodyTab); + dom.dialog.setAttribute("aria-labelledby", dom.title.id); + dom.startBodyTab.setAttribute("x-ms-aria-flowfrom", dom.endBodyTab.id); + dom.endBodyTab.setAttribute("aria-flowto", dom.startBodyTab.id); + this._updateTabIndices(); + + dom.root.addEventListener("keydown", this._onKeyDownEnteringElement.bind(this), true); + _ElementUtilities._addEventListener(dom.root, "pointerdown", this._onPointerDown.bind(this)); + _ElementUtilities._addEventListener(dom.root, "pointerup", this._onPointerUp.bind(this)); + dom.root.addEventListener("click", this._onClick.bind(this)); + _ElementUtilities._addEventListener(dom.startBodyTab, "focusin", this._onStartBodyTabFocusIn.bind(this)); + _ElementUtilities._addEventListener(dom.endBodyTab, "focusin", this._onEndBodyTabFocusIn.bind(this)); + dom.commands[0].addEventListener("click", this._onCommandClicked.bind(this, DismissalResult.primary)); + dom.commands[1].addEventListener("click", this._onCommandClicked.bind(this, DismissalResult.secondary)); + }, + + _updateCommandsUI: function ContentDialog_updateCommandsUI() { + this._dom.commands[0].style.display = this.primaryCommandText ? "" : "none"; + this._dom.commands[1].style.display = this.secondaryCommandText ? "" : "none"; + + // commandSpacer's purpose is to ensure that when only 1 button is shown, that button takes up half + // the width of the dialog and is right-aligned. It works by: + // - When only one command is shown: + // - Coming before the other command in the DOM (so the other command will look right-aligned) + // - Having the same flex-grow as the other command (so it occupies half of the space) + // - Having visibility: hidden (so it's invisible but it takes up space) + // - When both commands are shown: + // - Having display: none (so it doesn't occupy any space and the two shown commands each take up half the dialog) + // - When 0 commands are shown: + // - Having display: none (so the commands area takes up no space) + this._dom.commandSpacer.style.display = this.primaryCommandText && !this.secondaryCommandText || !this.primaryCommandText && this.secondaryCommandText ? "" : "none"; + }, + + // _updateTabIndices and _updateTabIndicesImpl are used in tests + _updateTabIndices: function ContentDialog_updateTabIndices() { + if (!this._updateTabIndicesThrottled) { + this._updateTabIndicesThrottled = _BaseUtils._throttledFunction(100, this._updateTabIndicesImpl.bind(this)); + } + this._updateTabIndicesThrottled(); + }, + _updateTabIndicesImpl: function ContentDialog_updateTabIndicesImpl() { + var tabIndex = _ElementUtilities._getHighAndLowTabIndices(this._dom.content); + this._dom.startBodyTab.tabIndex = tabIndex.lowest; + this._dom.commands[0].tabIndex = tabIndex.highest; + this._dom.commands[1].tabIndex = tabIndex.highest; + this._dom.endBodyTab.tabIndex = tabIndex.highest; + }, + + _elementInDialog: function ContentDialog_elementInDialog(element) { + return this._dom.dialog.contains(element) || element === this._dom.startBodyTab || element === this._dom.endBodyTab; + }, + + _onCommandClicked: function ContentDialog_onCommandClicked(dismissalResult) { + this._state.onCommandClicked(dismissalResult); + }, + + _onPointerDown: function ContentDialog_onPointerDown(eventObject) { + eventObject.stopPropagation(); + if (!this._elementInDialog(eventObject.target)) { + eventObject.preventDefault(); + } + }, + + _onPointerUp: function ContentDialog_onPointerUp(eventObject) { + eventObject.stopPropagation(); + if (!this._elementInDialog(eventObject.target)) { + eventObject.preventDefault(); + } + }, + + _onClick: function ContentDialog_onClick(eventObject) { + eventObject.stopPropagation(); + if (!this._elementInDialog(eventObject.target)) { + eventObject.preventDefault(); + } + }, + + _onKeyDownEnteringElement: function ContentDialog_onKeyDownEnteringElement(eventObject) { + if (eventObject.keyCode === _ElementUtilities.Key.tab) { + this._updateTabIndices(); + } + }, + + _onStartBodyTabFocusIn: function ContentDialog_onStartBodyTabFocusIn() { + _ElementUtilities._focusLastFocusableElement(this._dom.dialog); + }, + + _onEndBodyTabFocusIn: function ContentDialog_onEndBodyTabFocusIn() { + _ElementUtilities._focusFirstFocusableElement(this._dom.dialog); + }, + + _onInputPaneShown: function ContentDialog_onInputPaneShown(eventObject) { + this._state.onInputPaneShown(eventObject.detail.originalEvent); + }, + + _onInputPaneHidden: function ContentDialog_onInputPaneHidden() { + this._state.onInputPaneHidden(); + }, + + // + // Methods called by states + // + + _setState: function ContentDialog_setState(NewState, arg0) { + if (!this._disposed) { + this._state && this._state.exit(); + this._state = new NewState(); + this._state.dialog = this; + this._state.enter(arg0); + } + }, + + // Calls into arbitrary app code + _resetDismissalPromise: function ContentDialog_resetDismissalPromise(dismissalResult, newSignal) { + var dismissedSignal = this._dismissedSignal; + var newDismissedSignal = this._dismissedSignal = newSignal; + dismissedSignal.complete({ result: dismissalResult }); + return newDismissedSignal; + }, + + // Calls into arbitrary app code + _cancelDismissalPromise: function ContentDialog_cancelDismissalPromise(newSignal) { + var dismissedSignal = this._dismissedSignal; + var newDismissedSignal = this._dismissedSignal = newSignal; + dismissedSignal.cancel(); + return newDismissedSignal; + }, + + // Calls into arbitrary app code + _fireEvent: function ContentDialog_fireEvent(eventName, options) { + options = options || {}; + var detail = options.detail || null; + var cancelable = !!options.cancelable; + + var eventObject = _Global.document.createEvent("CustomEvent"); + eventObject.initCustomEvent(eventName, true, cancelable, detail); + return this._dom.root.dispatchEvent(eventObject); + }, + + // Calls into arbitrary app code + _fireBeforeShow: function ContentDialog_fireBeforeShow() { + return this._fireEvent(EventNames.beforeShow, { + cancelable: true + }); + }, + + // Calls into arbitrary app code + _fireBeforeHide: function ContentDialog_fireBeforeHide(dismissalResult) { + return this._fireEvent(EventNames.beforeHide, { + detail: { result: dismissalResult }, + cancelable: true + }); + }, + + // Calls into arbitrary app code + _fireAfterHide: function ContentDialog_fireAfterHide(dismissalResult) { + this._fireEvent(EventNames.afterHide, { + detail: { result: dismissalResult } + }); + }, + + _playEntranceAnimation: function ContentDialog_playEntranceAnimation() { + return cancelablePromise(_Animations.fadeIn(this._dom.root)); + }, + + _playExitAnimation: function ContentDialog_playExitAnimation() { + return cancelablePromise(_Animations.fadeOut(this._dom.root)); + }, + + _addExternalListeners: function ContentDialog_addExternalListeners() { + _ElementUtilities._inputPaneListener.addEventListener(this._dom.root, "showing", this._onInputPaneShownBound); + _ElementUtilities._inputPaneListener.addEventListener(this._dom.root, "hiding", this._onInputPaneShownBound); + }, + + _removeExternalListeners: function ContentDialog_removeExternalListeners() { + _ElementUtilities._inputPaneListener.removeEventListener(this._dom.root, "showing", this._onInputPaneShownBound); + _ElementUtilities._inputPaneListener.removeEventListener(this._dom.root, "hiding", this._onInputPaneShownBound); + }, + + _renderForInputPane: function ContentDialog_renderForInputPane(inputPaneHeight) { + this._clearInputPaneRendering(); + + var dialog = this._dom.dialog; + var style = dialog.style; + var left = dialog.offsetLeft; + var top = dialog.offsetTop; + var height = dialog.offsetHeight; + var bottom = top + height; + var visibleBottom = this._dom.root.offsetHeight - inputPaneHeight; + var titleHeight = _ElementUtilities.getTotalHeight(this._dom.title); + var commandsHeight = _ElementUtilities.getTotalHeight(this._dom.commandContainer); + + if (bottom > visibleBottom) { + var newHeight = height - (bottom - visibleBottom); + if (newHeight - titleHeight - commandsHeight < minContentHeightWithInputPane) { + // Put title into scroller so there's more screen real estate for the content + this._dom.scroller.insertBefore(this._dom.title, this._dom.content); + } + + this._dom.root.style.display = "block"; + style.height = newHeight + "px"; + style.position = "absolute"; + style.left = left + "px"; + style.top = top + "px"; + style.minHeight = 0; + + this._resizedForInputPane = true; + _Global.document.activeElement.focus(); // Ensure activeElement is scrolled into view + } + }, + + _clearInputPaneRendering: function ContentDialog_clearInputPaneRendering() { + if (this._resizedForInputPane) { + if (this._dom.title.parentNode !== this._dom.dialog) { + // Make sure the title isn't in the scroller + this._dom.dialog.insertBefore(this._dom.title, this._dom.scroller); + } + + var style = this._dom.dialog.style; + this._dom.root.style.display = ""; + style.height = ""; + style.position = ""; + style.left = ""; + style.top = ""; + style.minHeight = ""; + this._resizedForInputPane = false; + } + } + }, { + /// + /// Specifies the result of dismissing the ContentDialog. + /// + DismissalResult: DismissalResult, + + _ClassNames: ClassNames + }); + _Base.Class.mix(ContentDialog, _Events.createEventProperties( + "beforeshow", + "aftershow", + "beforehide", + "afterhide" + )); + _Base.Class.mix(ContentDialog, _Control.DOMEventMixin); + return ContentDialog; + }) + }); +}); + + +define('require-style!less/styles-splitview',[],function(){}); + +define('require-style!less/colors-splitview',[],function(){}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// +define('WinJS/Controls/SplitView/_SplitView',["require", "exports", '../../Animations', '../../Core/_Base', '../../Core/_BaseUtils', '../../Utilities/_Control', '../../Utilities/_Dispose', '../../Utilities/_ElementUtilities', '../../Core/_ErrorFromName', '../../Core/_Events', '../../Core/_Global', '../../_LightDismissService', '../../Utilities/_OpenCloseMachine'], function (require, exports, Animations, _Base, _BaseUtils, _Control, _Dispose, _ElementUtilities, _ErrorFromName, _Events, _Global, _LightDismissService, _OpenCloseMachine) { + require(["require-style!less/styles-splitview"]); + require(["require-style!less/colors-splitview"]); + "use strict"; + var transformNames = _BaseUtils._browserStyleEquivalents["transform"]; + var Strings = { + get duplicateConstruction() { + return "Invalid argument: Controls may only be instantiated one time for each DOM element"; + } + }; + var ClassNames = { + splitView: "win-splitview", + pane: "win-splitview-pane", + content: "win-splitview-content", + // closed/opened + paneClosed: "win-splitview-pane-closed", + paneOpened: "win-splitview-pane-opened", + _panePlaceholder: "win-splitview-paneplaceholder", + _paneWrapper: "win-splitview-panewrapper", + _contentWrapper: "win-splitview-contentwrapper", + // placement + _placementLeft: "win-splitview-placementleft", + _placementRight: "win-splitview-placementright", + _placementTop: "win-splitview-placementtop", + _placementBottom: "win-splitview-placementbottom", + // closed display mode + _closedDisplayNone: "win-splitview-closeddisplaynone", + _closedDisplayInline: "win-splitview-closeddisplayinline", + // opened display mode + _openedDisplayInline: "win-splitview-openeddisplayinline", + _openedDisplayOverlay: "win-splitview-openeddisplayoverlay" + }; + var EventNames = { + beforeOpen: "beforeopen", + afterOpen: "afteropen", + beforeClose: "beforeclose", + afterClose: "afterclose" + }; + var Dimension = { + width: "width", + height: "height" + }; + var ClosedDisplayMode = { + /// + /// When the pane is closed, it is not visible and doesn't take up any space. + /// + none: "none", + /// + /// When the pane is closed, it occupies space leaving less room for the SplitView's content. + /// + inline: "inline" + }; + var OpenedDisplayMode = { + /// + /// When the pane is open, it occupies space leaving less room for the SplitView's content. + /// + inline: "inline", + /// + /// When the pane is open, it doesn't take up any space and it is light dismissable. + /// + overlay: "overlay" + }; + var PanePlacement = { + /// + /// Pane is positioned left of the SplitView's content. + /// + left: "left", + /// + /// Pane is positioned right of the SplitView's content. + /// + right: "right", + /// + /// Pane is positioned above the SplitView's content. + /// + top: "top", + /// + /// Pane is positioned below the SplitView's content. + /// + bottom: "bottom" + }; + var closedDisplayModeClassMap = {}; + closedDisplayModeClassMap[ClosedDisplayMode.none] = ClassNames._closedDisplayNone; + closedDisplayModeClassMap[ClosedDisplayMode.inline] = ClassNames._closedDisplayInline; + var openedDisplayModeClassMap = {}; + openedDisplayModeClassMap[OpenedDisplayMode.overlay] = ClassNames._openedDisplayOverlay; + openedDisplayModeClassMap[OpenedDisplayMode.inline] = ClassNames._openedDisplayInline; + var panePlacementClassMap = {}; + panePlacementClassMap[PanePlacement.left] = ClassNames._placementLeft; + panePlacementClassMap[PanePlacement.right] = ClassNames._placementRight; + panePlacementClassMap[PanePlacement.top] = ClassNames._placementTop; + panePlacementClassMap[PanePlacement.bottom] = ClassNames._placementBottom; + // Versions of add/removeClass that are no ops when called with falsy class names. + function addClass(element, className) { + className && _ElementUtilities.addClass(element, className); + } + function removeClass(element, className) { + className && _ElementUtilities.removeClass(element, className); + } + function rectToThickness(rect, dimension) { + return (dimension === Dimension.width) ? { + content: rect.contentWidth, + total: rect.totalWidth + } : { + content: rect.contentHeight, + total: rect.totalHeight + }; + } + /// + /// + /// Displays a SplitView which renders a collapsable pane next to arbitrary HTML content. + /// + /// + /// + /// + /// ]]> + /// Raised just before opening the pane. Call preventDefault on this event to stop the pane from opening. + /// Raised immediately after the pane is fully opened. + /// Raised just before closing the pane. Call preventDefault on this event to stop the pane from closing. + /// Raised immediately after the pane is fully closed. + /// The entire SplitView control. + /// The element which hosts the SplitView's pane. + /// The element which hosts the SplitView's content. + /// + /// + var SplitView = (function () { + function SplitView(element, options) { + /// + /// + /// Creates a new SplitView control. + /// + /// + /// The DOM element that hosts the SplitView control. + /// + /// + /// An object that contains one or more property/value pairs to apply to the new control. + /// Each property of the options object corresponds to one of the control's properties or events. + /// Event names must begin with "on". For example, to provide a handler for the beforeclose event, + /// add a property named "onbeforeclose" to the options object and set its value to the event handler. + /// + /// + /// The new SplitView. + /// + /// + var _this = this; + if (options === void 0) { options = {}; } + // State private to _updateDomImpl. No other method should make use of it. + // + // Nothing has been rendered yet so these are all initialized to undefined. Because + // they are undefined, the first time _updateDomImpl is called, they will all be + // rendered. + this._updateDomImpl_rendered = { + paneIsFirst: undefined, + isOpenedMode: undefined, + closedDisplayMode: undefined, + openedDisplayMode: undefined, + panePlacement: undefined, + panePlaceholderWidth: undefined, + panePlaceholderHeight: undefined, + isOverlayShown: undefined + }; + // Check to make sure we weren't duplicated + if (element && element["winControl"]) { + throw new _ErrorFromName("WinJS.UI.SplitView.DuplicateConstruction", Strings.duplicateConstruction); + } + this._initializeDom(element || _Global.document.createElement("div")); + this._machine = new _OpenCloseMachine.OpenCloseMachine({ + eventElement: this._dom.root, + onOpen: function () { + _this._cachedHiddenPaneThickness = null; + var hiddenPaneThickness = _this._getHiddenPaneThickness(); + _this._isOpenedMode = true; + _this._updateDomImpl(); + return _this._playShowAnimation(hiddenPaneThickness); + }, + onClose: function () { + return _this._playHideAnimation(_this._getHiddenPaneThickness()).then(function () { + _this._isOpenedMode = false; + _this._updateDomImpl(); + }); + }, + onUpdateDom: function () { + _this._updateDomImpl(); + }, + onUpdateDomWithIsOpened: function (isOpened) { + _this._isOpenedMode = isOpened; + _this._updateDomImpl(); + } + }); + // Initialize private state. + this._disposed = false; + this._dismissable = new _LightDismissService.LightDismissableElement({ + element: this._dom.paneWrapper, + tabIndex: -1, + onLightDismiss: function () { + _this.closePane(); + }, + onTakeFocus: function (useSetActive) { + _this._dismissable.restoreFocus() || _ElementUtilities._tryFocusOnAnyElement(_this._dom.pane, useSetActive); + } + }); + this._cachedHiddenPaneThickness = null; + // Initialize public properties. + this.paneOpened = false; + this.closedDisplayMode = ClosedDisplayMode.inline; + this.openedDisplayMode = OpenedDisplayMode.overlay; + this.panePlacement = PanePlacement.left; + _Control.setOptions(this, options); + // Exit the Init state. + _ElementUtilities._inDom(this._dom.root).then(function () { + _this._rtl = _Global.getComputedStyle(_this._dom.root).direction === 'rtl'; + _this._machine.exitInit(); + }); + } + Object.defineProperty(SplitView.prototype, "element", { + /// + get: function () { + return this._dom.root; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SplitView.prototype, "paneElement", { + /// + get: function () { + return this._dom.pane; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SplitView.prototype, "contentElement", { + /// + get: function () { + return this._dom.content; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SplitView.prototype, "closedDisplayMode", { + /// + /// Gets or sets the display mode of the SplitView's pane when it is hidden. + /// + get: function () { + return this._closedDisplayMode; + }, + set: function (value) { + if (ClosedDisplayMode[value] && this._closedDisplayMode !== value) { + this._closedDisplayMode = value; + this._cachedHiddenPaneThickness = null; + this._machine.updateDom(); + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SplitView.prototype, "openedDisplayMode", { + /// + /// Gets or sets the display mode of the SplitView's pane when it is open. + /// + get: function () { + return this._openedDisplayMode; + }, + set: function (value) { + if (OpenedDisplayMode[value] && this._openedDisplayMode !== value) { + this._openedDisplayMode = value; + this._cachedHiddenPaneThickness = null; + this._machine.updateDom(); + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SplitView.prototype, "panePlacement", { + /// + /// Gets or sets the placement of the SplitView's pane. + /// + get: function () { + return this._panePlacement; + }, + set: function (value) { + if (PanePlacement[value] && this._panePlacement !== value) { + this._panePlacement = value; + this._cachedHiddenPaneThickness = null; + this._machine.updateDom(); + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SplitView.prototype, "paneOpened", { + /// + get: function () { + return this._machine.opened; + }, + set: function (value) { + this._machine.opened = value; + }, + enumerable: true, + configurable: true + }); + SplitView.prototype.dispose = function () { + /// + /// + /// Disposes this control. + /// + /// + if (this._disposed) { + return; + } + this._disposed = true; + this._machine.dispose(); + _LightDismissService.hidden(this._dismissable); + _Dispose._disposeElement(this._dom.pane); + _Dispose._disposeElement(this._dom.content); + }; + SplitView.prototype.openPane = function () { + /// + /// + /// Opens the SplitView's pane. + /// + /// + this._machine.open(); + }; + SplitView.prototype.closePane = function () { + /// + /// + /// Closes the SplitView's pane. + /// + /// + this._machine.close(); + }; + SplitView.prototype._initializeDom = function (root) { + // The first child is the pane + var paneEl = root.firstElementChild || _Global.document.createElement("div"); + _ElementUtilities.addClass(paneEl, ClassNames.pane); + if (!paneEl.hasAttribute("tabIndex")) { + paneEl.tabIndex = -1; + } + // All other children are members of the content + var contentEl = _Global.document.createElement("div"); + _ElementUtilities.addClass(contentEl, ClassNames.content); + var child = paneEl.nextSibling; + while (child) { + var sibling = child.nextSibling; + contentEl.appendChild(child); + child = sibling; + } + // paneWrapper's purpose is to clip the pane during the pane resize animation + var paneWrapperEl = _Global.document.createElement("div"); + paneWrapperEl.className = ClassNames._paneWrapper; + paneWrapperEl.appendChild(paneEl); + var panePlaceholderEl = _Global.document.createElement("div"); + panePlaceholderEl.className = ClassNames._panePlaceholder; + // contentWrapper is an extra element we need to allow heights to be specified as percentages (e.g. height: 100%) + // for elements within the content area. It works around this Chrome bug: + // Issue 428049: 100% height doesn't work on child of a definite-flex-basis flex item (in vertical flex container) + // https://code.google.com/p/chromium/issues/detail?id=428049 + // The workaround is that putting a position: absolute element (_dom.content) within the flex item (_dom.contentWrapper) + // allows percentage heights to work within the absolutely positioned element (_dom.content). + var contentWrapperEl = _Global.document.createElement("div"); + contentWrapperEl.className = ClassNames._contentWrapper; + contentWrapperEl.appendChild(contentEl); + root["winControl"] = this; + _ElementUtilities.addClass(root, ClassNames.splitView); + _ElementUtilities.addClass(root, "win-disposable"); + this._dom = { + root: root, + pane: paneEl, + paneWrapper: paneWrapperEl, + panePlaceholder: panePlaceholderEl, + content: contentEl, + contentWrapper: contentWrapperEl + }; + }; + SplitView.prototype._measureElement = function (element) { + var style = getComputedStyle(element); + var position = _ElementUtilities._getPositionRelativeTo(element, this._dom.root); + var marginLeft = parseInt(style.marginLeft, 10); + var marginTop = parseInt(style.marginTop, 10); + return { + left: position.left - marginLeft, + top: position.top - marginTop, + contentWidth: _ElementUtilities.getContentWidth(element), + contentHeight: _ElementUtilities.getContentHeight(element), + totalWidth: _ElementUtilities.getTotalWidth(element), + totalHeight: _ElementUtilities.getTotalHeight(element) + }; + }; + SplitView.prototype._setContentRect = function (contentRect) { + var contentWrapperStyle = this._dom.contentWrapper.style; + contentWrapperStyle.left = contentRect.left + "px"; + contentWrapperStyle.top = contentRect.top + "px"; + contentWrapperStyle.height = contentRect.contentHeight + "px"; + contentWrapperStyle.width = contentRect.contentWidth + "px"; + }; + // Overridden by tests. + SplitView.prototype._prepareAnimation = function (paneRect, contentRect) { + var paneWrapperStyle = this._dom.paneWrapper.style; + paneWrapperStyle.position = "absolute"; + paneWrapperStyle.left = paneRect.left + "px"; + paneWrapperStyle.top = paneRect.top + "px"; + paneWrapperStyle.height = paneRect.totalHeight + "px"; + paneWrapperStyle.width = paneRect.totalWidth + "px"; + var contentWrapperStyle = this._dom.contentWrapper.style; + contentWrapperStyle.position = "absolute"; + this._setContentRect(contentRect); + }; + // Overridden by tests. + SplitView.prototype._clearAnimation = function () { + var paneWrapperStyle = this._dom.paneWrapper.style; + paneWrapperStyle.position = ""; + paneWrapperStyle.left = ""; + paneWrapperStyle.top = ""; + paneWrapperStyle.height = ""; + paneWrapperStyle.width = ""; + paneWrapperStyle[transformNames.scriptName] = ""; + var contentWrapperStyle = this._dom.contentWrapper.style; + contentWrapperStyle.position = ""; + contentWrapperStyle.left = ""; + contentWrapperStyle.top = ""; + contentWrapperStyle.height = ""; + contentWrapperStyle.width = ""; + contentWrapperStyle[transformNames.scriptName] = ""; + var paneStyle = this._dom.pane.style; + paneStyle.height = ""; + paneStyle.width = ""; + paneStyle[transformNames.scriptName] = ""; + }; + SplitView.prototype._getHiddenContentRect = function (shownContentRect, hiddenPaneThickness, shownPaneThickness) { + if (this.openedDisplayMode === OpenedDisplayMode.overlay) { + return shownContentRect; + } + else { + var placementRight = this._rtl ? PanePlacement.left : PanePlacement.right; + var multiplier = this.panePlacement === placementRight || this.panePlacement === PanePlacement.bottom ? 0 : 1; + var paneDiff = { + content: shownPaneThickness.content - hiddenPaneThickness.content, + total: shownPaneThickness.total - hiddenPaneThickness.total + }; + return this._horizontal ? { + left: shownContentRect.left - multiplier * paneDiff.total, + top: shownContentRect.top, + contentWidth: shownContentRect.contentWidth + paneDiff.content, + contentHeight: shownContentRect.contentHeight, + totalWidth: shownContentRect.totalWidth + paneDiff.total, + totalHeight: shownContentRect.totalHeight + } : { + left: shownContentRect.left, + top: shownContentRect.top - multiplier * paneDiff.total, + contentWidth: shownContentRect.contentWidth, + contentHeight: shownContentRect.contentHeight + paneDiff.content, + totalWidth: shownContentRect.totalWidth, + totalHeight: shownContentRect.totalHeight + paneDiff.total + }; + } + }; + Object.defineProperty(SplitView.prototype, "_horizontal", { + get: function () { + return this.panePlacement === PanePlacement.left || this.panePlacement === PanePlacement.right; + }, + enumerable: true, + configurable: true + }); + SplitView.prototype._getHiddenPaneThickness = function () { + if (this._cachedHiddenPaneThickness === null) { + if (this._closedDisplayMode === ClosedDisplayMode.none) { + this._cachedHiddenPaneThickness = { content: 0, total: 0 }; + } + else { + if (this._isOpenedMode) { + _ElementUtilities.removeClass(this._dom.root, ClassNames.paneOpened); + _ElementUtilities.addClass(this._dom.root, ClassNames.paneClosed); + } + var size = this._measureElement(this._dom.pane); + this._cachedHiddenPaneThickness = rectToThickness(size, this._horizontal ? Dimension.width : Dimension.height); + if (this._isOpenedMode) { + _ElementUtilities.removeClass(this._dom.root, ClassNames.paneClosed); + _ElementUtilities.addClass(this._dom.root, ClassNames.paneOpened); + } + } + } + return this._cachedHiddenPaneThickness; + }; + // Should be called while SplitView is rendered in its opened mode + // Overridden by tests. + SplitView.prototype._playShowAnimation = function (hiddenPaneThickness) { + var _this = this; + var dim = this._horizontal ? Dimension.width : Dimension.height; + var shownPaneRect = this._measureElement(this._dom.pane); + var shownContentRect = this._measureElement(this._dom.content); + var shownPaneThickness = rectToThickness(shownPaneRect, dim); + var hiddenContentRect = this._getHiddenContentRect(shownContentRect, hiddenPaneThickness, shownPaneThickness); + this._prepareAnimation(shownPaneRect, hiddenContentRect); + var playPaneAnimation = function () { + var placementRight = _this._rtl ? PanePlacement.left : PanePlacement.right; + // What percentage of the size change should be skipped? (e.g. let's do the first + // 30% of the size change instantly and then animate the other 70%) + var animationOffsetFactor = 0.3; + var from = hiddenPaneThickness.total + animationOffsetFactor * (shownPaneThickness.total - hiddenPaneThickness.total); + return Animations._resizeTransition(_this._dom.paneWrapper, _this._dom.pane, { + from: from, + to: shownPaneThickness.total, + actualSize: shownPaneThickness.total, + dimension: dim, + anchorTrailingEdge: _this.panePlacement === placementRight || _this.panePlacement === PanePlacement.bottom + }); + }; + var playShowAnimation = function () { + if (_this.openedDisplayMode === OpenedDisplayMode.inline) { + _this._setContentRect(shownContentRect); + } + return playPaneAnimation(); + }; + return playShowAnimation().then(function () { + _this._clearAnimation(); + }); + }; + // Should be called while SplitView is rendered in its opened mode + // Overridden by tests. + SplitView.prototype._playHideAnimation = function (hiddenPaneThickness) { + var _this = this; + var dim = this._horizontal ? Dimension.width : Dimension.height; + var shownPaneRect = this._measureElement(this._dom.pane); + var shownContentRect = this._measureElement(this._dom.content); + var shownPaneThickness = rectToThickness(shownPaneRect, dim); + var hiddenContentRect = this._getHiddenContentRect(shownContentRect, hiddenPaneThickness, shownPaneThickness); + this._prepareAnimation(shownPaneRect, shownContentRect); + var playPaneAnimation = function () { + var placementRight = _this._rtl ? PanePlacement.left : PanePlacement.right; + // What percentage of the size change should be skipped? (e.g. let's do the first + // 30% of the size change instantly and then animate the other 70%) + var animationOffsetFactor = 0.3; + var from = shownPaneThickness.total - animationOffsetFactor * (shownPaneThickness.total - hiddenPaneThickness.total); + return Animations._resizeTransition(_this._dom.paneWrapper, _this._dom.pane, { + from: from, + to: hiddenPaneThickness.total, + actualSize: shownPaneThickness.total, + dimension: dim, + anchorTrailingEdge: _this.panePlacement === placementRight || _this.panePlacement === PanePlacement.bottom + }); + }; + var playHideAnimation = function () { + if (_this.openedDisplayMode === OpenedDisplayMode.inline) { + _this._setContentRect(hiddenContentRect); + } + return playPaneAnimation(); + }; + return playHideAnimation().then(function () { + _this._clearAnimation(); + }); + }; + SplitView.prototype._updateDomImpl = function () { + var rendered = this._updateDomImpl_rendered; + var paneShouldBeFirst = this.panePlacement === PanePlacement.left || this.panePlacement === PanePlacement.top; + if (paneShouldBeFirst !== rendered.paneIsFirst) { + // TODO: restore focus + if (paneShouldBeFirst) { + this._dom.root.appendChild(this._dom.panePlaceholder); + this._dom.root.appendChild(this._dom.paneWrapper); + this._dom.root.appendChild(this._dom.contentWrapper); + } + else { + this._dom.root.appendChild(this._dom.contentWrapper); + this._dom.root.appendChild(this._dom.paneWrapper); + this._dom.root.appendChild(this._dom.panePlaceholder); + } + } + rendered.paneIsFirst = paneShouldBeFirst; + if (rendered.isOpenedMode !== this._isOpenedMode) { + if (this._isOpenedMode) { + _ElementUtilities.removeClass(this._dom.root, ClassNames.paneClosed); + _ElementUtilities.addClass(this._dom.root, ClassNames.paneOpened); + } + else { + _ElementUtilities.removeClass(this._dom.root, ClassNames.paneOpened); + _ElementUtilities.addClass(this._dom.root, ClassNames.paneClosed); + } + } + rendered.isOpenedMode = this._isOpenedMode; + if (rendered.panePlacement !== this.panePlacement) { + removeClass(this._dom.root, panePlacementClassMap[rendered.panePlacement]); + addClass(this._dom.root, panePlacementClassMap[this.panePlacement]); + rendered.panePlacement = this.panePlacement; + } + if (rendered.closedDisplayMode !== this.closedDisplayMode) { + removeClass(this._dom.root, closedDisplayModeClassMap[rendered.closedDisplayMode]); + addClass(this._dom.root, closedDisplayModeClassMap[this.closedDisplayMode]); + rendered.closedDisplayMode = this.closedDisplayMode; + } + if (rendered.openedDisplayMode !== this.openedDisplayMode) { + removeClass(this._dom.root, openedDisplayModeClassMap[rendered.openedDisplayMode]); + addClass(this._dom.root, openedDisplayModeClassMap[this.openedDisplayMode]); + rendered.openedDisplayMode = this.openedDisplayMode; + } + var isOverlayShown = this._isOpenedMode && this.openedDisplayMode === OpenedDisplayMode.overlay; + // panePlaceholder's purpose is to take up the amount of space occupied by the + // hidden pane while the pane is shown in overlay mode. Without this, the content + // would shift as the pane shows and hides in overlay mode. + var width, height; + if (isOverlayShown) { + var hiddenPaneThickness = this._getHiddenPaneThickness(); + if (this._horizontal) { + width = hiddenPaneThickness.total + "px"; + height = ""; + } + else { + width = ""; + height = hiddenPaneThickness.total + "px"; + } + } + else { + width = ""; + height = ""; + } + if (rendered.panePlaceholderWidth !== width || rendered.panePlaceholderHeight !== height) { + var style = this._dom.panePlaceholder.style; + style.width = width; + style.height = height; + rendered.panePlaceholderWidth = width; + rendered.panePlaceholderHeight = height; + } + if (rendered.isOverlayShown !== isOverlayShown) { + if (isOverlayShown) { + _LightDismissService.shown(this._dismissable); + } + else { + _LightDismissService.hidden(this._dismissable); + } + rendered.isOverlayShown = isOverlayShown; + } + }; + /// + /// Display options for a SplitView's pane when it is closed. + /// + SplitView.ClosedDisplayMode = ClosedDisplayMode; + /// + /// Display options for a SplitView's pane when it is open. + /// + SplitView.OpenedDisplayMode = OpenedDisplayMode; + /// + /// Placement options for a SplitView's pane. + /// + SplitView.PanePlacement = PanePlacement; + SplitView.supportedForProcessing = true; + SplitView._ClassNames = ClassNames; + return SplitView; + })(); + exports.SplitView = SplitView; + _Base.Class.mix(SplitView, _Events.createEventProperties(EventNames.beforeOpen, EventNames.afterOpen, EventNames.beforeClose, EventNames.afterClose)); + _Base.Class.mix(SplitView, _Control.DOMEventMixin); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// +define('WinJS/Controls/SplitView',["require", "exports", '../Core/_Base'], function (require, exports, _Base) { + var module = null; + _Base.Namespace.define("WinJS.UI", { + SplitView: { + get: function () { + if (!module) { + require(["./SplitView/_SplitView"], function (m) { + module = m; + }); + } + return module.SplitView; + } + } + }); +}); + + +define('require-style!less/styles-splitviewpanetoggle',[],function(){}); + +define('require-style!less/colors-splitviewpanetoggle',[],function(){}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// +define('WinJS/Controls/SplitViewPaneToggle/_SplitViewPaneToggle',["require", "exports", '../../Core/_Base', '../../Utilities/_Control', '../../Utilities/_ElementUtilities', '../../Core/_ErrorFromName', '../../Core/_Events', '../../Core/_Global', '../../Utilities/_KeyboardBehavior', '../../Utilities/_Hoverable'], function (require, exports, _Base, _Control, _ElementUtilities, _ErrorFromName, _Events, _Global, _KeyboardBehavior, _Hoverable) { + _Hoverable.isHoverable; // Force dependency on the hoverable module + require(["require-style!less/styles-splitviewpanetoggle"]); + require(["require-style!less/colors-splitviewpanetoggle"]); + "use strict"; + // This control has 2 modes depending on whether or not the app has provided a SplitView: + // - SplitView not provided + // SplitViewPaneToggle provides button visuals and fires the invoked event. The app + // intends to do everything else: + // - Handle the invoked event + // - Handle the SplitView opening and closing + // - Handle aria-expanded being mutated by UIA (i.e. screen readers) + // - Keep the aria-controls attribute, aria-expanded attribute, and SplitView in sync + // - SplitView is provided via splitView property + // SplitViewPaneToggle keeps the SplitView, the aria-controls attribute, and the + // aria-expands attribute in sync. In this use case, apps typically won't listen + // to the invoked event (but it's still fired). + var ClassNames = { + splitViewPaneToggle: "win-splitviewpanetoggle" + }; + var EventNames = { + // Fires when the user invokes the button with mouse/keyboard/touch. Does not + // fire if the SplitViewPaneToggle's state changes due to UIA (i.e. aria-expanded + // being set) or due to the SplitView pane opening/closing. + invoked: "invoked" + }; + var Strings = { + get duplicateConstruction() { + return "Invalid argument: Controls may only be instantiated one time for each DOM element"; + }, + get badButtonElement() { + return "Invalid argument: The SplitViewPaneToggle's element must be a button element"; + } + }; + // The splitViewElement may not have a winControl associated with it yet in the case + // that the SplitViewPaneToggle was constructed before the SplitView. This may happen + // when WinJS.UI.processAll is used to construct the controls because the order of construction + // depends on the order in which the SplitView and SplitViewPaneToggle appear in the DOM. + function getSplitViewControl(splitViewElement) { + return (splitViewElement && splitViewElement["winControl"]); + } + function getPaneOpened(splitViewElement) { + var splitViewControl = getSplitViewControl(splitViewElement); + return splitViewControl ? splitViewControl.paneOpened : false; + } + /// + /// + /// Displays a button which is used for opening and closing a SplitView's pane. + /// + /// + /// + /// + /// ]]> + /// The SplitViewPaneToggle control itself. + /// + /// + var SplitViewPaneToggle = (function () { + function SplitViewPaneToggle(element, options) { + /// + /// + /// Creates a new SplitViewPaneToggle control. + /// + /// + /// The DOM element that hosts the SplitViewPaneToggle control. + /// + /// + /// An object that contains one or more property/value pairs to apply to the new control. + /// Each property of the options object corresponds to one of the control's properties or events. + /// Event names must begin with "on". For example, to provide a handler for the invoked event, + /// add a property named "oninvoked" to the options object and set its value to the event handler. + /// + /// + /// The new SplitViewPaneToggle. + /// + /// + if (options === void 0) { options = {}; } + // State private to _updateDom. No other method should make use of it. + // + // Nothing has been rendered yet so these are all initialized to undefined. Because + // they are undefined, the first time _updateDom is called, they will all be + // rendered. + this._updateDom_rendered = { + splitView: undefined + }; + // Check to make sure we weren't duplicated + if (element && element["winControl"]) { + throw new _ErrorFromName("WinJS.UI.SplitViewPaneToggle.DuplicateConstruction", Strings.duplicateConstruction); + } + this._onPaneStateSettledBound = this._onPaneStateSettled.bind(this); + this._ariaExpandedMutationObserver = new _ElementUtilities._MutationObserver(this._onAriaExpandedPropertyChanged.bind(this)); + this._initializeDom(element || _Global.document.createElement("button")); + // Private state + this._disposed = false; + // Default values + this.splitView = null; + _Control.setOptions(this, options); + this._initialized = true; + this._updateDom(); + } + Object.defineProperty(SplitViewPaneToggle.prototype, "element", { + /// + get: function () { + return this._dom.root; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SplitViewPaneToggle.prototype, "splitView", { + /// + get: function () { + return this._splitView; + }, + set: function (splitView) { + this._splitView = splitView; + if (splitView) { + this._opened = getPaneOpened(splitView); + } + this._updateDom(); + }, + enumerable: true, + configurable: true + }); + SplitViewPaneToggle.prototype.dispose = function () { + /// + /// + /// Disposes this control. + /// + /// + if (this._disposed) { + return; + } + this._disposed = true; + this._splitView && this._removeListeners(this._splitView); + }; + SplitViewPaneToggle.prototype._initializeDom = function (root) { + if (root.tagName !== "BUTTON") { + throw new _ErrorFromName("WinJS.UI.SplitViewPaneToggle.BadButtonElement", Strings.badButtonElement); + } + root["winControl"] = this; + _ElementUtilities.addClass(root, ClassNames.splitViewPaneToggle); + _ElementUtilities.addClass(root, "win-disposable"); + if (!root.hasAttribute("type")) { + root.type = "button"; + } + new _KeyboardBehavior._WinKeyboard(root); + root.addEventListener("click", this._onClick.bind(this)); + this._dom = { + root: root + }; + }; + SplitViewPaneToggle.prototype._updateDom = function () { + if (!this._initialized || this._disposed) { + return; + } + var rendered = this._updateDom_rendered; + if (this._splitView !== rendered.splitView) { + if (rendered.splitView) { + this._dom.root.removeAttribute("aria-controls"); + this._removeListeners(rendered.splitView); + } + if (this._splitView) { + _ElementUtilities._ensureId(this._splitView); + this._dom.root.setAttribute("aria-controls", this._splitView.id); + this._addListeners(this._splitView); + } + rendered.splitView = this._splitView; + } + // When no SplitView is provided, it's up to the app to manage aria-expanded. + if (this._splitView) { + // Always update aria-expanded and don't cache its most recently rendered value + // in _updateDom_rendered. The reason is that we're not the only ones that update + // aria-expanded. aria-expanded may be changed thru UIA APIs. Consequently, if we + // cached the last value we set in _updateDom_rendered, it may not reflect the current + // value in the DOM. + var expanded = this._opened ? "true" : "false"; + _ElementUtilities._setAttribute(this._dom.root, "aria-expanded", expanded); + // The splitView element may not have a winControl associated with it yet in the case + // that the SplitViewPaneToggle was constructed before the SplitView. This may happen + // when WinJS.UI.processAll is used to construct the controls because the order of construction + // depends on the order in which the SplitView and SplitViewPaneToggle appear in the DOM. + var splitViewControl = getSplitViewControl(this._splitView); + if (splitViewControl) { + splitViewControl.paneOpened = this._opened; + } + } + }; + SplitViewPaneToggle.prototype._addListeners = function (splitViewElement) { + splitViewElement.addEventListener("_openCloseStateSettled", this._onPaneStateSettledBound); + this._ariaExpandedMutationObserver.observe(this._dom.root, { + attributes: true, + attributeFilter: ["aria-expanded"] + }); + }; + SplitViewPaneToggle.prototype._removeListeners = function (splitViewElement) { + splitViewElement.removeEventListener("_openCloseStateSettled", this._onPaneStateSettledBound); + this._ariaExpandedMutationObserver.disconnect(); + }; + SplitViewPaneToggle.prototype._fireEvent = function (eventName) { + var eventObject = _Global.document.createEvent("CustomEvent"); + eventObject.initCustomEvent(eventName, true, false, null); + return this._dom.root.dispatchEvent(eventObject); + }; + // Inputs that change the SplitViewPaneToggle's state + // + SplitViewPaneToggle.prototype._onPaneStateSettled = function (eventObject) { + if (eventObject.target === this._splitView) { + this._opened = getPaneOpened(this._splitView); + this._updateDom(); + } + }; + // Called by tests. + SplitViewPaneToggle.prototype._onAriaExpandedPropertyChanged = function (mutations) { + var ariaExpanded = this._dom.root.getAttribute("aria-expanded") === "true"; + this._opened = ariaExpanded; + this._updateDom(); + }; + SplitViewPaneToggle.prototype._onClick = function (eventObject) { + this._invoked(); + }; + // Called by tests. + SplitViewPaneToggle.prototype._invoked = function () { + if (this._disposed) { + return; + } + if (this._splitView) { + this._opened = !this._opened; + this._updateDom(); + } + this._fireEvent(EventNames.invoked); + }; + SplitViewPaneToggle._ClassNames = ClassNames; + SplitViewPaneToggle.supportedForProcessing = true; + return SplitViewPaneToggle; + })(); + exports.SplitViewPaneToggle = SplitViewPaneToggle; + _Base.Class.mix(SplitViewPaneToggle, _Events.createEventProperties(EventNames.invoked)); + _Base.Class.mix(SplitViewPaneToggle, _Control.DOMEventMixin); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// +define('WinJS/Controls/SplitViewPaneToggle',["require", "exports", '../Core/_Base'], function (require, exports, _Base) { + var module = null; + _Base.Namespace.define("WinJS.UI", { + SplitViewPaneToggle: { + get: function () { + if (!module) { + require(["./SplitViewPaneToggle/_SplitViewPaneToggle"], function (m) { + module = m; + }); + } + return module.SplitViewPaneToggle; + } + } + }); +}); + +define('WinJS/Controls/AppBar/_Constants',["require", "exports", "../CommandingSurface/_Constants"], function (require, exports, _CommandingSurfaceConstants) { + // appbar class names + exports.ClassNames = { + controlCssClass: "win-appbar", + disposableCssClass: "win-disposable", + actionAreaCssClass: "win-appbar-actionarea", + overflowButtonCssClass: "win-appbar-overflowbutton", + spacerCssClass: "win-appbar-spacer", + ellipsisCssClass: "win-appbar-ellipsis", + overflowAreaCssClass: "win-appbar-overflowarea", + contentFlyoutCssClass: "win-appbar-contentflyout", + emptyappbarCssClass: "win-appbar-empty", + menuCssClass: "win-menu", + menuContainsToggleCommandClass: "win-menu-containstogglecommand", + openedClass: "win-appbar-opened", + closedClass: "win-appbar-closed", + noneClass: "win-appbar-closeddisplaynone", + minimalClass: "win-appbar-closeddisplayminimal", + compactClass: "win-appbar-closeddisplaycompact", + fullClass: "win-appbar-closeddisplayfull", + placementTopClass: "win-appbar-top", + placementBottomClass: "win-appbar-bottom", + }; + exports.EventNames = { + // AppBar + beforeOpen: "beforeopen", + afterOpen: "afteropen", + beforeClose: "beforeclose", + afterClose: "afterclose", + // AppBarCommand + commandPropertyMutated: "_commandpropertymutated", + }; + exports.controlMinWidth = _CommandingSurfaceConstants.controlMinWidth; + exports.defaultClosedDisplayMode = "compact"; + exports.defaultOpened = false; + exports.defaultPlacement = "bottom"; + // Constants for commands + exports.typeSeparator = "separator"; + exports.typeContent = "content"; + exports.typeButton = "button"; + exports.typeToggle = "toggle"; + exports.typeFlyout = "flyout"; + exports.commandSelector = ".win-command"; + exports.primaryCommandSection = "primary"; + exports.secondaryCommandSection = "secondary"; +}); + + +define('require-style!less/styles-appbar',[],function(){}); +define('WinJS/Controls/AppBar/_AppBar',["require", "exports", "../../Core/_Base", "../AppBar/_Constants", "../CommandingSurface", "../../Utilities/_Control", "../../Utilities/_Dispose", "../../Utilities/_ElementUtilities", "../../Core/_ErrorFromName", '../../Core/_Events', "../../Core/_Global", '../../Utilities/_KeyboardInfo', '../../_LightDismissService', '../../Promise', "../../Core/_Resources", '../../Utilities/_OpenCloseMachine', "../../Core/_WriteProfilerMark"], function (require, exports, _Base, _Constants, _CommandingSurface, _Control, _Dispose, _ElementUtilities, _ErrorFromName, _Events, _Global, _KeyboardInfo, _LightDismissService, Promise, _Resources, _OpenCloseMachine, _WriteProfilerMark) { + require(["require-style!less/styles-appbar"]); + "use strict"; + var keyboardInfo = _KeyboardInfo._KeyboardInfo; + var strings = { + get ariaLabel() { + return _Resources._getWinJSString("ui/appBarAriaLabel").value; + }, + get overflowButtonAriaLabel() { + return _Resources._getWinJSString("ui/appBarOverflowButtonAriaLabel").value; + }, + get mustContainCommands() { + return "The AppBar can only contain WinJS.UI.Command or WinJS.UI.AppBarCommand controls"; + }, + get duplicateConstruction() { + return "Invalid argument: Controls may only be instantiated one time for each DOM element"; + } + }; + var ClosedDisplayMode = { + /// + /// When the AppBar is closed, it is not visible and doesn't take up any space. + /// + none: "none", + /// + /// When the AppBar is closed, its height is reduced to the minimal height required to display only its overflowbutton. All other content in the AppBar is not displayed. + /// + minimal: "minimal", + /// + /// When the AppBar is closed, its height is reduced such that button commands are still visible, but their labels are hidden. + /// + compact: "compact", + /// + /// When the AppBar is closed, its height is always sized to content. + /// + full: "full", + }; + var closedDisplayModeClassMap = {}; + closedDisplayModeClassMap[ClosedDisplayMode.none] = _Constants.ClassNames.noneClass; + closedDisplayModeClassMap[ClosedDisplayMode.minimal] = _Constants.ClassNames.minimalClass; + closedDisplayModeClassMap[ClosedDisplayMode.compact] = _Constants.ClassNames.compactClass; + closedDisplayModeClassMap[ClosedDisplayMode.full] = _Constants.ClassNames.fullClass; + var Placement = { + /// + /// The AppBar appears at the top of the main view + /// + top: "top", + /// + /// The AppBar appears at the bottom of the main view + /// + bottom: "bottom", + }; + var placementClassMap = {}; + placementClassMap[Placement.top] = _Constants.ClassNames.placementTopClass; + placementClassMap[Placement.bottom] = _Constants.ClassNames.placementBottomClass; + // Versions of add/removeClass that are no ops when called with falsy class names. + function addClass(element, className) { + className && _ElementUtilities.addClass(element, className); + } + function removeClass(element, className) { + className && _ElementUtilities.removeClass(element, className); + } + /// + /// + /// Represents an appbar for displaying commands. + /// + /// + /// + /// + /// + /// + /// ]]> + /// The entire AppBar control. + /// The appbar overflow button. + /// The container for appbar commands that overflow. + /// + /// + var AppBar = (function () { + function AppBar(element, options) { + /// + /// + /// Creates a new AppBar control. + /// + /// + /// The DOM element that will host the control. + /// + /// + /// The set of properties and values to apply to the new AppBar control. + /// + /// + /// The new AppBar control. + /// + /// + var _this = this; + if (options === void 0) { options = {}; } + // State private to the _updateDomImpl family of method. No other methods should make use of it. + // + // Nothing has been rendered yet so these are all initialized to undefined. Because + // they are undefined, the first time _updateDomImpl is called, they will all be + // rendered. + this._updateDomImpl_renderedState = { + isOpenedMode: undefined, + placement: undefined, + closedDisplayMode: undefined, + adjustedOffsets: { top: undefined, bottom: undefined }, + }; + this._writeProfilerMark("constructor,StartTM"); + // Check to make sure we weren't duplicated + if (element && element["winControl"]) { + throw new _ErrorFromName("WinJS.UI.AppBar.DuplicateConstruction", strings.duplicateConstruction); + } + this._initializeDom(element || _Global.document.createElement("div")); + var stateMachine = new _OpenCloseMachine.OpenCloseMachine({ + eventElement: this.element, + onOpen: function () { + var openAnimation = _this._commandingSurface.createOpenAnimation(_this._getClosedHeight()); + // We're temporarily setting the AppBar's style from position=-ms-device-fixed to fixed to work around an animations bug in IE, + // where two AppBars will end up being rendered when animating instead of one. + // We need to recalculate our offsets relative to the top and bottom of the visible document because position fixed elements use layout viewport coordinates + // while position -ms-device-fixed use visual viewport coordinates.This difference in coordinate systems is especially pronounced if the IHM has caused the visual viewport to resize. + _this.element.style.position = "fixed"; + if (_this._placement === AppBar.Placement.top) { + _this.element.style.top = _KeyboardInfo._KeyboardInfo._layoutViewportCoords.visibleDocTop + "px"; + } + else { + _this.element.style.bottom = _KeyboardInfo._KeyboardInfo._layoutViewportCoords.visibleDocBottom + "px"; + } + _this._synchronousOpen(); + return openAnimation.execute().then(function () { + _this.element.style.position = ""; + _this.element.style.top = _this._adjustedOffsets.top; + _this.element.style.bottom = _this._adjustedOffsets.bottom; + }); + }, + onClose: function () { + var closeAnimation = _this._commandingSurface.createCloseAnimation(_this._getClosedHeight()); + // We're temporarily setting the AppBar's style from position=-ms-device-fixed to fixed to work around an animations bug in IE, + // where two AppBars will end up being rendered when animating instead of one. + // We need to recalculate our offsets relative to the top and bottom of the visible document because position fixed elements use layout viewport coordinates + // while position -ms-device-fixed use visual viewport coordinates.This difference in coordinate systems is especially pronounced if the IHM has caused the visual viewport to resize. + _this.element.style.position = "fixed"; + if (_this._placement === AppBar.Placement.top) { + _this.element.style.top = _KeyboardInfo._KeyboardInfo._layoutViewportCoords.visibleDocTop + "px"; + } + else { + _this.element.style.bottom = _KeyboardInfo._KeyboardInfo._layoutViewportCoords.visibleDocBottom + "px"; + } + return closeAnimation.execute().then(function () { + _this._synchronousClose(); + _this.element.style.position = ""; + _this.element.style.top = _this._adjustedOffsets.top; + _this.element.style.bottom = _this._adjustedOffsets.bottom; + }); + }, + onUpdateDom: function () { + _this._updateDomImpl(); + }, + onUpdateDomWithIsOpened: function (isOpened) { + _this._isOpenedMode = isOpened; + _this._updateDomImpl(); + } + }); + // Events + this._handleShowingKeyboardBound = this._handleShowingKeyboard.bind(this); + this._handleHidingKeyboardBound = this._handleHidingKeyboard.bind(this); + _ElementUtilities._inputPaneListener.addEventListener(this._dom.root, "showing", this._handleShowingKeyboardBound); + _ElementUtilities._inputPaneListener.addEventListener(this._dom.root, "hiding", this._handleHidingKeyboardBound); + // Initialize private state. + this._disposed = false; + this._cachedClosedHeight = null; + this._commandingSurface = new _CommandingSurface._CommandingSurface(this._dom.commandingSurfaceEl, { openCloseMachine: stateMachine }); + addClass(this._dom.commandingSurfaceEl.querySelector(".win-commandingsurface-actionarea"), _Constants.ClassNames.actionAreaCssClass); + addClass(this._dom.commandingSurfaceEl.querySelector(".win-commandingsurface-overflowarea"), _Constants.ClassNames.overflowAreaCssClass); + addClass(this._dom.commandingSurfaceEl.querySelector(".win-commandingsurface-overflowbutton"), _Constants.ClassNames.overflowButtonCssClass); + addClass(this._dom.commandingSurfaceEl.querySelector(".win-commandingsurface-ellipsis"), _Constants.ClassNames.ellipsisCssClass); + this._isOpenedMode = _Constants.defaultOpened; + this._dismissable = new _LightDismissService.LightDismissableElement({ + element: this._dom.root, + tabIndex: this._dom.root.hasAttribute("tabIndex") ? this._dom.root.tabIndex : -1, + onLightDismiss: function () { + _this.close(); + } + }); + // Initialize public properties. + this.closedDisplayMode = _Constants.defaultClosedDisplayMode; + this.placement = _Constants.defaultPlacement; + this.opened = this._isOpenedMode; + _Control.setOptions(this, options); + // Exit the Init state. + _ElementUtilities._inDom(this.element).then(function () { + return _this._commandingSurface.initialized; + }).then(function () { + stateMachine.exitInit(); + _this._writeProfilerMark("constructor,StopTM"); + }); + } + Object.defineProperty(AppBar.prototype, "element", { + /// + get: function () { + return this._dom.root; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(AppBar.prototype, "data", { + /// + /// Gets or sets the Binding List of WinJS.UI.Command for the AppBar. + /// + get: function () { + return this._commandingSurface.data; + }, + set: function (value) { + this._commandingSurface.data = value; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(AppBar.prototype, "closedDisplayMode", { + /// + /// Gets or sets the closedDisplayMode for the AppBar. Values are "none", "minimal", "compact" and "full". + /// + get: function () { + return this._commandingSurface.closedDisplayMode; + }, + set: function (value) { + if (ClosedDisplayMode[value]) { + this._commandingSurface.closedDisplayMode = value; + this._cachedClosedHeight = null; + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(AppBar.prototype, "placement", { + /// + get: function () { + return this._placement; + }, + set: function (value) { + if (Placement[value] && this._placement !== value) { + this._placement = value; + switch (value) { + case Placement.top: + this._commandingSurface.overflowDirection = "bottom"; + break; + case Placement.bottom: + this._commandingSurface.overflowDirection = "top"; + break; + } + this._adjustedOffsets = this._computeAdjustedOffsets(); + this._commandingSurface.deferredDomUpate(); + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(AppBar.prototype, "opened", { + /// + get: function () { + return this._commandingSurface.opened; + }, + set: function (value) { + this._commandingSurface.opened = value; + }, + enumerable: true, + configurable: true + }); + AppBar.prototype.open = function () { + /// + /// + /// Opens the AppBar + /// + /// + this._commandingSurface.open(); + }; + AppBar.prototype.close = function () { + /// + /// + /// Closes the AppBar + /// + /// + this._commandingSurface.close(); + }; + AppBar.prototype.dispose = function () { + /// + /// + /// Disposes this AppBar. + /// + /// + if (this._disposed) { + return; + } + this._disposed = true; + _LightDismissService.hidden(this._dismissable); + // Disposing the _commandingSurface will trigger dispose on its OpenCloseMachine + // and synchronously complete any animations that might have been running. + this._commandingSurface.dispose(); + _ElementUtilities._inputPaneListener.removeEventListener(this._dom.root, "showing", this._handleShowingKeyboardBound); + _ElementUtilities._inputPaneListener.removeEventListener(this._dom.root, "hiding", this._handleHidingKeyboardBound); + _Dispose.disposeSubTree(this.element); + }; + AppBar.prototype.forceLayout = function () { + /// + /// + /// Forces the AppBar to update its layout. Use this function when the window did not change size, but the container of the AppBar changed size. + /// + /// + this._commandingSurface.forceLayout(); + }; + AppBar.prototype.getCommandById = function (id) { + /// + /// + /// Retrieves the command with the specified ID from this AppBar. + /// If more than one command is found, this method returns the first command found. + /// + /// Id of the command to return. + /// + /// The command found, or null if no command is found. + /// + /// + return this._commandingSurface.getCommandById(id); + }; + AppBar.prototype.showOnlyCommands = function (commands) { + /// + /// + /// Show the specified commands, hiding all of the others in the AppBar. + /// + /// + /// An array of the commands to show. The array elements may be Command objects, or the string identifiers (IDs) of commands. + /// + /// + return this._commandingSurface.showOnlyCommands(commands); + }; + AppBar.prototype._writeProfilerMark = function (text) { + _WriteProfilerMark("WinJS.UI.AppBar:" + this._id + ":" + text); + }; + AppBar.prototype._initializeDom = function (root) { + this._writeProfilerMark("_intializeDom,info"); + // Attaching JS control to DOM element + root["winControl"] = this; + this._id = root.id || _ElementUtilities._uniqueID(root); + _ElementUtilities.addClass(root, _Constants.ClassNames.controlCssClass); + _ElementUtilities.addClass(root, _Constants.ClassNames.disposableCssClass); + // Make sure we have an ARIA role + var role = root.getAttribute("role"); + if (!role) { + root.setAttribute("role", "menubar"); + } + var label = root.getAttribute("aria-label"); + if (!label) { + root.setAttribute("aria-label", strings.ariaLabel); + } + // Create element for commandingSurface and reparent any declarative Commands. + // commandingSurface will parse child elements as AppBarCommands. + var commandingSurfaceEl = document.createElement("DIV"); + _ElementUtilities._reparentChildren(root, commandingSurfaceEl); + root.appendChild(commandingSurfaceEl); + this._dom = { + root: root, + commandingSurfaceEl: commandingSurfaceEl, + }; + }; + AppBar.prototype._handleShowingKeyboard = function (event) { + // If the IHM resized the window, we can rely on -ms-device-fixed positioning to remain visible. + // If the IHM does not resize the window we will need to adjust our offsets to avoid being occluded + // The IHM does not cause a window resize to happen right away, set a timeout to check if the viewport + // has been resized after enough time has passed for both the IHM animation, and scroll-into-view, to + // complete. + var _this = this; + // If focus is in the AppBar, tell the platform we will move ourselves. + if (this._dom.root.contains(_Global.document.activeElement)) { + var inputPaneEvent = event.detail.originalEvent; + inputPaneEvent.ensuredFocusedElementInView = true; + } + var duration = keyboardInfo._animationShowLength + keyboardInfo._scrollTimeout; + // Returns a promise for unit tests to verify the correct behavior after the timeout. + return Promise.timeout(duration).then(function () { + if (_this._shouldAdjustForShowingKeyboard() && !_this._disposed) { + _this._adjustedOffsets = _this._computeAdjustedOffsets(); + _this._commandingSurface.deferredDomUpate(); + } + }); + }; + AppBar.prototype._shouldAdjustForShowingKeyboard = function () { + // Overwriteable for unit tests + // Determines if an AppBar needs to adjust its position to move in response to a shown IHM, or if it can + // just ride the bottom of the visual viewport to remain visible. The latter requires that the IHM has + // caused the viewport to resize. + return keyboardInfo._visible && !keyboardInfo._isResized; + }; + AppBar.prototype._handleHidingKeyboard = function () { + // Make sure AppBar has the correct offsets since it could have been displaced by the IHM. + this._adjustedOffsets = this._computeAdjustedOffsets(); + this._commandingSurface.deferredDomUpate(); + }; + AppBar.prototype._computeAdjustedOffsets = function () { + // Position the AppBar element relative to the top or bottom edge of the visible + // document. + var offsets = { top: "", bottom: "" }; + if (this._placement === Placement.bottom) { + // If the IHM is open, the bottom of the visual viewport may or may not be occluded + offsets.bottom = keyboardInfo._visibleDocBottomOffset + "px"; + } + else if (this._placement === Placement.top) { + offsets.top = keyboardInfo._visibleDocTop + "px"; + } + return offsets; + }; + AppBar.prototype._synchronousOpen = function () { + this._isOpenedMode = true; + this._updateDomImpl(); + }; + AppBar.prototype._synchronousClose = function () { + this._isOpenedMode = false; + this._updateDomImpl(); + }; + AppBar.prototype._updateDomImpl = function () { + var rendered = this._updateDomImpl_renderedState; + if (rendered.isOpenedMode !== this._isOpenedMode) { + if (this._isOpenedMode) { + this._updateDomImpl_renderOpened(); + } + else { + this._updateDomImpl_renderClosed(); + } + rendered.isOpenedMode = this._isOpenedMode; + } + if (rendered.placement !== this.placement) { + removeClass(this._dom.root, placementClassMap[rendered.placement]); + addClass(this._dom.root, placementClassMap[this.placement]); + rendered.placement = this.placement; + } + if (rendered.closedDisplayMode !== this.closedDisplayMode) { + removeClass(this._dom.root, closedDisplayModeClassMap[rendered.closedDisplayMode]); + addClass(this._dom.root, closedDisplayModeClassMap[this.closedDisplayMode]); + rendered.closedDisplayMode = this.closedDisplayMode; + } + if (rendered.adjustedOffsets.top !== this._adjustedOffsets.top) { + this._dom.root.style.top = this._adjustedOffsets.top; + rendered.adjustedOffsets.top = this._adjustedOffsets.top; + } + if (rendered.adjustedOffsets.bottom !== this._adjustedOffsets.bottom) { + this._dom.root.style.bottom = this._adjustedOffsets.bottom; + rendered.adjustedOffsets.bottom = this._adjustedOffsets.bottom; + } + this._commandingSurface.updateDomImpl(); + }; + AppBar.prototype._getClosedHeight = function () { + if (this._cachedClosedHeight === null) { + var wasOpen = this._isOpenedMode; + if (this._isOpenedMode) { + this._synchronousClose(); + } + this._cachedClosedHeight = this._commandingSurface.getBoundingRects().commandingSurface.height; + if (wasOpen) { + this._synchronousOpen(); + } + } + return this._cachedClosedHeight; + }; + AppBar.prototype._updateDomImpl_renderOpened = function () { + addClass(this._dom.root, _Constants.ClassNames.openedClass); + removeClass(this._dom.root, _Constants.ClassNames.closedClass); + this._commandingSurface.synchronousOpen(); + _LightDismissService.shown(this._dismissable); // Call at the start of the open animation + }; + AppBar.prototype._updateDomImpl_renderClosed = function () { + addClass(this._dom.root, _Constants.ClassNames.closedClass); + removeClass(this._dom.root, _Constants.ClassNames.openedClass); + this._commandingSurface.synchronousClose(); + _LightDismissService.hidden(this._dismissable); // Call after the close animation + }; + /// + /// Display options for the AppBar when closed. + /// + AppBar.ClosedDisplayMode = ClosedDisplayMode; + /// + /// Display options for AppBar placement in relation to the main view. + /// + AppBar.Placement = Placement; + AppBar.supportedForProcessing = true; + return AppBar; + })(); + exports.AppBar = AppBar; + _Base.Class.mix(AppBar, _Events.createEventProperties(_Constants.EventNames.beforeOpen, _Constants.EventNames.afterOpen, _Constants.EventNames.beforeClose, _Constants.EventNames.afterClose)); + // addEventListener, removeEventListener, dispatchEvent + _Base.Class.mix(AppBar, _Control.DOMEventMixin); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// +define('WinJS/Controls/AppBar',["require", "exports", '../Core/_Base'], function (require, exports, _Base) { + var module = null; + _Base.Namespace.define("WinJS.UI", { + AppBar: { + get: function () { + if (!module) { + require(["./AppBar/_AppBar"], function (m) { + module = m; + }); + } + return module.AppBar; + } + } + }); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('ui',[ + 'WinJS/Core/_WinJS', + 'WinJS/VirtualizedDataSource', + 'WinJS/Controls/IntrinsicControls', + 'WinJS/Controls/ListView', + 'WinJS/Controls/FlipView', + 'WinJS/Controls/ItemContainer', + 'WinJS/Controls/Repeater', + 'WinJS/Controls/DatePicker', + 'WinJS/Controls/TimePicker', + 'WinJS/Controls/BackButton', + 'WinJS/Controls/Rating', + 'WinJS/Controls/ToggleSwitch', + 'WinJS/Controls/SemanticZoom', + 'WinJS/Controls/Pivot', + 'WinJS/Controls/Hub', + 'WinJS/Controls/Flyout', + 'WinJS/Controls/_LegacyAppBar', + 'WinJS/Controls/Menu', + 'WinJS/Controls/SearchBox', + 'WinJS/Controls/SettingsFlyout', + 'WinJS/Controls/NavBar', + 'WinJS/Controls/Tooltip', + 'WinJS/Controls/ViewBox', + 'WinJS/Controls/ContentDialog', + 'WinJS/Controls/SplitView', + 'WinJS/Controls/SplitViewPaneToggle', + 'WinJS/Controls/ToolBar', + 'WinJS/Controls/AppBar', + ], function (_WinJS) { + "use strict"; + + return _WinJS; +}); + + require(['WinJS/Core/_WinJS', 'ui'], function (_WinJS) { + // WinJS always publishes itself to global + globalObject.WinJS = _WinJS; + if (typeof module !== 'undefined') { + // This is a CommonJS context so publish to exports + module.exports = _WinJS; + } + }); + return globalObject.WinJS; + })); +}()); + diff --git a/UnitsNet.TestApps.Uwp.JavaScript/css/default.css b/UnitsNet.TestApps.Uwp.JavaScript/css/default.css new file mode 100644 index 0000000000..46800d16ad --- /dev/null +++ b/UnitsNet.TestApps.Uwp.JavaScript/css/default.css @@ -0,0 +1,2 @@ +body { +} diff --git a/UnitsNet.TestApps.Uwp.JavaScript/default.html b/UnitsNet.TestApps.Uwp.JavaScript/default.html new file mode 100644 index 0000000000..146d754434 --- /dev/null +++ b/UnitsNet.TestApps.Uwp.JavaScript/default.html @@ -0,0 +1,47 @@ + + + + + UnitsNet.TestApps.Uwp.JavaScript + + + + + + + + + + + + + + +
+

Content goes here

+
+ + diff --git a/UnitsNet.TestApps.Uwp.JavaScript/images/LockScreenLogo.scale-200.png b/UnitsNet.TestApps.Uwp.JavaScript/images/LockScreenLogo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..735f57adb5dfc01886d137b4e493d7e97cf13af3 GIT binary patch literal 1430 zcmaJ>TTC2P7~aKltDttVHYH6u8Io4i*}3fO&d$gd*bA_<3j~&e7%8(eXJLfhS!M@! zKrliY>>6yT4+Kr95$!DoD(Qn-5TP|{V_KS`k~E6(LGS@#`v$hQo&^^BKsw3HIsZBT z_y6C2n`lK@apunKojRQ^(_P}Mgewt$(^BBKCTZ;*xa?J3wQ7~@S0lUvbcLeq1Bg4o zH-bvQi|wt~L7q$~a-gDFP!{&TQfc3fX*6=uHv* zT&1&U(-)L%Xp^djI2?~eBF2cxC@YOP$+9d?P&h?lPy-9M2UT9fg5jKm1t$m#iWE{M zIf%q9@;fyT?0UP>tcw-bLkz;s2LlKl2qeP0w zECS7Ate+Awk|KQ+DOk;fl}Xsy4o^CY=pwq%QAAKKl628_yNPsK>?A>%D8fQG6IgdJ ztnxttBz#NI_a@fk7SU`WtrpsfZsNs9^0(2a z@C3#YO3>k~w7?2hipBf{#b6`}Xw1hlG$yi?;1dDs7k~xDAw@jiI*+tc;t2Lflg&bM)0!Y;0_@=w%`LW^8DsYpS#-bLOklX9r?Ei}TScw|4DbpW%+7 zFgAI)f51s}{y-eWb|vrU-Ya!GuYKP)J7z#*V_k^Xo>4!1Yqj*m)x&0L^tg3GJbVAJ zJ-Pl$R=NAabouV=^z_t;^K*0AvFs!vYU>_<|I^#c?>>CR<(T?=%{;U=aI*SbZADLH z&(f2wz_Y0??Tf|g;?|1Znw6}6U43Q#qNRwv1vp9uFn1)V#*4p&%$mP9x&15^OaBiDS(XppT|z^>;B{PLVEbS3IFYV yGvCsSX*m literal 0 HcmV?d00001 diff --git a/UnitsNet.TestApps.Uwp.JavaScript/images/SplashScreen.scale-200.png b/UnitsNet.TestApps.Uwp.JavaScript/images/SplashScreen.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..023e7f1feda78d5100569825acedfd213a0d84e9 GIT binary patch literal 7700 zcmeHLYj~4Yw%(;oxoEH#Kxq-eR|+VkP17b#Vk;?4QwkI+A{L04G+#<<(x#Un1#+h5>eArRq zTw$)ZvTWW_Y?bDho0nPVTh08+s`sp!j74rJTTtXIDww0SILedFv?sZ?yb@@}GN;#8 znk_b~Q(A0YR#uV4ef!osoV1M3;vQ8N$O|fStfgf$S5;ddUNv`tWtGjM;koG#N;7M< zP*84lnx(bn_KF&9Z5Ai$)#Cs3a|$OFw>WKCT$of*L7_CqQEinflT|W{JT+aKp-E0v zsxmYg)1(T>DROm+LN1eQw8}KCTp=C!$H7`PU!t9_Hw@TsTI2`udRZv*!a5`#A9hK6Y95L(CDUX&_@QxKV z_feX{UhA#ZWlvgpL$#w^D#lq`_A4AzDqd|Zv6y9PX&DNcN|l}_D^{q@GG&H^Pg583 z8FI6N8^H7b5WjGp;urW)d7F+_lcp%KsLX0viCmE(OHH+=%ZfD_=`voUuoUxFO^L;- z;!;2{g-YiiO6m4bs89OuF9!p{FGtH-f%8<2gY!h9s)4ciN%{Kh1+`}{^}M~+TDH9N z^Z5PlgVXMC&2&k*Hw^Lb9gny#ro$MOIxIt{+r)EA10$VR3 zanN8D{TUkl+v0CQ_>ZoHP<M-x#8@8ZiT#$Kh`(uRaX1g$Bg|qy$<#7 zSSAi{Nb8Y=lvNVeio+UGLCAtoLBfL`iOv`)yoJMDJBN>4IH@(l7YRF;61@>qq1iM9 zr@b#OC~SAxSle?5Pp8Z78{VO0YFr1x7kZU64Z23eLf2T2#6J_t;-E}DkB?NufZ0Ug zi?J&byXeaB-uTNVhuiM!UVQw}bZrJ3GtAETYp->!{q#zfN7D3AS9@Q7*V^85jGx#R z(QxYV(wW#F0XF9^^s>>H8pPlVJ>)3Oz z&_X8Sf@~?cH_O*cgi$U#`v`RRfv#y3m(ZpKk^5uLup+lVs$~}FZU$r_+}#hl%?g5m z-u-}-666ssp-xWQak~>PPy$mRc|~?pVSs1_@mBEXpPVfLF6(Ktf1S* zPPh@QZ=tFMs?LM2(5P3L2;l_6XX6s&cYsP1ip#eg0`ZEP0HGYh{UmS@o`MihLLvkU zgyAG0G`b1|qjxxh1(ODKFE%AP}Dq=3vK$P7TXP4GrM1kQ72!GUVMDl`rDC&2;TA}*nF z8$nQD&6ys_nc1*E7$*1S@R8$ymy(sQV}imGSedB@{!QR5P&N_H=-^o!?LsWs+2|mH z-e=)T^SvI)=_JIm7}j4;@*Z17=(#}m=~YF~z~CLI+vdAGlJDcdF$TM?CVI1%LhUrN zaa6DJ=Yh$)$k&Oz{-~8yw^GM^8prYxSxo zvI4k#ibryMa%%*8oI-5m61Koa_A_xg=(fwp0aBX{;X4Q;NXUhtaoJDo1>TqhWtn=_ zd5~chq#&6~c%8JZK#t_&J(9EVUU&upYeIovLt1>vaHe}UUq>#RGQj!EN#5+0@T`(@ z^g~>*c`VGRiSt;!$_4+0hk^I!@O3``5=sZ8IwlxWW7km1B&_t&E*u0_9UBa#VqwY* zz>nxv?FAsVnRaD(Bui=6i==BFUw0k4n$>`umU`F2l?7CYTD^)c2X+d9X&ddS9|gj? zM?knGkGCX&W8offw8aLC2$D{PjC3nVZwd4k?eZH8*mZ)U@3Qk8RDFOz_#WUA#vnzy zyP>KrCfKwSXea7}jgJjBc}PGY+4#6%lbZyjhy`5sZd_Vy6Wz;ixa?czkN}J9It1K6 zY!eu>|AwF^fwZlLAYyQI*lM@^>O>Iu6Vf6i>Q$?v!SeUS<{>UYMwz$*%Aq?w^`j{h z!$GZbhu=^D{&ET8;))LL%ZBDZkQqRd2;u~!d9bHGmLRhLDctNgYyjsuvoSZ#iVdoB z2!f--UUA#U;<{je#?cYt^{PIyKa%hW>}uepWMyAI{{Zo7?2>?$c9;whJae%oN|I-kpTQSx_C$Z&;f zi2i)qmEn=y4U0uvk)$m;zKfjPK@oc?I`}1Jzl$Q~aoKBd3kt7L#7gyt|A_qgz6ai< z=X%D1i!d2h?rHR^R8SUj&G||dkC?DT>{o#Yau<@uqVT{Xef&XG}5*E4aPk{}~ zplx&XhaV)&1EfI3Em;Bw#O5SV^c;{twb-1Rw)+=0!e_BLbd7tYmXCH0wrlOSS+~`7He8Iqx0{CN+DVit9;*6L~JAN zD&cyT)2?h}xnYmL?^)<7YyzZ3$FHU^Eg;DLqAV{#wv#Wj7S`Jdl1pX&{3(uZ?!uh} zDc$ZTNV*7le_W6}Hju~GMTxZQ1aWCeUc%!jv3MHAzt>Y-nQK%zfT*3ebDQA5b?iGn; zBjv3B+GhLTexd_(CzZDP4|#n5^~scvB6#Pk%Ho!kQ>yYw((Dv{6=$g3jT1!u6gORW zx5#`7Wy-ZHRa~IxGHdrp(bm%lf>2%J660nj$fCqN(epv@y!l9s7@k6EvxS{AMP>WY zX4$@F8^kayphIx-RGO$+LYl9YdoI5d|4#q9##`_F5Xnx`&GPzp2fB{-{P@ATw=X@~ z_|&^UMWAKD;jjBKTK(~o?cUFRK8EX=6>cXpfzg4ZpMB>*w_^8GSiT-Jp|xBOnzM+j z*09-@-~qJ(eqWq5@R4i^u4^{McCP(!3}C|v_WsTR*bIUxN(Nx`u##3B4{sE`Z`v8w zAwIG`?1~PkID~W{uDzmqH98Pew_1(;x2%8r^vY{)_&J2K)cN{W+h5+g)ZcjP&Ci#O zgy|8K@4kyMfwilHd&6TDlhb%++Pk!>9HRld6HT7gwyZGrxS$}CsD6`>6!!2K1@Mjf z(P0WYB7V_OFZyeWrbOFb>O54BNXf~K&?}3=^v;v_wT{DKr?jN^DtN&DXwX%u?s*c6`%8>WFz z7}YW^tp0bp^NriE)AB6M2l<7rn7fzePtR*omOevpfm9n?}2V*+0iW;S)C zhg`NAjL?D=W#k*$aR{>pGf~lD-rVtD;5jW1_*Jn1j1=es@Kcx4ySM_bwcQCT=d+DV z>Sz~L=Hj@(X%31nK$mWI@7d>}ORB`K(p=+`UD)+99YUGQc7y^bHZ1F(8|tL0 zdK*DT0kSXG_{BKTpP2*2PecdKV9;dq$^ZZDP;Nyq1kp-&GI5eAyZsK!e3V zK@rPy*{(`KIfo+lc878mDKk^V#`VT05}64kBtk%DgwLrOvLMj5-;*GNKv6c6pzMuL z6EP%ob|_0IW}lLRXCP2!9wWhEw3LA7iF#1O1mIZ@Z=6&bz41F;@S_GvYAG-#CW3z{ zP3+6vHhvP&A3$##Vo9$dT^#MoGg^|MDm=Bt1d2RRwSZ<;ZHICpLBv5Xs!D?BH^(9_ z7`H=N&^v|Z-%mP}wNzG{aiFCsRgwzwq!N6obW9+7(R; z(SZ=23`|`>qil!LMGG{_Heq!BD>(Y-zV9wD)}hz25JA37YR%39;kI4y9pgtcUass6 zP24}ZY$vvYeI`zy&)A_X#nY3017ap*0&jx|mVwyGhg3;!keU53a}Uhm3BZI$N$6Se zLWlAmy1S0xKJm4G_U@sN_Tm=`$xWJSEwKU98rZ&)1R^*$$1vA3oG#&*%SMxY_~oGP zP&PFJatFLM-Ps%84IV-+Ow)T{C7cqUAvauy4C z(FRz&?6$Rypj{xO!`y=*J5o4@U8Q-(y5(*=YoKeZ+-1YdljXxkA#B)zo=FeQH#?Le zycNUmEEHWO9a=X^pb#&cOq7-`7UA87#|S22)<7RUtZo|(zibX=w;K3qur9vy#`MNV z6UUcf9ZwEnKCCp+OoBnF@OdbvH)ANXO0o~Pi9l8=x3))}L<#vO0-~O4!~--Ket?d} zJaqsj<@CD1%S2cTW%rOP{Vto%0sGW~1RMa_j^)5nil0Yw- z0EE#bP+l4#P^%PQ+N*oxu1Zq05xZ!bXfYTg>9c{(Iw*lnjR^>kz%lAN^zFce7rppy zY8zA~3GD=A6d*hze&l4D_wA~+O!56)BZTe_rEu}Ezi<4!kG|W#amBZ5{&XS2@6R~H z{9o^y*BkH4$~yX9U&@CgbOzX1bn9xqF|zh$Dh0Y5y*E0e90*$!ObrHY3Ok0`2=O~r zCuke6KrP9KOf?V(YDsM<6pX2nVoN%M$LT^q#FmtaF?1^27F*IcNX~XRB(|hCFvdcc zc)$=S-)acdk$g4?_>jRqxpI6M3vHZk?0c^3=byamYDNf;uB{3NlKW5IhnOS3DNkMV z?tK8?kJ}pmvp%&&eTVOVjHP`q34hN1@!aK}H(K!vI`~gf|Gv+FNEQD5Yd<~yX7k_l h&G-K)@HZb3BABY{)U1?^%I#E6`MGoTtustd{~yM6srvu` literal 0 HcmV?d00001 diff --git a/UnitsNet.TestApps.Uwp.JavaScript/images/Square150x150Logo.scale-200.png b/UnitsNet.TestApps.Uwp.JavaScript/images/Square150x150Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..af49fec1a5484db1d52a7f9b5ec90a27c7030186 GIT binary patch literal 2937 zcma)84OCO-8BSud5)jwMLRVKgX(S?$n?Ld|vrsm<$CF7)&zTbyy1FE5bU`Q17MRv`9ue$;R(@8kR;#vJ*IM0>cJIAOte!d7oRgdH zd%ySjdB6L9=gX^A6)VzH7p2l@v~3zJAMw|DFy#^)F@@F*`mqUn=Il>l)8_+ab;nOW{%+iPx z+s{Eu|&pIs)Z7{La9~?xKfyl z#43?gjEL15d4WbOZo#SiP%>DB^+BcnJ=7dHEe;r#G=tuw|ka z%q@}##Uh7;tc%L_64m(kHtw74ty%BJMb)_1)#S0j`)F8_1jF7vScpsnH=0V19bO8y zR`0SjIdCUo&=>JwMQF8KHA<{ODHTiQh}0^@5QRmCA?gOH6_H3K^-_sNB^RrdNuK-R zOO*vOrKCVvDwgUck`kF(E7j{I#iiN;b*ZdCt4m@HPA`EuEqGGf4%!K<;(=I=&Vyrw z%TwcWtxa}8mCZ%Cyf&ActJ6_$ox5z6-D!0-dvnRx6t7y3d+h6QYpKWO;8OdnvERo7 zuEf>ih5`wqY)~o@OeVt-wM?Q!>QzdGRj!bz6fzYrfw$hZfAKzr2-M+D+R>}~oT574c;_3zquHcElqKIsryILt3g8n3jcMb+j?i?-L3FpZJ z2WRVBRdDPc+G5aaYg#5hpE+6nQ|(VSoxT3|biF;BUq#==-27Xi=gihDPYP$7?=9cP zYKE$jeQ|3~_L0VG-(F~2ZPyD0=k{J4Q~h(t__{-mz_w8{JDY9{`1ouzz!Vr5!ECdE z6U~O1k8c}24V7~zzXWTV-Pe4)y}wQJS&q%H5`Fo_f_JvIU489aCX$;P`u#!I-=^4ijC2{&9!O&h>mi?9oYD=GC#%)6{GzN6nQYw+Fal50!#x^asjBBR50i`+mho*ttoqV)ubM2KD9S~k7+FR4>{29?6 z{!l6kDdyTN0YJ9LgkPWeXm|gyi@zM3?0@{&pXT12w|78&W-q!RRF)&iLCEZVH<|fR zN0fr2^t8H(>L?>K#>^+jWROLral(Qy-xoBq1U7A&DV||wClb)Otd9?(gZ|8znMF}D zf<1haWz^s0qgecz;RFGt0C-B4g`jNGHsFU+;{<%t65v^sjk^h$lmWn#B0#_)9ij&d z-~lc`A)YYExi^7sBuPM^Y|wA2g*5?`K?#7tzELQYNxGo$UB$4J8RJp1k(8Jj+~hMT zlN~>M@KTTh^--8y3PK_NZ@AC!{PT=CziBzGd+wTJ^@icH!Bd}%)g8V)%K?|c&WTUk zy}qv1C%(fjRoZ4ozC3{O%@5?)XzH35zHns$pgU*Q?fj4v?fp1Qbm+j;3l;9jam9Da zXVcKjPlQ73x78QPu|Ffm6x?`~e3oD=gl=4kYK?={kD5j~QCXU)`HSdduNNENzA*2$ zOm3PzF!lN5e*06-f1Uot67wY#{o-S1!KZ7E=!~7ynnk9_iJR#kFoNbAOT#^2Gd17F zMmvU6>lndZQGd|ax9kUoXXO+$N?|j@6qpsF&_j7YXvwo_C{JpmLw5&#e6k>atv%es z5)7r*Wvv_JkUpT}M!_o!nVlEk1Zbl=a*2hQ*<|%*K1Glj^FcF`6kTzGQ3lz~2tCc@ z&x|tj;aH&1&9HwcJBcT`;{?a+pnej;M1HO(6Z{#J!cZA04hnFl;NXA+&`=7bjW_^o zfC40u3LMG?NdPtwGl>Tq6u}*QG)}-y;)lu-_>ee3kibW(69n0$0Zy!}9rQz%*v1iO zT9_H>99yIrSPYVy6^);rR}7Yo=J_T@hi+qhTZXnVWyf;JDYm5#eYLTxr*?kiNn!+Y zQ+LUkBafNJ#rH#C(?d5^;gw9o#%daEI{mA*LHPIHPU`#|H$hD zwm>0&+kahQ)E#%~k>&5@&#Vg82H?s%71=)(soi@174pi9--2{w{1$}Sz4zGn3Du&x bht0Iza^2ykEt4(epJ78uh5nDlX8(TxzDYwP literal 0 HcmV?d00001 diff --git a/UnitsNet.TestApps.Uwp.JavaScript/images/Square44x44Logo.scale-200.png b/UnitsNet.TestApps.Uwp.JavaScript/images/Square44x44Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..ce342a2ec8a61291ba76c54604aea7e9d20af11b GIT binary patch literal 1647 zcmaJ?eM}Q)7(e+G1Q(|`V9JhTI2>MkceK4;p;PR&$Pi?ejk3YQ_3o`S&|W_dsOZ8# zWPTt69g`t$ab`0cj-Y0yiBSOqmd)tG7G(}M5aP0_%&9TijB#&)I{zSE^4@#z^FF`l z`8{8`o%wlL(UI|y2!cdsuVamHH~H86F!*-15em4)NqUpCQM5?aoC_eCf@lV4wvF2a zjDQn1JBL69f&@2M3rvzJcfE!eZ8FZUBlFlC5RD)it33{mF9#B82AiyQE%w)`vlwa> zv{<1sm&kSKK$&%2jSFn7$t&P%%6Ue>R=EAnG8N7fqynWG8L3p!4801a;8{+nliO(qd(jNJ_?+9W3#hLIDLoT6~3fx9=`CC-D}-AMrpEO7HK zt3$GicGPc?GmDjy7K2P@La;eu4!$zWCZ`ym{Z$b zu-O6RM&K4JT|BIZB`E-gxqG%FzanI#+2FFmqHqXG7yxWB=w55RGOM)$xMb(>kSNR z2w=1AZi%z=AmG~yea~XaXJR!v7vLn(RUnELfiB1|6D84ICOS}^Zo2AdN}<&*h}G_u z{xZ!(%>tLT3J3<5XhWy-tg+6)0nmUUENLW8TWA{R6bgVd3X;anYFZ^IRis*_P-C-r z;i>%1^eL3UI2-{w8nuFFcs0e~7J{O2k^~Ce%+Ly4U?|=!0LH=t6()xi<^I-rs+9sF z*q{E-CxZbGPeu#a;XJwE;9S1?#R&uns>^0G3p`hEUF*v`M?@h%T%J%RChmD|EVydq zmHWh*_=S%emRC*mhxaVLzT@>Z2SX0u9v*DIJ@WC^kLVdlGV6LpK$KIrlJqc zpJ921)+3JJdTx|<`G&kXpKkjGJv=76R`yYIQ{#c-`%+`#V(7}Q;&@6U8!Td1`d;?N z_9mnI#?AA}4J!r)LN4!E-@H5eXauuB7TOawS>Y|{-P?NNx-lq+z1W-+y(;39P&&LP zL{N80?&=C*qKmdA^moMZRuPcD!B<*mq$ch=0Cnlitw#txRWhb3%TQvPqjkC`F69G4b! ze7z9MZ#+;_#l?H37UqUhDFb^l&s2{oM$3I0o^Q!yx;;V)QmCMo)Tb_ui|mit8MS?U zm##6$sZZ1$@|s%?l@>4Z<*Q}sRBSKMhb4I{e5LdEhsHIHTe8Bod5c>6QtT>$XgUBz z6MK`kO$=jmt@FqggOhJ5j~e@ygRbG;<{Vu)*+nn9aQeo0;$#j;|MS=S$&L?BeV25z xs3B`@=#`5TF{^6(A1rvdY@|-RtQ|iS5{tyX+wH?;n8E)G$kykv-D^wh{{!TZT%7;_ literal 0 HcmV?d00001 diff --git a/UnitsNet.TestApps.Uwp.JavaScript/images/Square44x44Logo.targetsize-24_altform-unplated.png b/UnitsNet.TestApps.Uwp.JavaScript/images/Square44x44Logo.targetsize-24_altform-unplated.png new file mode 100644 index 0000000000000000000000000000000000000000..f6c02ce97e0a802b85f6021e822c89f8bf57d5cd GIT binary patch literal 1255 zcmaJ>TWs4@7*5+{G#S+&C!qC#> zf>5N3P6jO*Cz>ug*(_DmW=)kea&m$gZ^+nyiF`;j%w@}y8)>p*SH}C`m?DXeieF2U zyQHecc_L%Gh!7GMt+hG06y;+|p4>m~}PjA}rKViGiEnn7G0ZO<>G|7q;2?NwGCM3s?eued6%hd$B+ z*kQJ{#~$S=DFE(%=E+UkmlEI*%3llUf~8Ja9YU1Vui0IbGBkW_gHB%Rd&!!ioX zs40O?i9I{};kle7GMvE7(rk`la=gTI)47=>%?q@^iL-nUo3}h4S}N-KHn8t5mVP8w z&bSErwp+37 zNJJ8?a|{r5Q3R0Z5s-LB1WHOwYC@7pCHWND#cL1cZ?{kJ368_*(UDWUDyb<}0y@o# zfMF016iMWPCb6obAxT$JlB6(2DrlXDTB&!0`!m??4F(qWMhjVZo?JXQmz`1*58Z=& zcDmB|S-E@j?BoFGix0flckqdS4jsPNzhfWyWIM98GxcLs89C(~dw%$_t;JjX-SD}E zfiGV;{8Q%8r}w9x>EEigW81>`kvnU@pK)4+xk9@+bNj9L!AAZ@SZ@q|)&BmY3+HZx zul~BeG4|}-;L%cHViQGQX?^zFfO0&#cHwel=d`lH9sJ-@Sl@n*(8J2>%Ac`IxyY?Q z{=GhWvC#gu-~Ia7*n{=+;qM?Ul_wy1+u7ho;=`>EwP^g~R@{unBds`!#@}tluZQpS zm)M~nYEifJWJGx?_6DcTy>#uh%>!H9=hb^(v`=m3F1{L>db=<5_tm+_&knAQ2EU$s Mu9UqpbNZeC0BbUo^Z)<= literal 0 HcmV?d00001 diff --git a/UnitsNet.TestApps.Uwp.JavaScript/images/StoreLogo.png b/UnitsNet.TestApps.Uwp.JavaScript/images/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..7385b56c0e4d3c6b0efe3324aa1194157d837826 GIT binary patch literal 1451 zcmaJ>eN5D57_Z|bH;{0+1#mbl)eTU3{h)Wf7EZV?;HD@XL@{B`Ui%(2aMxQ~xdXSv z5nzWi(LW)U2=Vc-cY@s7nPt{i0hc6!7xN4NNHI#EQl>YNBy8l4%x9gr_W-j zEZMQmmTIy(>;lblRfh`dIyTgc9W5d!VP$L4(kKrN1c5G~(O_#xG zAJCNTstD^5SeXFB+&$h=ToJP2H>xr$iqPs-#O*;4(!Fjw25-!gEb*)mU}=)J;Iu>w zxK(5XoD0wrPSKQ~rbL^Cw6O_03*l*}i=ydbu7adJ6y;%@tjFeXIXT+ms30pmbOP%Q zX}S;+LBh8Tea~TSkHzvX6$rYb)+n&{kSbIqh|c7hmlxmwSiq5iVhU#iEQ<>a18|O^Sln-8t&+t`*{qBWo5M?wFM(JuimAOb5!K#D}XbslM@#1ZVz_;!9U zpfEpLAOz=0g@bd6Xj_ILi-x^!M}73h^o@}hM$1jflTs|Yuj9AL@A3<-?MV4!^4q`e z)fO@A;{9K^?W?DbnesnPr6kK>$zaKo&;FhFd(GYFCIU^T+OIMb%Tqo+P%oq(IdX7S zf6+HLO?7o0m+p>~Tp5UrXWh!UH!wZ5kv!E`_w)PTpI(#Iw{AS`gH4^b(bm^ZCq^FZ zY9DD7bH}rq9mg88+KgA$Zp!iWncuU2n1AuIa@=sWvUR-s`Qb{R*kk(SPU^`$6BXz8 zn#7yaFOIK%qGxyi`dYtm#&qqox0$h=pNi#u=M8zUG@bpiZ=3sT=1}Trr}39cC)H|v zbL?W)=&s4zrh)7>L(|cc%$1#!zfL?HjpeP%T+x_a+jZ16b^iKOHxFEX$7d|8${H-* zIrOJ5w&i$>*D>AKaIoYg`;{L@jM((Kt?$N$5OnuPqVvq**Nm}(f0wwOF%iX_Pba;V z;m@wxX&NcV3?<1+u?A{y_DIj7#m3Af1rCE)o`D&Y3}0%7E;iX1yMDiS)sh0wKi!36 zL!Wmq?P^Ku&rK~HJd97KkLTRl>ScGFYZNlYytWnhmuu|)L&ND8_PmkayQb{HOY640 bno1(wj@u8DCVuFR|31B*4ek@pZJqxCDDe1x literal 0 HcmV?d00001 diff --git a/UnitsNet.TestApps.Uwp.JavaScript/images/Wide310x150Logo.scale-200.png b/UnitsNet.TestApps.Uwp.JavaScript/images/Wide310x150Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..288995b397fdbef1fb7e85afd71445d5de1952c5 GIT binary patch literal 3204 zcmbVPeQXow8NYmBd90>}0NP?GhXW~VaeThm=a0tV#EwJMI!)6M3}|c4_Bl3=Kd>G0 z(GHx1wl<7(tP?FsOQkTilSo*iIvF%uArExJ73~P zSv1xEy!U(Wd4A9D`FQV@W3@F^qJ@PEF$@z`Z!*BbFsS(^?B zyiAzJ+q})bkgiQHWqEb*jJD-coHYr1^iocg)l!Qa{Xqs-l~6J}p-|##ZHYofskQ3$ zI0;xzXyhazBeXhIsg5A=%ufo@f)1yy&ScKS0;HF^!r_2UE^lpZEom(+@duma3awTv zCrCL-%D_SvYWIcdHkmI}#50(fkUi)Qgx!80ju>g1za^}ff>JI8Z@^-iCiaCgg@TgF z+vtE?Q9{VQUX&MW9SYYmGcxA14%N2@7FwBTD4N<(2{nWgV8$e3?-F=L^&FrtWn~(U_Q~~^uYiyeY6-KoTnfh9AWz@ zIKje0)u!_Lw)E}G!#kEfwKVdNt(UAf9*f>tEL_(=xco-T%jTi@7YlC3hs2ik%Le0H ztj}RTeCF(5mwvi3_56>-yB?l;J>-1%!9~=fs|QcNG3J~a@JCu`4SB460s0ZO+##4fFUSGLcj_ja^fL4&BKALfb#$6$O?>P@qx2Agl^x0i&ugt zsy5Pyu=()`7HRMG3IB7F1@`_ z+-!J%#i6e^U$e#+C%Q>_qVRzWRsG^W_n+@OcX@vzI&z;mzHNb!GQ?LWA(wtpqHqTM z1OFw_{Zn?fD)p)`c`kOgv{de=v@suGRqY{N^U7gI1VF3*F=obwaXI6ob5__Yn zVTguS!%(NI09J8x#AO_aW!9W7k*UvB;IWDFC3srwftr{kHj%g)fvnAm;&h_dnl~

MY- zf+K}sCe8qU6Ujs`3ua{U0Of$R_gVQBuUA za0v=mu#vIOqiiAZOr&h*$WyOw&k-xr$;G4Ixa!#TJNr>95(h>l%)PUy4p+^SgR(uR zta%k*?ny-+nAr8spEk1fo{J4i!b^Fia`N{_F6@zidA2ZTTrjl#^5Z-2KfB@Cu}l9s z(*|Z2jc?p~vn2f)3y9i*7zJV1L{$?|&q)4oaT;uXi6>1GkRXVTOzAz(RHEmr=eFIi z`}<>-Q?K0GN8!IYxeP1XKXO+jsJbp~o^);Bc;%b7Flpe7;1`Ny@3r7ZR;?R)aJt8C ziNlEC<@3f_lIV4TwV}&e;D!Ee5_|e#g0LUh=5vmYWYm7&2h*M>QPKvGh9-)wfMMW3 z8J9b%1k7dzPzO0_NGQy92BZ^FR6R~6;^6?lqO;-QUP4BY%cG%3vEhbm#>4vIhPBh3 z-+pZGjh$x%Hp{?=FHsMp0&wNPlj00us{&`1ZOZTqs8%4X&xH=UDr*xyBW(Zp&Em94 zf)ZSfn#yg0N)>!1kWdkqJ^S*z0FF5|fj&qcE#Na|%OY0$uO>!&hP+1ywfD_WXk@4J(?MBftK7>$Nvqh@tDuarN%PrTLQ2Uzysx>UV=V zk^RrDSvdQ?0;=hY67EgII-f4`t=+i*yS=Y~!XlqIy_4x&%+OdfbKOFPXS2X5%4R{N z$SQMX^AK6(fA + + + + + UnitsNet.TestApps.Uwp.JavaScript + Andreas + images\storelogo.png + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UnitsNet.TestApps.Uwp.JavaScript/packages.config b/UnitsNet.TestApps.Uwp.JavaScript/packages.config new file mode 100644 index 0000000000..7c41c26962 --- /dev/null +++ b/UnitsNet.TestApps.Uwp.JavaScript/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file From d72d912c14fd2c293aa144240cd45f66eadd477a Mon Sep 17 00:00:00 2001 From: Andreas Gullberg Larsen Date: Sun, 10 Apr 2016 12:06:59 +0200 Subject: [PATCH 12/17] testapp: Add WinJS app with manually added project.json As recommended by nuget team: https://github.com/NuGet/Home/issues/2406#issuecomment-207867025 This works around the issue with packages.config and SpecificVersion. Copied GUI and JS code from previous JS test app. --- .../UnitsNet.TestApps.Uwp.WinJS.jsproj | 91 + UnitsNet.TestApps.Uwp.WinJS/css/default.css | 2 + .../images/LockScreenLogo.scale-200.png | Bin 0 -> 1430 bytes .../images/SplashScreen.scale-200.png | Bin 0 -> 7700 bytes .../images/Square150x150Logo.scale-200.png | Bin 0 -> 2937 bytes .../images/Square44x44Logo.scale-200.png | Bin 0 -> 1647 bytes ...x44Logo.targetsize-24_altform-unplated.png | Bin 0 -> 1255 bytes .../images/StoreLogo.png | Bin 0 -> 1451 bytes .../images/Wide310x150Logo.scale-200.png | Bin 0 -> 3204 bytes UnitsNet.TestApps.Uwp.WinJS/index.html | 43 + UnitsNet.TestApps.Uwp.WinJS/js/main.js | 27 + .../lib/winjs-4.0.1/css/ui-dark.css | 7304 ++ .../lib/winjs-4.0.1/css/ui-light.css | 7304 ++ .../lib/winjs-4.0.1/js/base.js | 26523 ++++++++ .../lib/winjs-4.0.1/js/ui.js | 54913 ++++++++++++++++ .../package.appxmanifest | 52 + UnitsNet.TestApps.Uwp.WinJS/project.json | 17 + 17 files changed, 96276 insertions(+) create mode 100644 UnitsNet.TestApps.Uwp.WinJS/UnitsNet.TestApps.Uwp.WinJS.jsproj create mode 100644 UnitsNet.TestApps.Uwp.WinJS/css/default.css create mode 100644 UnitsNet.TestApps.Uwp.WinJS/images/LockScreenLogo.scale-200.png create mode 100644 UnitsNet.TestApps.Uwp.WinJS/images/SplashScreen.scale-200.png create mode 100644 UnitsNet.TestApps.Uwp.WinJS/images/Square150x150Logo.scale-200.png create mode 100644 UnitsNet.TestApps.Uwp.WinJS/images/Square44x44Logo.scale-200.png create mode 100644 UnitsNet.TestApps.Uwp.WinJS/images/Square44x44Logo.targetsize-24_altform-unplated.png create mode 100644 UnitsNet.TestApps.Uwp.WinJS/images/StoreLogo.png create mode 100644 UnitsNet.TestApps.Uwp.WinJS/images/Wide310x150Logo.scale-200.png create mode 100644 UnitsNet.TestApps.Uwp.WinJS/index.html create mode 100644 UnitsNet.TestApps.Uwp.WinJS/js/main.js create mode 100644 UnitsNet.TestApps.Uwp.WinJS/lib/winjs-4.0.1/css/ui-dark.css create mode 100644 UnitsNet.TestApps.Uwp.WinJS/lib/winjs-4.0.1/css/ui-light.css create mode 100644 UnitsNet.TestApps.Uwp.WinJS/lib/winjs-4.0.1/js/base.js create mode 100644 UnitsNet.TestApps.Uwp.WinJS/lib/winjs-4.0.1/js/ui.js create mode 100644 UnitsNet.TestApps.Uwp.WinJS/package.appxmanifest create mode 100644 UnitsNet.TestApps.Uwp.WinJS/project.json diff --git a/UnitsNet.TestApps.Uwp.WinJS/UnitsNet.TestApps.Uwp.WinJS.jsproj b/UnitsNet.TestApps.Uwp.WinJS/UnitsNet.TestApps.Uwp.WinJS.jsproj new file mode 100644 index 0000000000..894618691a --- /dev/null +++ b/UnitsNet.TestApps.Uwp.WinJS/UnitsNet.TestApps.Uwp.WinJS.jsproj @@ -0,0 +1,91 @@ + + + + + Debug + AnyCPU + + + Debug + ARM + + + Debug + x64 + + + Debug + x86 + + + Release + AnyCPU + true + + + Release + ARM + true + + + Release + x64 + true + + + Release + x86 + true + + + + b87e6239-f2ca-4b18-85ae-c8296d3c5e3b + + + + 14.0 + + + + + UAP + 10.0.10586.0 + 10.0.10240.0 + $(VersionNumberMajor).$(VersionNumberMinor) + en-US + UnitsNet.TestApps.Uwp.WinJS_TemporaryKey.pfx + + + + Designer + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UnitsNet.TestApps.Uwp.WinJS/css/default.css b/UnitsNet.TestApps.Uwp.WinJS/css/default.css new file mode 100644 index 0000000000..46800d16ad --- /dev/null +++ b/UnitsNet.TestApps.Uwp.WinJS/css/default.css @@ -0,0 +1,2 @@ +body { +} diff --git a/UnitsNet.TestApps.Uwp.WinJS/images/LockScreenLogo.scale-200.png b/UnitsNet.TestApps.Uwp.WinJS/images/LockScreenLogo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..735f57adb5dfc01886d137b4e493d7e97cf13af3 GIT binary patch literal 1430 zcmaJ>TTC2P7~aKltDttVHYH6u8Io4i*}3fO&d$gd*bA_<3j~&e7%8(eXJLfhS!M@! zKrliY>>6yT4+Kr95$!DoD(Qn-5TP|{V_KS`k~E6(LGS@#`v$hQo&^^BKsw3HIsZBT z_y6C2n`lK@apunKojRQ^(_P}Mgewt$(^BBKCTZ;*xa?J3wQ7~@S0lUvbcLeq1Bg4o zH-bvQi|wt~L7q$~a-gDFP!{&TQfc3fX*6=uHv* zT&1&U(-)L%Xp^djI2?~eBF2cxC@YOP$+9d?P&h?lPy-9M2UT9fg5jKm1t$m#iWE{M zIf%q9@;fyT?0UP>tcw-bLkz;s2LlKl2qeP0w zECS7Ate+Awk|KQ+DOk;fl}Xsy4o^CY=pwq%QAAKKl628_yNPsK>?A>%D8fQG6IgdJ ztnxttBz#NI_a@fk7SU`WtrpsfZsNs9^0(2a z@C3#YO3>k~w7?2hipBf{#b6`}Xw1hlG$yi?;1dDs7k~xDAw@jiI*+tc;t2Lflg&bM)0!Y;0_@=w%`LW^8DsYpS#-bLOklX9r?Ei}TScw|4DbpW%+7 zFgAI)f51s}{y-eWb|vrU-Ya!GuYKP)J7z#*V_k^Xo>4!1Yqj*m)x&0L^tg3GJbVAJ zJ-Pl$R=NAabouV=^z_t;^K*0AvFs!vYU>_<|I^#c?>>CR<(T?=%{;U=aI*SbZADLH z&(f2wz_Y0??Tf|g;?|1Znw6}6U43Q#qNRwv1vp9uFn1)V#*4p&%$mP9x&15^OaBiDS(XppT|z^>;B{PLVEbS3IFYV yGvCsSX*m literal 0 HcmV?d00001 diff --git a/UnitsNet.TestApps.Uwp.WinJS/images/SplashScreen.scale-200.png b/UnitsNet.TestApps.Uwp.WinJS/images/SplashScreen.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..023e7f1feda78d5100569825acedfd213a0d84e9 GIT binary patch literal 7700 zcmeHLYj~4Yw%(;oxoEH#Kxq-eR|+VkP17b#Vk;?4QwkI+A{L04G+#<<(x#Un1#+h5>eArRq zTw$)ZvTWW_Y?bDho0nPVTh08+s`sp!j74rJTTtXIDww0SILedFv?sZ?yb@@}GN;#8 znk_b~Q(A0YR#uV4ef!osoV1M3;vQ8N$O|fStfgf$S5;ddUNv`tWtGjM;koG#N;7M< zP*84lnx(bn_KF&9Z5Ai$)#Cs3a|$OFw>WKCT$of*L7_CqQEinflT|W{JT+aKp-E0v zsxmYg)1(T>DROm+LN1eQw8}KCTp=C!$H7`PU!t9_Hw@TsTI2`udRZv*!a5`#A9hK6Y95L(CDUX&_@QxKV z_feX{UhA#ZWlvgpL$#w^D#lq`_A4AzDqd|Zv6y9PX&DNcN|l}_D^{q@GG&H^Pg583 z8FI6N8^H7b5WjGp;urW)d7F+_lcp%KsLX0viCmE(OHH+=%ZfD_=`voUuoUxFO^L;- z;!;2{g-YiiO6m4bs89OuF9!p{FGtH-f%8<2gY!h9s)4ciN%{Kh1+`}{^}M~+TDH9N z^Z5PlgVXMC&2&k*Hw^Lb9gny#ro$MOIxIt{+r)EA10$VR3 zanN8D{TUkl+v0CQ_>ZoHP<M-x#8@8ZiT#$Kh`(uRaX1g$Bg|qy$<#7 zSSAi{Nb8Y=lvNVeio+UGLCAtoLBfL`iOv`)yoJMDJBN>4IH@(l7YRF;61@>qq1iM9 zr@b#OC~SAxSle?5Pp8Z78{VO0YFr1x7kZU64Z23eLf2T2#6J_t;-E}DkB?NufZ0Ug zi?J&byXeaB-uTNVhuiM!UVQw}bZrJ3GtAETYp->!{q#zfN7D3AS9@Q7*V^85jGx#R z(QxYV(wW#F0XF9^^s>>H8pPlVJ>)3Oz z&_X8Sf@~?cH_O*cgi$U#`v`RRfv#y3m(ZpKk^5uLup+lVs$~}FZU$r_+}#hl%?g5m z-u-}-666ssp-xWQak~>PPy$mRc|~?pVSs1_@mBEXpPVfLF6(Ktf1S* zPPh@QZ=tFMs?LM2(5P3L2;l_6XX6s&cYsP1ip#eg0`ZEP0HGYh{UmS@o`MihLLvkU zgyAG0G`b1|qjxxh1(ODKFE%AP}Dq=3vK$P7TXP4GrM1kQ72!GUVMDl`rDC&2;TA}*nF z8$nQD&6ys_nc1*E7$*1S@R8$ymy(sQV}imGSedB@{!QR5P&N_H=-^o!?LsWs+2|mH z-e=)T^SvI)=_JIm7}j4;@*Z17=(#}m=~YF~z~CLI+vdAGlJDcdF$TM?CVI1%LhUrN zaa6DJ=Yh$)$k&Oz{-~8yw^GM^8prYxSxo zvI4k#ibryMa%%*8oI-5m61Koa_A_xg=(fwp0aBX{;X4Q;NXUhtaoJDo1>TqhWtn=_ zd5~chq#&6~c%8JZK#t_&J(9EVUU&upYeIovLt1>vaHe}UUq>#RGQj!EN#5+0@T`(@ z^g~>*c`VGRiSt;!$_4+0hk^I!@O3``5=sZ8IwlxWW7km1B&_t&E*u0_9UBa#VqwY* zz>nxv?FAsVnRaD(Bui=6i==BFUw0k4n$>`umU`F2l?7CYTD^)c2X+d9X&ddS9|gj? zM?knGkGCX&W8offw8aLC2$D{PjC3nVZwd4k?eZH8*mZ)U@3Qk8RDFOz_#WUA#vnzy zyP>KrCfKwSXea7}jgJjBc}PGY+4#6%lbZyjhy`5sZd_Vy6Wz;ixa?czkN}J9It1K6 zY!eu>|AwF^fwZlLAYyQI*lM@^>O>Iu6Vf6i>Q$?v!SeUS<{>UYMwz$*%Aq?w^`j{h z!$GZbhu=^D{&ET8;))LL%ZBDZkQqRd2;u~!d9bHGmLRhLDctNgYyjsuvoSZ#iVdoB z2!f--UUA#U;<{je#?cYt^{PIyKa%hW>}uepWMyAI{{Zo7?2>?$c9;whJae%oN|I-kpTQSx_C$Z&;f zi2i)qmEn=y4U0uvk)$m;zKfjPK@oc?I`}1Jzl$Q~aoKBd3kt7L#7gyt|A_qgz6ai< z=X%D1i!d2h?rHR^R8SUj&G||dkC?DT>{o#Yau<@uqVT{Xef&XG}5*E4aPk{}~ zplx&XhaV)&1EfI3Em;Bw#O5SV^c;{twb-1Rw)+=0!e_BLbd7tYmXCH0wrlOSS+~`7He8Iqx0{CN+DVit9;*6L~JAN zD&cyT)2?h}xnYmL?^)<7YyzZ3$FHU^Eg;DLqAV{#wv#Wj7S`Jdl1pX&{3(uZ?!uh} zDc$ZTNV*7le_W6}Hju~GMTxZQ1aWCeUc%!jv3MHAzt>Y-nQK%zfT*3ebDQA5b?iGn; zBjv3B+GhLTexd_(CzZDP4|#n5^~scvB6#Pk%Ho!kQ>yYw((Dv{6=$g3jT1!u6gORW zx5#`7Wy-ZHRa~IxGHdrp(bm%lf>2%J660nj$fCqN(epv@y!l9s7@k6EvxS{AMP>WY zX4$@F8^kayphIx-RGO$+LYl9YdoI5d|4#q9##`_F5Xnx`&GPzp2fB{-{P@ATw=X@~ z_|&^UMWAKD;jjBKTK(~o?cUFRK8EX=6>cXpfzg4ZpMB>*w_^8GSiT-Jp|xBOnzM+j z*09-@-~qJ(eqWq5@R4i^u4^{McCP(!3}C|v_WsTR*bIUxN(Nx`u##3B4{sE`Z`v8w zAwIG`?1~PkID~W{uDzmqH98Pew_1(;x2%8r^vY{)_&J2K)cN{W+h5+g)ZcjP&Ci#O zgy|8K@4kyMfwilHd&6TDlhb%++Pk!>9HRld6HT7gwyZGrxS$}CsD6`>6!!2K1@Mjf z(P0WYB7V_OFZyeWrbOFb>O54BNXf~K&?}3=^v;v_wT{DKr?jN^DtN&DXwX%u?s*c6`%8>WFz z7}YW^tp0bp^NriE)AB6M2l<7rn7fzePtR*omOevpfm9n?}2V*+0iW;S)C zhg`NAjL?D=W#k*$aR{>pGf~lD-rVtD;5jW1_*Jn1j1=es@Kcx4ySM_bwcQCT=d+DV z>Sz~L=Hj@(X%31nK$mWI@7d>}ORB`K(p=+`UD)+99YUGQc7y^bHZ1F(8|tL0 zdK*DT0kSXG_{BKTpP2*2PecdKV9;dq$^ZZDP;Nyq1kp-&GI5eAyZsK!e3V zK@rPy*{(`KIfo+lc878mDKk^V#`VT05}64kBtk%DgwLrOvLMj5-;*GNKv6c6pzMuL z6EP%ob|_0IW}lLRXCP2!9wWhEw3LA7iF#1O1mIZ@Z=6&bz41F;@S_GvYAG-#CW3z{ zP3+6vHhvP&A3$##Vo9$dT^#MoGg^|MDm=Bt1d2RRwSZ<;ZHICpLBv5Xs!D?BH^(9_ z7`H=N&^v|Z-%mP}wNzG{aiFCsRgwzwq!N6obW9+7(R; z(SZ=23`|`>qil!LMGG{_Heq!BD>(Y-zV9wD)}hz25JA37YR%39;kI4y9pgtcUass6 zP24}ZY$vvYeI`zy&)A_X#nY3017ap*0&jx|mVwyGhg3;!keU53a}Uhm3BZI$N$6Se zLWlAmy1S0xKJm4G_U@sN_Tm=`$xWJSEwKU98rZ&)1R^*$$1vA3oG#&*%SMxY_~oGP zP&PFJatFLM-Ps%84IV-+Ow)T{C7cqUAvauy4C z(FRz&?6$Rypj{xO!`y=*J5o4@U8Q-(y5(*=YoKeZ+-1YdljXxkA#B)zo=FeQH#?Le zycNUmEEHWO9a=X^pb#&cOq7-`7UA87#|S22)<7RUtZo|(zibX=w;K3qur9vy#`MNV z6UUcf9ZwEnKCCp+OoBnF@OdbvH)ANXO0o~Pi9l8=x3))}L<#vO0-~O4!~--Ket?d} zJaqsj<@CD1%S2cTW%rOP{Vto%0sGW~1RMa_j^)5nil0Yw- z0EE#bP+l4#P^%PQ+N*oxu1Zq05xZ!bXfYTg>9c{(Iw*lnjR^>kz%lAN^zFce7rppy zY8zA~3GD=A6d*hze&l4D_wA~+O!56)BZTe_rEu}Ezi<4!kG|W#amBZ5{&XS2@6R~H z{9o^y*BkH4$~yX9U&@CgbOzX1bn9xqF|zh$Dh0Y5y*E0e90*$!ObrHY3Ok0`2=O~r zCuke6KrP9KOf?V(YDsM<6pX2nVoN%M$LT^q#FmtaF?1^27F*IcNX~XRB(|hCFvdcc zc)$=S-)acdk$g4?_>jRqxpI6M3vHZk?0c^3=byamYDNf;uB{3NlKW5IhnOS3DNkMV z?tK8?kJ}pmvp%&&eTVOVjHP`q34hN1@!aK}H(K!vI`~gf|Gv+FNEQD5Yd<~yX7k_l h&G-K)@HZb3BABY{)U1?^%I#E6`MGoTtustd{~yM6srvu` literal 0 HcmV?d00001 diff --git a/UnitsNet.TestApps.Uwp.WinJS/images/Square150x150Logo.scale-200.png b/UnitsNet.TestApps.Uwp.WinJS/images/Square150x150Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..af49fec1a5484db1d52a7f9b5ec90a27c7030186 GIT binary patch literal 2937 zcma)84OCO-8BSud5)jwMLRVKgX(S?$n?Ld|vrsm<$CF7)&zTbyy1FE5bU`Q17MRv`9ue$;R(@8kR;#vJ*IM0>cJIAOte!d7oRgdH zd%ySjdB6L9=gX^A6)VzH7p2l@v~3zJAMw|DFy#^)F@@F*`mqUn=Il>l)8_+ab;nOW{%+iPx z+s{Eu|&pIs)Z7{La9~?xKfyl z#43?gjEL15d4WbOZo#SiP%>DB^+BcnJ=7dHEe;r#G=tuw|ka z%q@}##Uh7;tc%L_64m(kHtw74ty%BJMb)_1)#S0j`)F8_1jF7vScpsnH=0V19bO8y zR`0SjIdCUo&=>JwMQF8KHA<{ODHTiQh}0^@5QRmCA?gOH6_H3K^-_sNB^RrdNuK-R zOO*vOrKCVvDwgUck`kF(E7j{I#iiN;b*ZdCt4m@HPA`EuEqGGf4%!K<;(=I=&Vyrw z%TwcWtxa}8mCZ%Cyf&ActJ6_$ox5z6-D!0-dvnRx6t7y3d+h6QYpKWO;8OdnvERo7 zuEf>ih5`wqY)~o@OeVt-wM?Q!>QzdGRj!bz6fzYrfw$hZfAKzr2-M+D+R>}~oT574c;_3zquHcElqKIsryILt3g8n3jcMb+j?i?-L3FpZJ z2WRVBRdDPc+G5aaYg#5hpE+6nQ|(VSoxT3|biF;BUq#==-27Xi=gihDPYP$7?=9cP zYKE$jeQ|3~_L0VG-(F~2ZPyD0=k{J4Q~h(t__{-mz_w8{JDY9{`1ouzz!Vr5!ECdE z6U~O1k8c}24V7~zzXWTV-Pe4)y}wQJS&q%H5`Fo_f_JvIU489aCX$;P`u#!I-=^4ijC2{&9!O&h>mi?9oYD=GC#%)6{GzN6nQYw+Fal50!#x^asjBBR50i`+mho*ttoqV)ubM2KD9S~k7+FR4>{29?6 z{!l6kDdyTN0YJ9LgkPWeXm|gyi@zM3?0@{&pXT12w|78&W-q!RRF)&iLCEZVH<|fR zN0fr2^t8H(>L?>K#>^+jWROLral(Qy-xoBq1U7A&DV||wClb)Otd9?(gZ|8znMF}D zf<1haWz^s0qgecz;RFGt0C-B4g`jNGHsFU+;{<%t65v^sjk^h$lmWn#B0#_)9ij&d z-~lc`A)YYExi^7sBuPM^Y|wA2g*5?`K?#7tzELQYNxGo$UB$4J8RJp1k(8Jj+~hMT zlN~>M@KTTh^--8y3PK_NZ@AC!{PT=CziBzGd+wTJ^@icH!Bd}%)g8V)%K?|c&WTUk zy}qv1C%(fjRoZ4ozC3{O%@5?)XzH35zHns$pgU*Q?fj4v?fp1Qbm+j;3l;9jam9Da zXVcKjPlQ73x78QPu|Ffm6x?`~e3oD=gl=4kYK?={kD5j~QCXU)`HSdduNNENzA*2$ zOm3PzF!lN5e*06-f1Uot67wY#{o-S1!KZ7E=!~7ynnk9_iJR#kFoNbAOT#^2Gd17F zMmvU6>lndZQGd|ax9kUoXXO+$N?|j@6qpsF&_j7YXvwo_C{JpmLw5&#e6k>atv%es z5)7r*Wvv_JkUpT}M!_o!nVlEk1Zbl=a*2hQ*<|%*K1Glj^FcF`6kTzGQ3lz~2tCc@ z&x|tj;aH&1&9HwcJBcT`;{?a+pnej;M1HO(6Z{#J!cZA04hnFl;NXA+&`=7bjW_^o zfC40u3LMG?NdPtwGl>Tq6u}*QG)}-y;)lu-_>ee3kibW(69n0$0Zy!}9rQz%*v1iO zT9_H>99yIrSPYVy6^);rR}7Yo=J_T@hi+qhTZXnVWyf;JDYm5#eYLTxr*?kiNn!+Y zQ+LUkBafNJ#rH#C(?d5^;gw9o#%daEI{mA*LHPIHPU`#|H$hD zwm>0&+kahQ)E#%~k>&5@&#Vg82H?s%71=)(soi@174pi9--2{w{1$}Sz4zGn3Du&x bht0Iza^2ykEt4(epJ78uh5nDlX8(TxzDYwP literal 0 HcmV?d00001 diff --git a/UnitsNet.TestApps.Uwp.WinJS/images/Square44x44Logo.scale-200.png b/UnitsNet.TestApps.Uwp.WinJS/images/Square44x44Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..ce342a2ec8a61291ba76c54604aea7e9d20af11b GIT binary patch literal 1647 zcmaJ?eM}Q)7(e+G1Q(|`V9JhTI2>MkceK4;p;PR&$Pi?ejk3YQ_3o`S&|W_dsOZ8# zWPTt69g`t$ab`0cj-Y0yiBSOqmd)tG7G(}M5aP0_%&9TijB#&)I{zSE^4@#z^FF`l z`8{8`o%wlL(UI|y2!cdsuVamHH~H86F!*-15em4)NqUpCQM5?aoC_eCf@lV4wvF2a zjDQn1JBL69f&@2M3rvzJcfE!eZ8FZUBlFlC5RD)it33{mF9#B82AiyQE%w)`vlwa> zv{<1sm&kSKK$&%2jSFn7$t&P%%6Ue>R=EAnG8N7fqynWG8L3p!4801a;8{+nliO(qd(jNJ_?+9W3#hLIDLoT6~3fx9=`CC-D}-AMrpEO7HK zt3$GicGPc?GmDjy7K2P@La;eu4!$zWCZ`ym{Z$b zu-O6RM&K4JT|BIZB`E-gxqG%FzanI#+2FFmqHqXG7yxWB=w55RGOM)$xMb(>kSNR z2w=1AZi%z=AmG~yea~XaXJR!v7vLn(RUnELfiB1|6D84ICOS}^Zo2AdN}<&*h}G_u z{xZ!(%>tLT3J3<5XhWy-tg+6)0nmUUENLW8TWA{R6bgVd3X;anYFZ^IRis*_P-C-r z;i>%1^eL3UI2-{w8nuFFcs0e~7J{O2k^~Ce%+Ly4U?|=!0LH=t6()xi<^I-rs+9sF z*q{E-CxZbGPeu#a;XJwE;9S1?#R&uns>^0G3p`hEUF*v`M?@h%T%J%RChmD|EVydq zmHWh*_=S%emRC*mhxaVLzT@>Z2SX0u9v*DIJ@WC^kLVdlGV6LpK$KIrlJqc zpJ921)+3JJdTx|<`G&kXpKkjGJv=76R`yYIQ{#c-`%+`#V(7}Q;&@6U8!Td1`d;?N z_9mnI#?AA}4J!r)LN4!E-@H5eXauuB7TOawS>Y|{-P?NNx-lq+z1W-+y(;39P&&LP zL{N80?&=C*qKmdA^moMZRuPcD!B<*mq$ch=0Cnlitw#txRWhb3%TQvPqjkC`F69G4b! ze7z9MZ#+;_#l?H37UqUhDFb^l&s2{oM$3I0o^Q!yx;;V)QmCMo)Tb_ui|mit8MS?U zm##6$sZZ1$@|s%?l@>4Z<*Q}sRBSKMhb4I{e5LdEhsHIHTe8Bod5c>6QtT>$XgUBz z6MK`kO$=jmt@FqggOhJ5j~e@ygRbG;<{Vu)*+nn9aQeo0;$#j;|MS=S$&L?BeV25z xs3B`@=#`5TF{^6(A1rvdY@|-RtQ|iS5{tyX+wH?;n8E)G$kykv-D^wh{{!TZT%7;_ literal 0 HcmV?d00001 diff --git a/UnitsNet.TestApps.Uwp.WinJS/images/Square44x44Logo.targetsize-24_altform-unplated.png b/UnitsNet.TestApps.Uwp.WinJS/images/Square44x44Logo.targetsize-24_altform-unplated.png new file mode 100644 index 0000000000000000000000000000000000000000..f6c02ce97e0a802b85f6021e822c89f8bf57d5cd GIT binary patch literal 1255 zcmaJ>TWs4@7*5+{G#S+&C!qC#> zf>5N3P6jO*Cz>ug*(_DmW=)kea&m$gZ^+nyiF`;j%w@}y8)>p*SH}C`m?DXeieF2U zyQHecc_L%Gh!7GMt+hG06y;+|p4>m~}PjA}rKViGiEnn7G0ZO<>G|7q;2?NwGCM3s?eued6%hd$B+ z*kQJ{#~$S=DFE(%=E+UkmlEI*%3llUf~8Ja9YU1Vui0IbGBkW_gHB%Rd&!!ioX zs40O?i9I{};kle7GMvE7(rk`la=gTI)47=>%?q@^iL-nUo3}h4S}N-KHn8t5mVP8w z&bSErwp+37 zNJJ8?a|{r5Q3R0Z5s-LB1WHOwYC@7pCHWND#cL1cZ?{kJ368_*(UDWUDyb<}0y@o# zfMF016iMWPCb6obAxT$JlB6(2DrlXDTB&!0`!m??4F(qWMhjVZo?JXQmz`1*58Z=& zcDmB|S-E@j?BoFGix0flckqdS4jsPNzhfWyWIM98GxcLs89C(~dw%$_t;JjX-SD}E zfiGV;{8Q%8r}w9x>EEigW81>`kvnU@pK)4+xk9@+bNj9L!AAZ@SZ@q|)&BmY3+HZx zul~BeG4|}-;L%cHViQGQX?^zFfO0&#cHwel=d`lH9sJ-@Sl@n*(8J2>%Ac`IxyY?Q z{=GhWvC#gu-~Ia7*n{=+;qM?Ul_wy1+u7ho;=`>EwP^g~R@{unBds`!#@}tluZQpS zm)M~nYEifJWJGx?_6DcTy>#uh%>!H9=hb^(v`=m3F1{L>db=<5_tm+_&knAQ2EU$s Mu9UqpbNZeC0BbUo^Z)<= literal 0 HcmV?d00001 diff --git a/UnitsNet.TestApps.Uwp.WinJS/images/StoreLogo.png b/UnitsNet.TestApps.Uwp.WinJS/images/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..7385b56c0e4d3c6b0efe3324aa1194157d837826 GIT binary patch literal 1451 zcmaJ>eN5D57_Z|bH;{0+1#mbl)eTU3{h)Wf7EZV?;HD@XL@{B`Ui%(2aMxQ~xdXSv z5nzWi(LW)U2=Vc-cY@s7nPt{i0hc6!7xN4NNHI#EQl>YNBy8l4%x9gr_W-j zEZMQmmTIy(>;lblRfh`dIyTgc9W5d!VP$L4(kKrN1c5G~(O_#xG zAJCNTstD^5SeXFB+&$h=ToJP2H>xr$iqPs-#O*;4(!Fjw25-!gEb*)mU}=)J;Iu>w zxK(5XoD0wrPSKQ~rbL^Cw6O_03*l*}i=ydbu7adJ6y;%@tjFeXIXT+ms30pmbOP%Q zX}S;+LBh8Tea~TSkHzvX6$rYb)+n&{kSbIqh|c7hmlxmwSiq5iVhU#iEQ<>a18|O^Sln-8t&+t`*{qBWo5M?wFM(JuimAOb5!K#D}XbslM@#1ZVz_;!9U zpfEpLAOz=0g@bd6Xj_ILi-x^!M}73h^o@}hM$1jflTs|Yuj9AL@A3<-?MV4!^4q`e z)fO@A;{9K^?W?DbnesnPr6kK>$zaKo&;FhFd(GYFCIU^T+OIMb%Tqo+P%oq(IdX7S zf6+HLO?7o0m+p>~Tp5UrXWh!UH!wZ5kv!E`_w)PTpI(#Iw{AS`gH4^b(bm^ZCq^FZ zY9DD7bH}rq9mg88+KgA$Zp!iWncuU2n1AuIa@=sWvUR-s`Qb{R*kk(SPU^`$6BXz8 zn#7yaFOIK%qGxyi`dYtm#&qqox0$h=pNi#u=M8zUG@bpiZ=3sT=1}Trr}39cC)H|v zbL?W)=&s4zrh)7>L(|cc%$1#!zfL?HjpeP%T+x_a+jZ16b^iKOHxFEX$7d|8${H-* zIrOJ5w&i$>*D>AKaIoYg`;{L@jM((Kt?$N$5OnuPqVvq**Nm}(f0wwOF%iX_Pba;V z;m@wxX&NcV3?<1+u?A{y_DIj7#m3Af1rCE)o`D&Y3}0%7E;iX1yMDiS)sh0wKi!36 zL!Wmq?P^Ku&rK~HJd97KkLTRl>ScGFYZNlYytWnhmuu|)L&ND8_PmkayQb{HOY640 bno1(wj@u8DCVuFR|31B*4ek@pZJqxCDDe1x literal 0 HcmV?d00001 diff --git a/UnitsNet.TestApps.Uwp.WinJS/images/Wide310x150Logo.scale-200.png b/UnitsNet.TestApps.Uwp.WinJS/images/Wide310x150Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..288995b397fdbef1fb7e85afd71445d5de1952c5 GIT binary patch literal 3204 zcmbVPeQXow8NYmBd90>}0NP?GhXW~VaeThm=a0tV#EwJMI!)6M3}|c4_Bl3=Kd>G0 z(GHx1wl<7(tP?FsOQkTilSo*iIvF%uArExJ73~P zSv1xEy!U(Wd4A9D`FQV@W3@F^qJ@PEF$@z`Z!*BbFsS(^?B zyiAzJ+q})bkgiQHWqEb*jJD-coHYr1^iocg)l!Qa{Xqs-l~6J}p-|##ZHYofskQ3$ zI0;xzXyhazBeXhIsg5A=%ufo@f)1yy&ScKS0;HF^!r_2UE^lpZEom(+@duma3awTv zCrCL-%D_SvYWIcdHkmI}#50(fkUi)Qgx!80ju>g1za^}ff>JI8Z@^-iCiaCgg@TgF z+vtE?Q9{VQUX&MW9SYYmGcxA14%N2@7FwBTD4N<(2{nWgV8$e3?-F=L^&FrtWn~(U_Q~~^uYiyeY6-KoTnfh9AWz@ zIKje0)u!_Lw)E}G!#kEfwKVdNt(UAf9*f>tEL_(=xco-T%jTi@7YlC3hs2ik%Le0H ztj}RTeCF(5mwvi3_56>-yB?l;J>-1%!9~=fs|QcNG3J~a@JCu`4SB460s0ZO+##4fFUSGLcj_ja^fL4&BKALfb#$6$O?>P@qx2Agl^x0i&ugt zsy5Pyu=()`7HRMG3IB7F1@`_ z+-!J%#i6e^U$e#+C%Q>_qVRzWRsG^W_n+@OcX@vzI&z;mzHNb!GQ?LWA(wtpqHqTM z1OFw_{Zn?fD)p)`c`kOgv{de=v@suGRqY{N^U7gI1VF3*F=obwaXI6ob5__Yn zVTguS!%(NI09J8x#AO_aW!9W7k*UvB;IWDFC3srwftr{kHj%g)fvnAm;&h_dnl~

MY- zf+K}sCe8qU6Ujs`3ua{U0Of$R_gVQBuUA za0v=mu#vIOqiiAZOr&h*$WyOw&k-xr$;G4Ixa!#TJNr>95(h>l%)PUy4p+^SgR(uR zta%k*?ny-+nAr8spEk1fo{J4i!b^Fia`N{_F6@zidA2ZTTrjl#^5Z-2KfB@Cu}l9s z(*|Z2jc?p~vn2f)3y9i*7zJV1L{$?|&q)4oaT;uXi6>1GkRXVTOzAz(RHEmr=eFIi z`}<>-Q?K0GN8!IYxeP1XKXO+jsJbp~o^);Bc;%b7Flpe7;1`Ny@3r7ZR;?R)aJt8C ziNlEC<@3f_lIV4TwV}&e;D!Ee5_|e#g0LUh=5vmYWYm7&2h*M>QPKvGh9-)wfMMW3 z8J9b%1k7dzPzO0_NGQy92BZ^FR6R~6;^6?lqO;-QUP4BY%cG%3vEhbm#>4vIhPBh3 z-+pZGjh$x%Hp{?=FHsMp0&wNPlj00us{&`1ZOZTqs8%4X&xH=UDr*xyBW(Zp&Em94 zf)ZSfn#yg0N)>!1kWdkqJ^S*z0FF5|fj&qcE#Na|%OY0$uO>!&hP+1ywfD_WXk@4J(?MBftK7>$Nvqh@tDuarN%PrTLQ2Uzysx>UV=V zk^RrDSvdQ?0;=hY67EgII-f4`t=+i*yS=Y~!XlqIy_4x&%+OdfbKOFPXS2X5%4R{N z$SQMX^AK6(fA + + + + UnitsNet.TestApps.Uwp.WinJS + + + + + + + + + + +

+

Content goes here

+
+ + diff --git a/UnitsNet.TestApps.Uwp.WinJS/js/main.js b/UnitsNet.TestApps.Uwp.WinJS/js/main.js new file mode 100644 index 0000000000..abffc0200e --- /dev/null +++ b/UnitsNet.TestApps.Uwp.WinJS/js/main.js @@ -0,0 +1,27 @@ +(function() { + 'use strict'; + var app = WinJS.Application; + var activation = Windows.ApplicationModel.Activation; + app.onactivated = function (args) { + if (args.detail.kind === activation.ActivationKind.launch) { + if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) { + // TODO: This application has been newly launched. Initialize your application here. + var t = UnitsNet.Temperature.fromDegreesCelsius(100); + var unit = UnitsNet.Units.TemperatureUnit; + document.getElementById('label').innerHTML = t.toString(unit.degreeCelsius) + ' = ' + t.toString(unit.degreeFahrenheit) + ' = ' + t.toString(unit.kelvin); + } else { + // TODO: This application has been reactivated from suspension. + // Restore application state here. + } + args.setPromise(WinJS.UI.processAll().then(function() { + // TODO: Your code here. + })); + } + }; + app.oncheckpoint = function (args) { + // TODO: This application is about to be suspended. Save any state that needs to persist across suspensions here. + // You might use the WinJS.Application.sessionState object, which is automatically saved and restored across suspension. + // If you need to complete an asynchronous operation before your application is suspended, call args.setPromise(). + }; + app.start(); +}()); diff --git a/UnitsNet.TestApps.Uwp.WinJS/lib/winjs-4.0.1/css/ui-dark.css b/UnitsNet.TestApps.Uwp.WinJS/lib/winjs-4.0.1/css/ui-dark.css new file mode 100644 index 0000000000..991c9316d3 --- /dev/null +++ b/UnitsNet.TestApps.Uwp.WinJS/lib/winjs-4.0.1/css/ui-dark.css @@ -0,0 +1,7304 @@ +/* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. */ +@keyframes WinJS-node-inserted { + from { + outline-color: #000; + } + to { + outline-color: #001; + } +} +@keyframes WinJS-opacity-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} +@keyframes WinJS-opacity-out { + from { + opacity: 1; + } + to { + opacity: 0; + } +} +@keyframes WinJS-scale-up { + from { + transform: scale(0.85); + } + to { + transform: scale(1); + } +} +@keyframes WinJS-scale-down { + from { + transform: scale(1); + } + to { + transform: scale(0.85); + } +} +@keyframes WinJS-default-remove { + from { + transform: translateX(11px); + } + to { + transform: none; + } +} +@keyframes WinJS-default-remove-rtl { + from { + transform: translateX(-11px); + } + to { + transform: none; + } +} +@keyframes WinJS-default-apply { + from { + transform: none; + } + to { + transform: translateX(11px); + } +} +@keyframes WinJS-default-apply-rtl { + from { + transform: none; + } + to { + transform: translateX(-11px); + } +} +@keyframes WinJS-showEdgeUI { + from { + transform: translateY(-70px); + } + to { + transform: none; + } +} +@keyframes WinJS-showPanel { + from { + transform: translateX(364px); + } + to { + transform: none; + } +} +@keyframes WinJS-showPanel-rtl { + from { + transform: translateX(-364px); + } + to { + transform: none; + } +} +@keyframes WinJS-hideEdgeUI { + from { + transform: none; + } + to { + transform: translateY(-70px); + } +} +@keyframes WinJS-hidePanel { + from { + transform: none; + } + to { + transform: translateX(364px); + } +} +@keyframes WinJS-hidePanel-rtl { + from { + transform: none; + } + to { + transform: translateX(-364px); + } +} +@keyframes WinJS-showPopup { + from { + transform: translateY(50px); + } + to { + transform: none; + } +} +@keyframes WinJS-dragSourceEnd { + from { + transform: translateX(11px) scale(1.05); + } + to { + transform: none; + } +} +@keyframes WinJS-dragSourceEnd-rtl { + from { + transform: translateX(-11px) scale(1.05); + } + to { + transform: none; + } +} +@keyframes WinJS-enterContent { + from { + transform: translateY(28px); + } + to { + transform: none; + } +} +@keyframes WinJS-exit { + from { + transform: none; + } + to { + transform: none; + } +} +@keyframes WinJS-enterPage { + from { + transform: translateY(28px); + } + to { + transform: none; + } +} +@keyframes WinJS-updateBadge { + from { + transform: translateY(24px); + } + to { + transform: none; + } +} +@-webkit-keyframes WinJS-node-inserted { + from { + outline-color: #000; + } + to { + outline-color: #001; + } +} +@-webkit-keyframes -webkit-WinJS-opacity-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} +@-webkit-keyframes -webkit-WinJS-opacity-out { + from { + opacity: 1; + } + to { + opacity: 0; + } +} +@-webkit-keyframes -webkit-WinJS-scale-up { + from { + -webkit-transform: scale(0.85); + } + to { + -webkit-transform: scale(1); + } +} +@-webkit-keyframes -webkit-WinJS-scale-down { + from { + -webkit-transform: scale(1); + } + to { + -webkit-transform: scale(0.85); + } +} +@-webkit-keyframes -webkit-WinJS-default-remove { + from { + -webkit-transform: translateX(11px); + } + to { + -webkit-transform: none; + } +} +@-webkit-keyframes -webkit-WinJS-default-remove-rtl { + from { + -webkit-transform: translateX(-11px); + } + to { + -webkit-transform: none; + } +} +@-webkit-keyframes -webkit-WinJS-default-apply { + from { + -webkit-transform: none; + } + to { + -webkit-transform: translateX(11px); + } +} +@-webkit-keyframes -webkit-WinJS-default-apply-rtl { + from { + -webkit-transform: none; + } + to { + -webkit-transform: translateX(-11px); + } +} +@-webkit-keyframes -webkit-WinJS-showEdgeUI { + from { + -webkit-transform: translateY(-70px); + } + to { + -webkit-transform: none; + } +} +@-webkit-keyframes -webkit-WinJS-showPanel { + from { + -webkit-transform: translateX(364px); + } + to { + -webkit-transform: none; + } +} +@-webkit-keyframes -webkit-WinJS-showPanel-rtl { + from { + -webkit-transform: translateX(-364px); + } + to { + -webkit-transform: none; + } +} +@-webkit-keyframes -webkit-WinJS-hideEdgeUI { + from { + -webkit-transform: none; + } + to { + -webkit-transform: translateY(-70px); + } +} +@-webkit-keyframes -webkit-WinJS-hidePanel { + from { + -webkit-transform: none; + } + to { + -webkit-transform: translateX(364px); + } +} +@-webkit-keyframes -webkit-WinJS-hidePanel-rtl { + from { + -webkit-transform: none; + } + to { + -webkit-transform: translateX(-364px); + } +} +@-webkit-keyframes -webkit-WinJS-showPopup { + from { + -webkit-transform: translateY(50px); + } + to { + -webkit-transform: none; + } +} +@-webkit-keyframes -webkit-WinJS-dragSourceEnd { + from { + -webkit-transform: translateX(11px) scale(1.05); + } + to { + -webkit-transform: none; + } +} +@-webkit-keyframes -webkit-WinJS-dragSourceEnd-rtl { + from { + -webkit-transform: translateX(-11px) scale(1.05); + } + to { + -webkit-transform: none; + } +} +@-webkit-keyframes -webkit-WinJS-enterContent { + from { + -webkit-transform: translateY(28px); + } + to { + -webkit-transform: none; + } +} +@-webkit-keyframes -webkit-WinJS-exit { + from { + -webkit-transform: none; + } + to { + -webkit-transform: none; + } +} +@-webkit-keyframes -webkit-WinJS-enterPage { + from { + -webkit-transform: translateY(28px); + } + to { + -webkit-transform: none; + } +} +@-webkit-keyframes -webkit-WinJS-updateBadge { + from { + -webkit-transform: translateY(24px); + } + to { + -webkit-transform: none; + } +} +@font-face { + font-family: "Segoe UI Command"; + src: local("Segoe MDL2 Assets"); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: "Symbols"; + src: url(../fonts/Symbols.ttf); +} +.win-type-header, +.win-h1 { + font-size: 46px; + font-weight: 200; + line-height: 1.216; + letter-spacing: 0px; +} +.win-type-subheader, +.win-h2 { + font-size: 34px; + font-weight: 200; + line-height: 1.176; +} +.win-type-title, +.win-h3 { + font-size: 24px; + font-weight: 300; + line-height: 1.167; +} +.win-type-subtitle, +.win-h4 { + font-size: 20px; + font-weight: 400; + line-height: 1.2; +} +.win-type-body, +.win-h6 { + font-size: 15px; + font-weight: 400; + line-height: 1.333; +} +.win-type-base, +.win-h5 { + font-size: 15px; + font-weight: 500; + line-height: 1.333; +} +.win-type-caption { + font-size: 12px; + font-weight: 400; + line-height: 1.167; +} +@font-face { + font-family: "Segoe UI"; + font-weight: 200; + src: local("Segoe UI Light"); +} +@font-face { + font-family: "Segoe UI"; + font-weight: 300; + src: local("Segoe UI Semilight"); +} +@font-face { + font-family: "Segoe UI"; + font-weight: 400; + src: local("Segoe UI"); +} +@font-face { + font-family: "Segoe UI"; + font-weight: 500; + src: local("Segoe UI Semibold"); +} +@font-face { + font-family: "Segoe UI"; + font-weight: 600; + src: local("Segoe UI Bold"); +} +@font-face { + font-family: "Segoe UI"; + font-style: italic; + font-weight: 400; + src: local("Segoe UI Italic"); +} +@font-face { + font-family: "Segoe UI"; + font-style: italic; + font-weight: 700; + src: local("Segoe UI Bold Italic"); +} +@font-face { + font-family: "Microsoft Yahei UI"; + font-weight: 200; + src: local("Microsoft Yahei UI Light"); +} +@font-face { + font-family: "Microsoft Yahei UI"; + font-weight: 300; + src: local("Microsoft Yahei UI"); +} +@font-face { + font-family: "Microsoft Yahei UI"; + font-weight: 500; + src: local("Microsoft Yahei UI"); +} +@font-face { + font-family: "Microsoft Yahei UI"; + font-weight: 600; + src: local("Microsoft Yahei UI Bold"); +} +@font-face { + font-family: "Microsoft JhengHei UI"; + font-weight: 200; + src: local("Microsoft JhengHei UI Light"); +} +@font-face { + font-family: "Microsoft JhengHei UI"; + font-weight: 300; + src: local("Microsoft JhengHei UI"); +} +@font-face { + font-family: "Microsoft JhengHei UI"; + font-weight: 500; + src: local("Microsoft JhengHei UI"); +} +@font-face { + font-family: "Microsoft JhengHei UI"; + font-weight: 600; + src: local("Microsoft JhengHei UI Bold"); +} +.win-type-header:-ms-lang(am, ti), +.win-type-subheader:-ms-lang(am, ti), +.win-type-title:-ms-lang(am, ti), +.win-type-subtitle:-ms-lang(am, ti), +.win-type-base:-ms-lang(am, ti), +.win-type-body:-ms-lang(am, ti), +.win-type-caption:-ms-lang(am, ti), +.win-h1:-ms-lang(am, ti), +.win-h2:-ms-lang(am, ti), +.win-h3:-ms-lang(am, ti), +.win-h4:-ms-lang(am, ti), +.win-h5:-ms-lang(am, ti), +.win-h6:-ms-lang(am, ti), +.win-button:-ms-lang(am, ti), +.win-dropdown:-ms-lang(am, ti), +.win-textbox:-ms-lang(am, ti), +.win-link:-ms-lang(am, ti), +.win-textarea:-ms-lang(am, ti) { + font-family: "Ebrima", "Ebrima", "Nirmala UI", "Gadugi", "Segoe UI Emoji", "Segoe MDL2 Assets", "Symbols", "Yu Gothic UI", "Yu Gothic", "Meiryo UI", "Leelawadee UI", "Microsoft YaHei UI", "Microsoft JhengHei UI", "Malgun Gothic", "Segoe UI Historic", "Estrangelo Edessa", "Microsoft Himalaya", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", "Microsoft Yi Baiti", "Mongolian Baiti", "MV Boli", "Myanmar Text", "Javanese Text", "Cambria Math"; +} +.win-type-header:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-type-subheader:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-type-title:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-type-subtitle:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-type-base:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-type-body:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-type-caption:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-h1:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-h2:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-h3:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-h4:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-h5:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-h6:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-button:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-dropdown:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-textbox:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-link:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te), +.win-textarea:-ms-lang(as, bn, gu, hi, kn, kok, ml, mr, ne, or, pa, sat-Olck, si, srb-Sora, ta, te) { + font-family: "Nirmala UI", "Ebrima", "Nirmala UI", "Gadugi", "Segoe UI Emoji", "Segoe MDL2 Assets", "Symbols", "Yu Gothic UI", "Yu Gothic", "Meiryo UI", "Leelawadee UI", "Microsoft YaHei UI", "Microsoft JhengHei UI", "Malgun Gothic", "Segoe UI Historic", "Estrangelo Edessa", "Microsoft Himalaya", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", "Microsoft Yi Baiti", "Mongolian Baiti", "MV Boli", "Myanmar Text", "Javanese Text", "Cambria Math"; +} +.win-type-header:-ms-lang(chr-CHER-US), +.win-type-subheader:-ms-lang(chr-CHER-US), +.win-type-title:-ms-lang(chr-CHER-US), +.win-type-subtitle:-ms-lang(chr-CHER-US), +.win-type-base:-ms-lang(chr-CHER-US), +.win-type-body:-ms-lang(chr-CHER-US), +.win-type-caption:-ms-lang(chr-CHER-US), +.win-h1:-ms-lang(chr-CHER-US), +.win-h2:-ms-lang(chr-CHER-US), +.win-h3:-ms-lang(chr-CHER-US), +.win-h4:-ms-lang(chr-CHER-US), +.win-h5:-ms-lang(chr-CHER-US), +.win-h6:-ms-lang(chr-CHER-US), +.win-button:-ms-lang(chr-CHER-US), +.win-dropdown:-ms-lang(chr-CHER-US), +.win-textbox:-ms-lang(chr-CHER-US), +.win-link:-ms-lang(chr-CHER-US), +.win-textarea:-ms-lang(chr-CHER-US) { + font-family: "Gadugi", "Ebrima", "Nirmala UI", "Gadugi", "Segoe UI Emoji", "Segoe MDL2 Assets", "Symbols", "Yu Gothic UI", "Yu Gothic", "Meiryo UI", "Leelawadee UI", "Microsoft YaHei UI", "Microsoft JhengHei UI", "Malgun Gothic", "Segoe UI Historic", "Estrangelo Edessa", "Microsoft Himalaya", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", "Microsoft Yi Baiti", "Mongolian Baiti", "MV Boli", "Myanmar Text", "Javanese Text", "Cambria Math"; +} +.win-type-header:-ms-lang(ja), +.win-type-subheader:-ms-lang(ja), +.win-type-title:-ms-lang(ja), +.win-type-subtitle:-ms-lang(ja), +.win-type-base:-ms-lang(ja), +.win-type-body:-ms-lang(ja), +.win-type-caption:-ms-lang(ja), +.win-h1:-ms-lang(ja), +.win-h2:-ms-lang(ja), +.win-h3:-ms-lang(ja), +.win-h4:-ms-lang(ja), +.win-h5:-ms-lang(ja), +.win-h6:-ms-lang(ja), +.win-button:-ms-lang(ja), +.win-dropdown:-ms-lang(ja), +.win-textbox:-ms-lang(ja), +.win-link:-ms-lang(ja), +.win-textarea:-ms-lang(ja) { + font-family: "Yu Gothic UI", "Ebrima", "Nirmala UI", "Gadugi", "Segoe UI Emoji", "Segoe MDL2 Assets", "Symbols", "Yu Gothic UI", "Yu Gothic", "Meiryo UI", "Leelawadee UI", "Microsoft YaHei UI", "Microsoft JhengHei UI", "Malgun Gothic", "Segoe UI Historic", "Estrangelo Edessa", "Microsoft Himalaya", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", "Microsoft Yi Baiti", "Mongolian Baiti", "MV Boli", "Myanmar Text", "Javanese Text", "Cambria Math"; +} +.win-type-header:-ms-lang(km, lo, th, bug-Bugi), +.win-type-subheader:-ms-lang(km, lo, th, bug-Bugi), +.win-type-title:-ms-lang(km, lo, th, bug-Bugi), +.win-type-subtitle:-ms-lang(km, lo, th, bug-Bugi), +.win-type-base:-ms-lang(km, lo, th, bug-Bugi), +.win-type-body:-ms-lang(km, lo, th, bug-Bugi), +.win-type-caption:-ms-lang(km, lo, th, bug-Bugi), +.win-h1:-ms-lang(km, lo, th, bug-Bugi), +.win-h2:-ms-lang(km, lo, th, bug-Bugi), +.win-h3:-ms-lang(km, lo, th, bug-Bugi), +.win-h4:-ms-lang(km, lo, th, bug-Bugi), +.win-h5:-ms-lang(km, lo, th, bug-Bugi), +.win-h6:-ms-lang(km, lo, th, bug-Bugi), +.win-button:-ms-lang(km, lo, th, bug-Bugi), +.win-dropdown:-ms-lang(km, lo, th, bug-Bugi), +.win-textbox:-ms-lang(km, lo, th, bug-Bugi), +.win-link:-ms-lang(km, lo, th, bug-Bugi), +.win-textarea:-ms-lang(km, lo, th, bug-Bugi) { + font-family: "Leelawadee UI", "Ebrima", "Nirmala UI", "Gadugi", "Segoe UI Emoji", "Segoe MDL2 Assets", "Symbols", "Yu Gothic UI", "Yu Gothic", "Meiryo UI", "Leelawadee UI", "Microsoft YaHei UI", "Microsoft JhengHei UI", "Malgun Gothic", "Segoe UI Historic", "Estrangelo Edessa", "Microsoft Himalaya", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", "Microsoft Yi Baiti", "Mongolian Baiti", "MV Boli", "Myanmar Text", "Javanese Text", "Cambria Math"; +} +.win-type-header:-ms-lang(ko), +.win-type-subheader:-ms-lang(ko), +.win-type-title:-ms-lang(ko), +.win-type-subtitle:-ms-lang(ko), +.win-type-base:-ms-lang(ko), +.win-type-body:-ms-lang(ko), +.win-type-caption:-ms-lang(ko), +.win-h1:-ms-lang(ko), +.win-h2:-ms-lang(ko), +.win-h3:-ms-lang(ko), +.win-h4:-ms-lang(ko), +.win-h5:-ms-lang(ko), +.win-h6:-ms-lang(ko), +.win-button:-ms-lang(ko), +.win-dropdown:-ms-lang(ko), +.win-textbox:-ms-lang(ko), +.win-link:-ms-lang(ko), +.win-textarea:-ms-lang(ko) { + font-family: "Malgun Gothic", "Ebrima", "Nirmala UI", "Gadugi", "Segoe UI Emoji", "Segoe MDL2 Assets", "Symbols", "Yu Gothic UI", "Yu Gothic", "Meiryo UI", "Leelawadee UI", "Microsoft YaHei UI", "Microsoft JhengHei UI", "Malgun Gothic", "Segoe UI Historic", "Estrangelo Edessa", "Microsoft Himalaya", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", "Microsoft Yi Baiti", "Mongolian Baiti", "MV Boli", "Myanmar Text", "Javanese Text", "Cambria Math"; +} +.win-type-header:-ms-lang(jv-Java), +.win-type-subheader:-ms-lang(jv-Java), +.win-type-title:-ms-lang(jv-Java), +.win-type-subtitle:-ms-lang(jv-Java), +.win-type-base:-ms-lang(jv-Java), +.win-type-body:-ms-lang(jv-Java), +.win-type-caption:-ms-lang(jv-Java), +.win-h1:-ms-lang(jv-Java), +.win-h2:-ms-lang(jv-Java), +.win-h3:-ms-lang(jv-Java), +.win-h4:-ms-lang(jv-Java), +.win-h5:-ms-lang(jv-Java), +.win-h6:-ms-lang(jv-Java), +.win-button:-ms-lang(jv-Java), +.win-dropdown:-ms-lang(jv-Java), +.win-textbox:-ms-lang(jv-Java), +.win-link:-ms-lang(jv-Java), +.win-textarea:-ms-lang(jv-Java) { + font-family: "Javanese Text", "Ebrima", "Nirmala UI", "Gadugi", "Segoe UI Emoji", "Segoe MDL2 Assets", "Symbols", "Yu Gothic UI", "Yu Gothic", "Meiryo UI", "Leelawadee UI", "Microsoft YaHei UI", "Microsoft JhengHei UI", "Malgun Gothic", "Segoe UI Historic", "Estrangelo Edessa", "Microsoft Himalaya", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", "Microsoft Yi Baiti", "Mongolian Baiti", "MV Boli", "Myanmar Text", "Javanese Text", "Cambria Math"; +} +.win-type-header:-ms-lang(cop-Copt), +.win-type-subheader:-ms-lang(cop-Copt), +.win-type-title:-ms-lang(cop-Copt), +.win-type-subtitle:-ms-lang(cop-Copt), +.win-type-base:-ms-lang(cop-Copt), +.win-type-body:-ms-lang(cop-Copt), +.win-type-caption:-ms-lang(cop-Copt), +.win-h1:-ms-lang(cop-Copt), +.win-h2:-ms-lang(cop-Copt), +.win-h3:-ms-lang(cop-Copt), +.win-h4:-ms-lang(cop-Copt), +.win-h5:-ms-lang(cop-Copt), +.win-h6:-ms-lang(cop-Copt), +.win-button:-ms-lang(cop-Copt), +.win-dropdown:-ms-lang(cop-Copt), +.win-textbox:-ms-lang(cop-Copt), +.win-link:-ms-lang(cop-Copt), +.win-textarea:-ms-lang(cop-Copt) { + font-family: "Segoe MDL2 Assets", "Ebrima", "Nirmala UI", "Gadugi", "Segoe UI Emoji", "Segoe MDL2 Assets", "Symbols", "Yu Gothic UI", "Yu Gothic", "Meiryo UI", "Leelawadee UI", "Microsoft YaHei UI", "Microsoft JhengHei UI", "Malgun Gothic", "Segoe UI Historic", "Estrangelo Edessa", "Microsoft Himalaya", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", "Microsoft Yi Baiti", "Mongolian Baiti", "MV Boli", "Myanmar Text", "Javanese Text", "Cambria Math"; +} +.win-type-header:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-type-subheader:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-type-title:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-type-subtitle:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-type-base:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-type-body:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-type-caption:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-h1:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-h2:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-h3:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-h4:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-h5:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-h6:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-button:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-dropdown:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-textbox:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-link:-ms-lang(zh-CN, zh-Hans, zh-SG), +.win-textarea:-ms-lang(zh-CN, zh-Hans, zh-SG) { + font-family: "Microsoft YaHei UI", "Ebrima", "Nirmala UI", "Gadugi", "Segoe UI Emoji", "Segoe MDL2 Assets", "Symbols", "Yu Gothic UI", "Yu Gothic", "Meiryo UI", "Leelawadee UI", "Microsoft YaHei UI", "Microsoft JhengHei UI", "Malgun Gothic", "Segoe UI Historic", "Estrangelo Edessa", "Microsoft Himalaya", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", "Microsoft Yi Baiti", "Mongolian Baiti", "MV Boli", "Myanmar Text", "Javanese Text", "Cambria Math"; +} +.win-type-header:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-type-subheader:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-type-title:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-type-subtitle:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-type-base:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-type-body:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-type-caption:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-h1:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-h2:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-h3:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-h4:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-h5:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-h6:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-button:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-dropdown:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-textbox:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-link:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO), +.win-textarea:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO) { + font-family: "Microsoft JhengHei UI", "Ebrima", "Nirmala UI", "Gadugi", "Segoe UI Emoji", "Segoe MDL2 Assets", "Symbols", "Yu Gothic UI", "Yu Gothic", "Meiryo UI", "Leelawadee UI", "Microsoft YaHei UI", "Microsoft JhengHei UI", "Malgun Gothic", "Segoe UI Historic", "Estrangelo Edessa", "Microsoft Himalaya", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", "Microsoft Yi Baiti", "Mongolian Baiti", "MV Boli", "Myanmar Text", "Javanese Text", "Cambria Math"; +} +html, +body { + width: 100%; + height: 100%; + margin: 0px; + cursor: default; + -webkit-touch-callout: none; + -ms-scroll-translation: vertical-to-horizontal; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +html { + overflow: hidden; + direction: ltr; +} +html:lang(ar), +html:lang(dv), +html:lang(fa), +html:lang(he), +html:lang(ku-Arab), +html:lang(pa-Arab), +html:lang(prs), +html:lang(ps), +html:lang(sd-Arab), +html:lang(syr), +html:lang(ug), +html:lang(ur), +html:lang(qps-plocm) { + direction: rtl; +} +body { + -ms-content-zooming: none; +} +iframe { + border: 0; +} +.win-type-header, +.win-type-subheader, +.win-type-title, +.win-type-subtitle, +.win-type-base, +.win-type-body, +.win-type-caption, +.win-h1, +.win-h2, +.win-h3, +.win-h4, +.win-h5, +.win-h6, +.win-button, +.win-dropdown, +.win-textbox, +.win-link, +.win-textarea { + font-family: "Segoe UI", sans-serif, "Segoe MDL2 Assets", "Symbols"; +} +.win-textbox, +.win-textarea { + -ms-user-select: element; + border-style: solid; + border-width: 2px; + border-radius: 0; + margin: 8px 0px; + width: 296px; + min-width: 64px; + min-height: 28px; + background-clip: border-box; + box-sizing: border-box; + padding: 3px 6px 5px 10px; + outline: 0; + font-size: 15px; + font-weight: 400; + line-height: 1.333; +} +.win-textbox::-ms-value { + margin: 0; + padding: 0; +} +.win-textbox::-ms-clear, +.win-textbox::-ms-reveal { + padding-right: 2px; + margin-right: -8px; + margin-left: 2px; + margin-top: -8px; + margin-bottom: -8px; + width: 30px; + height: 32px; +} +.win-textbox:lang(ar)::-ms-clear, +.win-textbox:lang(dv)::-ms-clear, +.win-textbox:lang(fa)::-ms-clear, +.win-textbox:lang(he)::-ms-clear, +.win-textbox:lang(ku-Arab)::-ms-clear, +.win-textbox:lang(pa-Arab)::-ms-clear, +.win-textbox:lang(prs)::-ms-clear, +.win-textbox:lang(ps)::-ms-clear, +.win-textbox:lang(sd-Arab)::-ms-clear, +.win-textbox:lang(syr)::-ms-clear, +.win-textbox:lang(ug)::-ms-clear, +.win-textbox:lang(ur)::-ms-clear, +.win-textbox:lang(qps-plocm)::-ms-clear, +.win-textbox:lang(ar)::-ms-reveal, +.win-textbox:lang(dv)::-ms-reveal, +.win-textbox:lang(fa)::-ms-reveal, +.win-textbox:lang(he)::-ms-reveal, +.win-textbox:lang(ku-Arab)::-ms-reveal, +.win-textbox:lang(pa-Arab)::-ms-reveal, +.win-textbox:lang(prs)::-ms-reveal, +.win-textbox:lang(ps)::-ms-reveal, +.win-textbox:lang(sd-Arab)::-ms-reveal, +.win-textbox:lang(syr)::-ms-reveal, +.win-textbox:lang(ug)::-ms-reveal, +.win-textbox:lang(ur)::-ms-reveal, +.win-textbox:lang(qps-plocm)::-ms-reveal { + margin-left: -8px; + margin-right: 2px; +} +.win-textarea { + resize: none; + overflow-y: auto; +} +.win-radio, +.win-checkbox { + width: 20px; + height: 20px; + margin-right: 8px; + margin-top: 12px; + margin-bottom: 12px; +} +.win-radio:lang(ar), +.win-checkbox:lang(ar), +.win-radio:lang(dv), +.win-checkbox:lang(dv), +.win-radio:lang(fa), +.win-checkbox:lang(fa), +.win-radio:lang(he), +.win-checkbox:lang(he), +.win-radio:lang(ku-Arab), +.win-checkbox:lang(ku-Arab), +.win-radio:lang(pa-Arab), +.win-checkbox:lang(pa-Arab), +.win-radio:lang(prs), +.win-checkbox:lang(prs), +.win-radio:lang(ps), +.win-checkbox:lang(ps), +.win-radio:lang(sd-Arab), +.win-checkbox:lang(sd-Arab), +.win-radio:lang(syr), +.win-checkbox:lang(syr), +.win-radio:lang(ug), +.win-checkbox:lang(ug), +.win-radio:lang(ur), +.win-checkbox:lang(ur), +.win-radio:lang(qps-plocm), +.win-checkbox:lang(qps-plocm) { + margin-left: 8px; + margin-right: 0px; +} +.win-radio::-ms-check, +.win-checkbox::-ms-check { + border-style: solid; + display: inline-block; + border-width: 2px; + background-clip: border-box; +} +.win-button { + border-style: solid; + margin: 0px; + min-height: 32px; + min-width: 120px; + padding: 4px 8px; + border-width: 2px; + background-clip: border-box; + border-radius: 0; + touch-action: manipulation; + -webkit-appearance: none; + font-size: 15px; + font-weight: 400; + line-height: 1.333; +} +.win-button.win-button-file { + border: none; + min-width: 100px; + min-height: 20px; + width: 340px; + height: 32px; + padding: 0px; + margin: 7px 8px 21px 8px; + background-clip: padding-box; +} +.win-button.win-button-file::-ms-value { + margin: 0; + border-width: 2px; + border-style: solid; + border-right-style: none; + border-radius: 0; + background-clip: border-box; + font-size: 15px; + font-weight: 400; + line-height: 1.333; +} +.win-button.win-button-file:lang(ar)::-ms-value, +.win-button.win-button-file:lang(dv)::-ms-value, +.win-button.win-button-file:lang(fa)::-ms-value, +.win-button.win-button-file:lang(he)::-ms-value, +.win-button.win-button-file:lang(ku-Arab)::-ms-value, +.win-button.win-button-file:lang(pa-Arab)::-ms-value, +.win-button.win-button-file:lang(prs)::-ms-value, +.win-button.win-button-file:lang(ps)::-ms-value, +.win-button.win-button-file:lang(sd-Arab)::-ms-value, +.win-button.win-button-file:lang(syr)::-ms-value, +.win-button.win-button-file:lang(ug)::-ms-value, +.win-button.win-button-file:lang(ur)::-ms-value, +.win-button.win-button-file:lang(qps-plocm)::-ms-value { + border-left-style: none; + border-right-style: solid; +} +.win-button.win-button-file::-ms-browse { + margin: 0; + padding: 0 18px; + border-width: 2px; + border-style: solid; + background-clip: padding-box; + font-size: 15px; + font-weight: 400; + line-height: 1.333; +} +.win-dropdown { + min-width: 56px; + max-width: 368px; + min-height: 32px; + margin: 8px 0; + border-style: solid; + border-width: 2px; + background-clip: border-box; + background-image: none; + box-sizing: border-box; + border-radius: 0; + font-size: 15px; + font-weight: 400; + line-height: 1.333; +} +.win-dropdown::-ms-value { + padding: 5px 12px 7px 12px; + margin: 0; +} +.win-dropdown::-ms-expand { + border: none; + margin-right: 5px; + margin-left: 3px; + margin-bottom: -2px; + font-size: 20px; +} +select[multiple].win-dropdown { + padding: 0 0 0 12px; + vertical-align: bottom; +} +.win-dropdown option { + font-size: 15px; + font-weight: 400; + line-height: 1.333; +} +.win-progress-bar, +.win-progress-ring, +.win-ring { + width: 180px; + height: 4px; + -webkit-appearance: none; +} +.win-progress-bar:not(:indeterminate), +.win-progress-ring:not(:indeterminate), +.win-ring:not(:indeterminate) { + border-style: none; +} +.win-progress-bar::-ms-fill, +.win-progress-ring::-ms-fill, +.win-ring::-ms-fill { + border-style: none; +} +.win-progress-bar.win-medium, +.win-progress-ring.win-medium, +.win-ring.win-medium { + width: 296px; +} +.win-progress-bar.win-large, +.win-progress-ring.win-large, +.win-ring.win-large { + width: 100%; +} +.win-progress-bar:indeterminate::-webkit-progress-value, +.win-progress-ring:indeterminate::-webkit-progress-value, +.win-ring:indeterminate::-webkit-progress-value { + position: relative; + -webkit-animation: win-progress-indeterminate 3s linear infinite; +} +.win-progress-bar.win-paused:not(:indeterminate), +.win-progress-ring.win-paused:not(:indeterminate), +.win-ring.win-paused:not(:indeterminate) { + animation-name: win-progress-fade-out; + animation-duration: 3s; + animation-timing-function: cubic-bezier(0.03, 0.76, 0.31, 1); + opacity: 0.5; +} +.win-progress-bar.win-error::-ms-fill, +.win-progress-ring.win-error::-ms-fill, +.win-ring.win-error::-ms-fill { + opacity: 0; +} +.win-progress-ring, +.win-ring { + width: 20px; + height: 20px; +} +.win-progress-ring:indeterminate::-ms-fill, +.win-ring:indeterminate::-ms-fill { + animation-name: -ms-ring; +} +.win-progress-ring.win-medium, +.win-ring.win-medium { + width: 40px; + height: 40px; +} +.win-progress-ring.win-large, +.win-ring.win-large { + width: 60px; + height: 60px; +} +@-webkit-keyframes win-progress-indeterminate { + 0% { + left: 0; + width: 25%; + } + 50% { + left: calc(75%); + width: 25%; + } + 75% { + left: calc(100%); + width: 0%; + } + 75.1% { + left: 0; + width: 0%; + } + 100% { + left: 0; + width: 25%; + } +} +@keyframes win-progress-fade-out { + from { + opacity: 1.0; + } + to { + opacity: 0.5; + } +} +.win-slider { + -webkit-appearance: none; + width: 280px; + height: 22px; + padding-top: 17px; + padding-bottom: 32px; +} +.win-slider::-ms-track { + height: 2px; + border-style: none; +} +.win-slider::-webkit-slider-runnable-track { + height: 2px; + border-style: none; +} +.win-slider::-moz-range-track { + height: 2px; + border-style: none; +} +.win-slider::-ms-thumb { + width: 24px; + height: 8px; + border-radius: 4px; + border-style: none; +} +.win-slider::-webkit-slider-thumb { + -webkit-appearance: none; + margin-top: -4px; + width: 24px; + height: 8px; + border-radius: 4px; + border-style: none; +} +.win-slider::-moz-range-thumb { + width: 24px; + height: 8px; + border-radius: 4px; + border-style: none; +} +.win-slider.win-vertical { + writing-mode: bt-lr; + width: 22px; + height: 280px; +} +.win-slider.win-vertical::-ms-track { + width: 2px; + height: auto; +} +.win-slider.win-vertical::-ms-thumb { + width: 8px; + height: 24px; +} +.win-slider.win-vertical:lang(ar), +.win-slider.win-vertical:lang(dv), +.win-slider.win-vertical:lang(fa), +.win-slider.win-vertical:lang(he), +.win-slider.win-vertical:lang(ku-Arab), +.win-slider.win-vertical:lang(pa-Arab), +.win-slider.win-vertical:lang(prs), +.win-slider.win-vertical:lang(ps), +.win-slider.win-vertical:lang(sd-Arab), +.win-slider.win-vertical:lang(syr), +.win-slider.win-vertical:lang(ug), +.win-slider.win-vertical:lang(ur), +.win-slider.win-vertical:lang(qps-plocm) { + writing-mode: bt-rl; +} +.win-link { + text-decoration: underline; + cursor: pointer; + touch-action: manipulation; +} +.win-code { + font-family: "Consolas", "Menlo", "Monaco", "Courier New", monospace; + font-size: 15px; + font-weight: 400; + line-height: 1.333; +} +.win-type-ellipsis { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +h1.win-type-ellipsis, +.win-type-header.win-type-ellipsis, +.win-h1.win-type-ellipsis { + line-height: 1.4286; +} +h2.win-type-ellipsis, +.win-type-subheader.win-type-ellipsis, +.win-h2.win-type-ellipsis { + line-height: 1.5; +} +.win-scrollview { + overflow-x: auto; + overflow-y: hidden; + height: 400px; + width: 100%; +} +h1.win-type-header, +h2.win-type-subheader, +h3.win-type-title, +h4.win-type-subtitle, +h5.win-type-base, +h6.win-type-body, +h1.win-h1, +h2.win-h2, +h3.win-h3, +h4.win-h4, +h5.win-h5, +h6.win-h6 { + margin-top: 0px; + margin-bottom: 0px; +} +.win-type-body p, +p.win-type-body { + font-weight: 300; +} +.win-listview { + overflow: hidden; + height: 400px; +} +.win-listview .win-surface { + overflow: visible; +} +.win-listview > .win-viewport.win-horizontal .win-surface { + height: 100%; +} +.win-listview > .win-viewport.win-vertical .win-surface { + width: 100%; +} +.win-listview > .win-viewport { + position: relative; + width: 100%; + height: 100%; + z-index: 0; + -ms-overflow-style: -ms-autohiding-scrollbar; + -webkit-overflow-scrolling: touch; + white-space: nowrap; +} +.win-listview > .win-viewport.win-horizontal { + overflow-x: auto; + overflow-y: hidden; +} +.win-listview > .win-viewport.win-vertical { + overflow-x: hidden; + overflow-y: auto; +} +.win-listview .win-itemscontainer { + overflow: hidden; +} +.win-listview .win-itemscontainer-padder { + width: 0; + height: 0; + margin: 0; + padding: 0; + border: 0; + overflow: hidden; +} +.win-listview > .win-horizontal .win-container { + margin: 10px 5px 0px 5px; +} +.win-listview > .win-vertical .win-container { + margin: 10px 24px 0px 7px; +} +.win-listview.win-rtl > .win-vertical .win-container { + margin: 10px 7px 0px 24px; +} +.win-listview .win-container, +.win-listview .win-itembox, +.win-itemcontainer.win-container, +.win-itemcontainer .win-itembox { + cursor: default; + z-index: 0; +} +.win-listview .win-container { + touch-action: pan-x pan-y pinch-zoom; +} +.win-semanticzoom .win-listview > .win-viewport * { + touch-action: auto; +} +.win-semanticzoom .win-listview > .win-viewport.win-zooming-x { + overflow-x: visible; +} +.win-semanticzoom .win-listview > .win-viewport.win-zooming-y { + overflow-y: visible; +} +.win-listview .win-itembox, +.win-itemcontainer .win-itembox { + width: 100%; + height: 100%; +} +.win-listview .win-item, +.win-itemcontainer .win-item { + z-index: 1; +} +.win-listview .win-item, +.win-itemcontainer .win-item { + overflow: hidden; + position: relative; +} +.win-listview > .win-vertical .win-item { + width: 100%; +} +.win-listview .win-item:focus, +.win-itemcontainer .win-item:focus { + outline-style: none; +} +.win-listview .win-focusedoutline, +.win-itemcontainer .win-focusedoutline { + width: calc(100% - 4px); + height: calc(100% - 4px); + left: 2px; + top: 2px; + position: absolute; + z-index: 5; + pointer-events: none; +} +.win-container.win-selected .win-selectionborder { + border-width: 2px; + border-style: solid; +} +html.win-hoverable .win-container.win-selected:hover .win-selectionborder { + border-width: 2px; + border-style: solid; +} +html.win-hoverable .win-listview .win-itembox:hover::before, +html.win-hoverable .win-itemcontainer .win-itembox:hover::before { + position: absolute; + left: 0px; + top: 0px; + content: ""; + width: calc(100% - 4px); + height: calc(100% - 4px); + pointer-events: none; + border-style: solid; + border-width: 2px; + z-index: 3; +} +html.win-hoverable .win-listview.win-selectionstylefilled .win-itembox:hover::before, +html.win-hoverable .win-itemcontainer.win-selectionstylefilled .win-itembox:hover::before, +html.win-hoverable .win-listview .win-itembox.win-selected:hover::before, +html.win-hoverable .win-itemcontainer.win-itembox.win-selected:hover::before, +html.win-hoverable .win-itemcontainer.win-itembox.win-selected:hover::before { + display: none; +} +.win-listview .win-groupheader { + padding: 10px 10px 10px 2px; + overflow: hidden; + outline-width: 0.01px; + outline-style: none; + float: left; + font-size: 34px; + font-weight: 200; + line-height: 1.176; +} +.win-listview .win-groupheadercontainer { + z-index: 1; + touch-action: pan-x pan-y pinch-zoom; + overflow: hidden; +} +.win-listview .win-horizontal .win-headercontainer, +.win-listview .win-horizontal .win-footercontainer { + height: 100%; + display: inline-block; + overflow: hidden; + white-space: normal; +} +.win-listview .win-vertical .win-headercontainer, +.win-listview .win-vertical .win-footercontainer { + width: 100%; + display: block; + overflow: hidden; + white-space: normal; +} +.win-listview .win-groupheader.win-focused { + outline-style: dotted; +} +.win-listview.win-rtl .win-groupheader { + padding-left: 10px; + padding-right: 2px; + float: right; +} +.win-listview.win-groups .win-horizontal .win-groupleader { + margin-left: 70px; +} +.win-listview.win-groups.win-rtl .win-horizontal .win-groupleader { + margin-left: 0; + margin-right: 70px; +} +.win-listview.win-groups .win-vertical .win-listlayout .win-groupleader, +.win-listview.win-groups .win-vertical .win-gridlayout .win-groupleader { + margin-top: 70px; +} +.win-listview.win-groups > .win-vertical .win-surface.win-listlayout, +.win-listview.win-groups > .win-vertical .win-surface.win-gridlayout { + margin-top: -65px; +} +.win-listview.win-groups > .win-horizontal .win-surface { + margin-left: -70px; +} +.win-listview.win-groups.win-rtl > .win-horizontal .win-surface { + margin-left: 0; + margin-right: -70px; +} +.win-listview .win-surface { + -webkit-margin-collapse: separate; + white-space: normal; +} +.win-surface ._win-proxy { + position: relative; + overflow: hidden; + width: 0; + height: 0; + touch-action: none; +} +.win-selectionborder { + position: absolute; + opacity: inherit; + z-index: 2; + pointer-events: none; +} +.win-container.win-selected .win-selectionborder { + top: 0; + left: 0; + right: 0; + bottom: 0; +} +.win-selectionbackground { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 0; +} +.win-selectioncheckmarkbackground { + position: absolute; + top: 2px; + right: 2px; + width: 14px; + height: 11px; + margin: 0; + padding: 0; + border-left-width: 2px; + border-right-width: 2px; + border-top-width: 4px; + border-bottom-width: 3px; + border-style: solid; + z-index: 3; + display: none; +} +.win-listview.win-rtl .win-selectioncheckmarkbackground, +.win-itemcontainer.win-rtl .win-selectioncheckmarkbackground { + left: 2px; + right: auto; +} +.win-selectionmode.win-itemcontainer .win-selectioncheckmarkbackground, +.win-selectionmode.win-itemcontainer.win-selectionmode .win-selectioncheckmark, +.win-selectionmode .win-itemcontainer .win-selectioncheckmarkbackground, +.win-selectionmode .win-itemcontainer.win-selectionmode .win-selectioncheckmark, +.win-listview .win-selectionmode .win-selectioncheckmarkbackground, +.win-listview .win-selectionmode .win-selectioncheckmark { + display: block; +} +.win-selectioncheckmark { + position: absolute; + margin: 0; + padding: 2px; + right: 1px; + top: 1px; + font-family: "Segoe MDL2 Assets", "Symbols"; + font-size: 14px; + z-index: 4; + line-height: 1; + display: none; +} +.win-rtl .win-selectioncheckmark { + right: auto; + left: 0px; +} +.win-selectionstylefilled.win-container, +.win-selectionstylefilled .win-container { + overflow: hidden; +} +.win-selectionmode .win-itemcontainer.win-container .win-itembox::after, +.win-selectionmode.win-itemcontainer.win-container .win-itembox::after, +.win-listview .win-surface.win-selectionmode .win-itembox::after { + content: ""; + position: absolute; + width: 18px; + height: 18px; + pointer-events: none; + right: 2px; + top: 2px; + z-index: 3; +} +.win-rtl .win-selectionmode .win-itemcontainer.win-container .win-itembox::after, +.win-itemcontainer.win-rtl.win-selectionmode.win-container .win-itembox::after, +.win-listview.win-rtl .win-surface.win-selectionmode .win-itembox::after { + right: auto; + left: 2px; +} +.win-listview.win-selectionstylefilled .win-surface.win-selectionmode .win-item { + transition: transform 250ms cubic-bezier(0.17, 0.79, 0.215, 1.0025); + -webkit-transition: -webkit-transform 250ms cubic-bezier(0.17, 0.79, 0.215, 1.0025); + transform: translate(40px, 0px); + -webkit-transform: translate(40px, 0px); +} +.win-listview.win-rtl.win-selectionstylefilled .win-surface.win-selectionmode .win-item { + transition: transform 250ms cubic-bezier(0.17, 0.79, 0.215, 1.0025); + -webkit-transition: -webkit-transform 250ms cubic-bezier(0.17, 0.79, 0.215, 1.0025); + transform: translate(-40px, 0px); + -webkit-transform: translate(-40px, 0px); +} +.win-listview.win-selectionstylefilled .win-surface.win-hidingselectionmode .win-item { + transition: transform 250ms cubic-bezier(0.17, 0.79, 0.215, 1.0025); + -webkit-transition: -webkit-transform 250ms cubic-bezier(0.17, 0.79, 0.215, 1.0025); + transform: none; + -webkit-transform: none; +} +.win-listview.win-rtl.win-selectionstylefilled .win-surface.win-hideselectionmode .win-item { + transition: transform 250ms cubic-bezier(0.17, 0.79, 0.215, 1.0025); + -webkit-transition: -webkit-transform 250ms cubic-bezier(0.17, 0.79, 0.215, 1.0025); + transform: none; + -webkit-transform: none; +} +.win-listview.win-selectionstylefilled .win-surface.win-selectionmode .win-itembox::after { + left: 12px; + right: auto; + top: 50%; + margin-top: -9px; + display: block; + border: 2px solid; + width: 16px; + height: 16px; +} +.win-listview.win-selectionstylefilled.win-rtl .win-surface.win-selectionmode .win-itembox::after { + left: auto; + right: 12px; +} +.win-listview.win-selectionstylefilled .win-surface.win-selectionmode .win-selectioncheckmarkbackground { + left: 12px; + top: 50%; + margin-top: -9px; + display: block; + border: 2px solid; + width: 16px; + height: 16px; +} +.win-listview.win-selectionstylefilled.win-rtl .win-surface.win-selectionmode .win-selectioncheckmarkbackground { + left: auto; + right: 12px; +} +.win-listview.win-selectionstylefilled .win-surface.win-selectionmode .win-selectioncheckmark { + left: 13px; + top: 50%; + margin-top: -8px; + display: block; + width: 14px; + height: 14px; +} +.win-listview.win-selectionstylefilled.win-rtl .win-surface.win-selectionmode .win-selectioncheckmark { + left: 0; + right: 10px; +} +.win-selectionmode .win-itemcontainer.win-selectionstylefilled.win-container .win-itembox.win-selected::after, +.win-itemcontainer.win-selectionmode.win-selectionstylefilled.win-container .win-itembox.win-selected::after, +.win-listview.win-selectionstylefilled .win-surface.win-selectionmode .win-itembox.win-nonselectable::after, +.win-listview .win-surface.win-selectionmode .win-itembox.win-selected::after { + display: none; +} +.win-listview .win-progress { + left: 50%; + top: 50%; + width: 60px; + height: 60px; + margin-left: -30px; + margin-top: -30px; + z-index: 1; + position: absolute; +} +.win-listview .win-progress::-ms-fill { + animation-name: -ms-ring; +} +.win-listview .win-itemsblock { + overflow: hidden; +} +.win-listview .win-surface.win-nocssgrid.win-gridlayout, +.win-listview .win-horizontal .win-nocssgrid.win-listlayout, +.win-listview .win-vertical .win-nocssgrid.win-listlayout.win-headerpositionleft { + display: -ms-inline-flexbox; + display: -webkit-inline-flex; + display: inline-flex; + vertical-align: top; +} +.win-listview .win-horizontal .win-surface.win-nocssgrid { + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-line-pack: start; + -webkit-align-content: flex-start; + align-content: flex-start; +} +.win-listview .win-vertical .win-surface.win-nocssgrid { + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row; + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-line-pack: start; + -webkit-align-content: flex-start; + align-content: flex-start; +} +.win-listview .win-vertical .win-structuralnodes.win-single-itemsblock.win-listlayout .win-itemscontainer.win-laidout, +.win-listview .win-horizontal .win-structuralnodes.win-single-itemsblock.win-listlayout .win-itemscontainer.win-laidout, +.win-listview .win-vertical .win-structuralnodes.win-single-itemsblock.win-gridlayout .win-uniformgridlayout.win-itemscontainer.win-laidout, +.win-listview .win-horizontal .win-structuralnodes.win-single-itemsblock.win-gridlayout .win-uniformgridlayout.win-itemscontainer.win-laidout { + display: block; +} +.win-listview .win-vertical .win-structuralnodes.win-single-itemsblock.win-listlayout .win-itemscontainer.win-laidout .win-itemscontainer-padder, +.win-listview .win-horizontal .win-structuralnodes.win-single-itemsblock.win-listlayout .win-itemscontainer.win-laidout .win-itemscontainer-padder, +.win-listview .win-vertical .win-structuralnodes.win-single-itemsblock.win-gridlayout .win-uniformgridlayout.win-itemscontainer.win-laidout .win-itemscontainer-padder, +.win-listview .win-horizontal .win-structuralnodes.win-single-itemsblock.win-gridlayout .win-uniformgridlayout.win-itemscontainer.win-laidout .win-itemscontainer-padder { + height: 0; + width: 0; +} +.win-listview.win-groups .win-vertical .win-listlayout.win-headerpositionleft .win-itemscontainer, +.win-listview.win-groups .win-vertical .win-listlayout.win-headerpositionleft .win-groupheadercontainer, +.win-listview.win-groups .win-horizontal .win-listlayout .win-itemscontainer, +.win-listview.win-groups .win-horizontal .win-listlayout .win-groupheadercontainer { + display: none; +} +.win-listview.win-groups .win-vertical .win-listlayout.win-headerpositionleft .win-itemscontainer.win-laidout, +.win-listview.win-groups .win-vertical .win-listlayout.win-headerpositionleft .win-groupheadercontainer.win-laidout, +.win-listview.win-groups .win-horizontal .win-listlayout .win-groupheadercontainer.win-laidout { + display: block; +} +.win-listview .win-listlayout .win-itemscontainer { + overflow: visible; +} +.win-listview .win-listlayout .win-itemsblock { + padding-bottom: 4px; + margin-bottom: -4px; +} +.win-listview > .win-vertical .win-listlayout.win-headerpositiontop .win-groupheader { + float: none; +} +.win-listview > .win-vertical .win-surface.win-listlayout { + margin-bottom: 5px; +} +.win-listview .win-vertical .win-listlayout.win-headerpositionleft.win-surface { + display: -ms-inline-grid; + -ms-grid-columns: auto 1fr; + -ms-grid-rows: auto; +} +.win-listview .win-vertical .win-listlayout.win-headerpositionleft .win-groupheadercontainer { + -ms-grid-column: 1; +} +.win-listview .win-vertical .win-listlayout.win-headerpositionleft .win-itemscontainer { + -ms-grid-column: 2; +} +.win-listview > .win-horizontal .win-surface.win-listlayout { + display: -ms-inline-grid; + -ms-grid-columns: auto; + -ms-grid-rows: auto; + vertical-align: top; +} +.win-listview .win-horizontal .win-listlayout .win-itemsblock { + height: 100%; +} +.win-listview .win-horizontal .win-listlayout .win-itemscontainer { + margin-bottom: 24px; +} +.win-listview .win-horizontal .win-listlayout .win-container { + height: calc(100% - 10px); +} +.win-listview > .win-horizontal .win-surface.win-listlayout.win-headerpositiontop { + -ms-grid-rows: auto 1fr; +} +.win-listview .win-horizontal .win-listlayout.win-headerpositiontop .win-groupheadercontainer { + -ms-grid-row: 1; +} +.win-listview .win-horizontal .win-listlayout.win-headerpositiontop .win-itemscontainer { + -ms-grid-row: 2; +} +.win-listview .win-gridlayout.win-surface { + display: -ms-inline-grid; + vertical-align: top; +} +.win-listview .win-gridlayout .win-container { + margin: 5px; +} +.win-listview .win-vertical .win-gridlayout.win-headerpositionleft .win-groupheadercontainer, +.win-listview .win-vertical .win-gridlayout.win-headerpositiontop .win-groupheadercontainer { + -ms-grid-column: 1; +} +.win-listview.win-groups .win-gridlayout .win-itemscontainer, +.win-listview.win-groups .win-gridlayout .win-groupheadercontainer { + display: none; +} +.win-listview.win-groups .win-gridlayout .win-groupheadercontainer.win-laidout { + display: block; +} +.win-listview .win-horizontal .win-gridlayout.win-headerpositiontop.win-surface { + -ms-grid-columns: auto; + -ms-grid-rows: auto 1fr; +} +.win-listview .win-horizontal .win-gridlayout.win-headerpositiontop .win-groupheadercontainer { + -ms-grid-row: 1; +} +.win-listview .win-horizontal .win-gridlayout.win-headerpositiontop .win-itemscontainer { + -ms-grid-row: 2; +} +.win-listview .win-horizontal .win-gridlayout.win-headerpositionleft.win-surface { + -ms-grid-columns: auto; + -ms-grid-rows: auto; +} +.win-listview .win-horizontal .win-gridlayout.win-headerpositionleft .win-groupheadercontainer { + -ms-grid-row: 1; +} +.win-listview .win-horizontal .win-gridlayout.win-headerpositionleft .win-itemscontainer { + -ms-grid-row: 1; +} +.win-listview .win-vertical .win-gridlayout.win-headerpositiontop.win-surface { + -ms-grid-columns: auto; + -ms-grid-rows: auto; +} +.win-listview .win-vertical .win-gridlayout.win-headerpositiontop .win-itemscontainer { + -ms-grid-column: 1; +} +.win-listview .win-vertical .win-gridlayout.win-headerpositionleft.win-surface { + -ms-grid-columns: auto 1fr; + -ms-grid-rows: auto; +} +.win-listview .win-vertical .win-gridlayout.win-headerpositionleft .win-itemscontainer { + -ms-grid-column: 2; +} +.win-listview .win-gridlayout.win-structuralnodes .win-uniformgridlayout.win-itemscontainer.win-laidout { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row; +} +.win-listview .win-horizontal .win-listlayout .win-itemscontainer, +.win-listview.win-groups .win-horizontal .win-listlayout .win-itemscontainer.win-laidout, +.win-listview .win-horizontal .win-listlayout .win-itemsblock, +.win-listview .win-horizontal .win-gridlayout .win-uniformgridlayout.win-itemscontainer.win-laidout, +.win-listview .win-horizontal .win-gridlayout .win-uniformgridlayout .win-itemsblock { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-line-pack: start; + -webkit-align-content: flex-start; + align-content: flex-start; +} +.win-listview .win-horizontal .win-itemscontainer-padder { + height: 100%; +} +.win-listview .win-horizontal .win-gridlayout .win-uniformgridlayout .win-itemsblock { + height: 100%; +} +.win-listview .win-horizontal .win-gridlayout .win-cellspanninggridlayout.win-itemscontainer.win-laidout { + display: -ms-grid; +} +.win-listview .win-vertical .win-gridlayout.win-structuralnodes .win-uniformgridlayout.win-itemscontainer.win-laidout { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; +} +.win-listview .win-vertical .win-gridlayout .win-uniformgridlayout.win-itemscontainer.win-laidout, +.win-listview .win-vertical .win-gridlayout .win-uniformgridlayout .win-itemsblock { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row; + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-line-pack: start; + -webkit-align-content: flex-start; + align-content: flex-start; +} +.win-listview .win-vertical .win-gridlayout .win-uniformgridlayout .win-itemsblock { + width: 100%; +} +.win-listview .win-cellspanninggridlayout .win-container.win-laidout { + display: block; +} +.win-listview .win-cellspanninggridlayout .win-container { + display: none; +} +.win-listview .win-itembox { + position: relative; +} +.win-listview.win-dragover .win-itembox { + transform: scale(0.86); + -webkit-transform: scale(0.86); +} +.win-listview .win-itembox.win-dragsource, +.win-itemcontainer .win-itembox.win-dragsource { + opacity: 0.5; + transition: opacity cubic-bezier(0.1, 0.9, 0.2, 1) 167ms, transform cubic-bezier(0.1, 0.9, 0.2, 1) 220ms; + -webkit-transition: opacity cubic-bezier(0.1, 0.9, 0.2, 1) 167ms, transform cubic-bezier(0.1, 0.9, 0.2, 1) 220ms; +} +.win-listview.win-dragover .win-itembox.win-dragsource { + opacity: 0; + transition: none; + -webkit-transition: none; +} +html.win-hoverable .win-listview.win-dragover .win-container:hover { + outline: none; +} +.win-listview .win-itembox { + transition: transform cubic-bezier(0.1, 0.9, 0.2, 1) 220ms; + -webkit-transition: -webkit-transform cubic-bezier(0.1, 0.9, 0.2, 1) 220ms; +} +.win-listview.win-groups > .win-vertical .win-surface.win-listlayout.win-headerpositionleft { + margin-left: 70px; +} +.win-listview.win-groups.win-rtl > .win-vertical .win-surface.win-listlayout.win-headerpositionleft { + margin-left: 0px; + margin-right: 70px; +} +.win-listview > .win-horizontal .win-surface.win-listlayout { + margin-left: 70px; +} +.win-listview.win-rtl > .win-horizontal .win-surface.win-listlayout { + margin-left: 0px; + margin-right: 70px; +} +.win-listview .win-vertical .win-gridlayout.win-surface { + margin-left: 20px; +} +.win-listview.win-rtl .win-vertical .win-gridlayout.win-surface { + margin-left: 0px; + margin-right: 20px; +} +.win-itemcontainer .win-itembox, +.win-itemcontainer.win-container { + position: relative; +} +.win-itemcontainer { + touch-action: pan-x pan-y pinch-zoom; +} +html.win-hoverable .win-listview .win-itembox:hover::before, +html.win-hoverable .win-itemcontainer .win-itembox:hover::before { + opacity: 0.4; +} +html.win-hoverable .win-listview .win-pressed .win-itembox:hover::before, +html.win-hoverable .win-itemcontainer .win-pressed .win-itembox:hover::before, +html.win-hoverable .win-listview .win-pressed.win-itembox:hover::before, +html.win-hoverable .win-itemcontainer .win-pressed.win-itembox:hover::before { + opacity: 0.6; +} +html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover, +html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover, +html.win-hoverable .win-selectionstylefilled .win-itemcontainer.win-container:hover { + outline: none; +} +.win-selectionstylefilled.win-itemcontainer .win-itembox, +.win-selectionstylefilled .win-itemcontainer .win-itembox, +.win-listview.win-selectionstylefilled .win-itembox { + background-color: transparent; +} +.win-listview.win-selectionstylefilled .win-container.win-selected .win-selectionborder, +.win-itemcontainer.win-selectionstylefilled.win-container.win-selected .win-selectionborder { + border-color: transparent; +} +.win-listview.win-selectionstylefilled .win-surface.win-selectionmode .win-itembox::after { + background-color: transparent; +} +.win-listview.win-selectionstylefilled .win-selectioncheckmarkbackground, +.win-itemcontainer.win-selectionstylefilled .win-selectioncheckmarkbackground { + border-color: transparent; +} +.win-listview.win-selectionstylefilled .win-selected a, +.win-listview.win-selectionstylefilled .win-selected progress, +.win-listview.win-selectionstylefilled .win-selected .win-rating .win-star.win-full, +.win-itemcontainer.win-selectionstylefilled.win-selected a, +.win-itemcontainer.win-selectionstylefilled.win-selected progress, +.win-itemcontainer.win-selectionstylefilled.win-selected .win-rating .win-star.win-full { + color: #ffffff; +} +.win-listview.win-selectionstylefilled .win-selected.win-selected a:hover:active, +.win-itemcontainer.win-selectionstylefilled.win-selected.win-selected a:hover:active { + color: rgba(255, 255, 255, 0.6); +} +html.win-hoverable .win-listview.win-selectionstylefilled .win-selected a:hover, +html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-selected a:hover { + color: rgba(255, 255, 255, 0.8); +} +.win-listview.win-selectionstylefilled .win-selected button, +.win-listview.win-selectionstylefilled .win-selected input[type=button], +.win-listview.win-selectionstylefilled .win-selected input[type=reset], +.win-listview.win-selectionstylefilled .win-selected input[type=text], +.win-listview.win-selectionstylefilled .win-selected input[type=password], +.win-listview.win-selectionstylefilled .win-selected input[type=email], +.win-listview.win-selectionstylefilled .win-selected input[type=number], +.win-listview.win-selectionstylefilled .win-selected input[type=tel], +.win-listview.win-selectionstylefilled .win-selected input[type=url], +.win-listview.win-selectionstylefilled .win-selected input[type=search], +.win-listview.win-selectionstylefilled .win-selected input::-ms-check, +.win-listview.win-selectionstylefilled .win-selected textarea, +.win-listview.win-selectionstylefilled .win-selected .win-textarea, +.win-listview.win-selectionstylefilled .win-selected select, +.win-itemcontainer.win-selectionstylefilled.win-selected button, +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=button], +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=reset], +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=text], +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=password], +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=email], +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=number], +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=tel], +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=url], +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=search], +.win-itemcontainer.win-selectionstylefilled.win-selected input::-ms-check, +.win-itemcontainer.win-selectionstylefilled.win-selected textarea, +.win-itemcontainer.win-selectionstylefilled.win-selected .win-textarea, +.win-itemcontainer.win-selectionstylefilled.win-selected select { + background-clip: border-box; + background-color: rgba(255, 255, 255, 0.8); + border-color: transparent; + color: #000000; +} +.win-listview.win-selectionstylefilled .win-selected button[type=submit], +.win-listview.win-selectionstylefilled .win-selected input[type=submit], +.win-itemcontainer.win-selectionstylefilled.win-selected button[type=submit], +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=submit] { + border-color: #ffffff; +} +.win-listview.win-selectionstylefilled .win-selected input[type=range]::-ms-fill-lower, +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=range]::-ms-fill-lower { + background-color: #ffffff; +} +.win-listview.win-selectionstylefilled .win-selected input[type=range]::-ms-thumb, +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=range]::-ms-thumb { + background-color: #000000; +} +.win-listview.win-selectionstylefilled .win-selected input[type=range]::-ms-fill-upper, +.win-listview.win-selectionstylefilled .win-selected progress, +.win-itemcontainer.win-selectionstylefilled.win-selected input[type=range]::-ms-fill-upper, +.win-itemcontainer.win-selectionstylefilled.win-selected progress { + background-color: rgba(255, 255, 255, 0.16); +} +.win-listview.win-selectionstylefilled .win-selected progress:indeterminate, +.win-itemcontainer.win-selectionstylefilled.win-selected progress:indeterminate { + background-color: transparent; +} +.win-listview.win-selectionstylefilled .win-selected .win-rating .win-star.win-empty, +.win-itemcontainer.win-selectionstylefilled.win-selected .win-rating .win-star.win-empty { + color: rgba(255, 255, 255, 0.16); +} +.win-listview .win-viewport { + outline: none; +} +@media (-ms-high-contrast) { + .win-listview .win-groupheader { + color: WindowText; + } + .win-selectioncheckmark { + color: HighlightText; + } + .win-listview .win-focusedoutline, + .win-listview .win-groupheader, + .win-itemcontainer .win-focusedoutline { + outline-color: WindowText; + } + .win-listview.win-selectionstylefilled .win-itembox, + .win-itemcontainer.win-selectionstylefilled .win-itembox { + background-color: Window; + color: WindowText; + } + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover .win-itembox, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover .win-itembox { + background-color: Highlight; + color: HighlightText; + } + .win-listview.win-selectionstylefilled .win-container.win-selected .win-itembox, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container.win-selected:hover .win-itembox, + .win-itemcontainer.win-selectionstylefilled.win-container.win-selected .win-itembox, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container.win-selected:hover .win-itembox { + background-color: Highlight; + color: HighlightText; + } + .win-listview:not(.win-selectionstylefilled) .win-container.win-selected .win-selectionborder, + .win-itemcontainer:not(.win-selectionstylefilled).win-container.win-selected .win-selectionborder { + border-color: Highlight; + } + .win-listview.win-selectionstylefilled .win-container.win-selected .win-selectionborder, + .win-itemcontainer.win-selectionstylefilled.win-container.win-selected .win-selectionborder { + border-color: transparent; + } + html.win-hoverable .win-listview:not(.win-selectionstylefilled) .win-container.win-selected:hover .win-selectionborder, + html.win-hoverable .win-itemcontainer:not(.win-selectionstylefilled).win-container.win-selected:hover .win-selectionborder { + border-color: Highlight; + } + .win-listview.win-selectionstylefilled .win-selected .win-selectionbackground, + html.win-hoverable .win-listview.win-selectionstylefilled .win-selected:hover .win-selectionbackground, + .win-itemcontainer.win-selectionstylefilled.win-selected .win-selectionbackground, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-selected:hover .win-selectionbackground { + background-color: Highlight; + color: HighlightText; + } + .win-listview.win-selectionstylefilled .win-selectioncheckmarkbackground, + .win-itemcontainer.win-selectionstylefilled .win-selectioncheckmarkbackground { + border-color: transparent; + } + .win-listview.win-selectionstylefilled .win-selected a, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover a, + .win-listview.win-selectionstylefilled .win-selected progress, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover progress, + .win-listview.win-selectionstylefilled .win-selected .win-rating .win-star:after, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover .win-rating .win-star:after, + .win-itemcontainer.win-selectionstylefilled.win-selected a, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover a, + .win-itemcontainer.win-selectionstylefilled.win-selected progress, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover progress, + .win-itemcontainer.win-selectionstylefilled.win-selected .win-rating .win-star:after, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover .win-rating .win-star:after { + color: HighlightText; + } + .win-listview.win-selectionstylefilled .win-selected input, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover input, + .win-listview.win-selectionstylefilled .win-selected input::-ms-check, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover input::-ms-check, + .win-listview.win-selectionstylefilled .win-selected input::-ms-value, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover input::-ms-value, + .win-listview.win-selectionstylefilled .win-selected input::-ms-track, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover input::-ms-track, + .win-listview.win-selectionstylefilled .win-selected button, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover button, + .win-listview.win-selectionstylefilled .win-selected progress, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover progress, + .win-listview.win-selectionstylefilled .win-selected progress::-ms-fill, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover progress::-ms-fill, + .win-listview.win-selectionstylefilled .win-selected select, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover select, + .win-listview.win-selectionstylefilled .win-selected textarea, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover textarea, + .win-listview.win-selectionstylefilled.win-selected input, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover input, + .win-itemcontainer.win-selectionstylefilled.win-selected input::-ms-check, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover input::-ms-check, + .win-itemcontainer.win-selectionstylefilled.win-selected input::-ms-value, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover input::-ms-value, + .win-itemcontainer.win-selectionstylefilled.win-selected input::-ms-track, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover input::-ms-track, + .win-itemcontainer.win-selectionstylefilled.win-selected button, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover button, + .win-itemcontainer.win-selectionstylefilled.win-selected progress, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover progress, + .win-itemcontainer.win-selectionstylefilled.win-selected progress::-ms-fill, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover progress::-ms-fill, + .win-itemcontainer.win-selectionstylefilled.win-selected select, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover select, + .win-itemcontainer.win-selectionstylefilled.win-selected textarea, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover textarea { + border-color: HighlightText; + } + .win-listview.win-selectionstylefilled .win-selected input[type=range]::-ms-fill-lower, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover input[type=range]::-ms-fill-lower, + .win-listview.win-selectionstylefilled .win-selected progress::-ms-fill, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover progress::-ms-fill, + .win-itemcontainer.win-selectionstylefilled.win-selected input[type=range]::-ms-fill-lower, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover input[type=range]::-ms-fill-lower, + .win-itemcontainer.win-selectionstylefilled.win-selected progress::-ms-fill, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover progress::-ms-fill { + background-color: HighlightText; + } + .win-listview.win-selectionstylefilled .win-selected input[type=range]::-ms-fill-upper, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover input[type=range]::-ms-fill-upper, + .win-listview.win-selectionstylefilled .win-selected progress, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover progress, + .win-itemcontainer.win-selectionstylefilled.win-selected input[type=range]::-ms-fill-upper, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover input[type=range]::-ms-fill-upper, + .win-itemcontainer.win-selectionstylefilled.win-selected progress, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover progress { + background-color: Highlight; + } + .win-listview.win-selectionstylefilled .win-selected .win-rating .win-star.win-full:before, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover .win-rating .win-star.win-full:before, + .win-itemcontainer.win-selectionstylefilled.win-selected .win-rating .win-star.win-full:before, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover .win-rating .win-star.win-full:before { + color: ButtonFace; + } + .win-listview.win-selectionstylefilled .win-selected .win-rating .win-star.win-empty:before, + html.win-hoverable .win-listview.win-selectionstylefilled .win-container:hover .win-rating .win-star.win-empty:before, + .win-itemcontainer.win-selectionstylefilled.win-selected .win-rating .win-star.win-empty:before, + html.win-hoverable .win-itemcontainer.win-selectionstylefilled.win-container:hover .win-rating .win-star.win-empty:before { + color: Highlight; + } + html.win-hoverable .win-listview .win-container:hover, + html.win-hoverable .win-itemcontainer.win-container:hover { + outline: Highlight solid 3px; + } +} +.win-flipview { + overflow: hidden; + height: 400px; +} +.win-flipview .win-surface { + -ms-scroll-chaining: none; +} +.win-flipview .win-navleft { + left: 0%; + top: 50%; + margin-top: -19px; +} +.win-flipview .win-navright { + left: 100%; + top: 50%; + margin-left: -20px; + margin-top: -19px; +} +.win-flipview .win-navtop { + left: 50%; + top: 0%; + margin-left: -35px; +} +.win-flipview .win-navbottom { + left: 50%; + top: 100%; + margin-left: -35px; + margin-top: -36px; +} +.win-flipview .win-navbutton { + touch-action: manipulation; + border: none; + width: 20px; + height: 36px; + z-index: 1; + position: absolute; + font-family: "Segoe MDL2 Assets", "Symbols"; + font-size: 16px; + padding: 0; + min-width: 0; +} +.win-flipview .win-item, +.win-flipview .win-item > .win-template { + height: 100%; + width: 100%; + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -ms-flex-align: center; + -webkit-align-items: center; + align-items: center; + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; +} +@media (-ms-high-contrast) { + .win-flipview .win-navbottom { + left: 50%; + top: 100%; + margin-left: -35px; + margin-top: -35px; + } + .win-flipview .win-navbutton { + background-color: ButtonFace; + color: ButtonText; + border: 2px solid ButtonText; + width: 65px; + height: 35px; + } + .win-flipview .win-navbutton.win-navbutton:hover:active, + .win-flipview .win-navbutton.win-navbutton:active { + background-color: ButtonText; + color: ButtonFace; + } + .win-flipview .win-navright { + margin-left: -65px; + } + html.win-hoverable .win-flipview .win-navbutton:hover { + background-color: Highlight; + color: HighlightText; + } +} +.win-datepicker { + display: -ms-inline-flexbox; + display: -webkit-inline-flex; + display: inline-flex; + height: auto; + width: auto; +} +.win-datepicker select { + min-width: 80px; + margin-top: 4px; + margin-bottom: 4px; +} +.win-datepicker .win-datepicker-month { + margin-right: 20px; +} +.win-datepicker .win-datepicker-date.win-order0, +.win-datepicker .win-datepicker-date.win-order1 { + margin-right: 20px; +} +.win-datepicker .win-datepicker-year.win-order0 { + margin-right: 20px; +} +.win-datepicker .win-datepicker-month:lang(ar), +.win-datepicker .win-datepicker-month:lang(dv), +.win-datepicker .win-datepicker-month:lang(fa), +.win-datepicker .win-datepicker-month:lang(he), +.win-datepicker .win-datepicker-month:lang(ku-Arab), +.win-datepicker .win-datepicker-month:lang(pa-Arab), +.win-datepicker .win-datepicker-month:lang(prs), +.win-datepicker .win-datepicker-month:lang(ps), +.win-datepicker .win-datepicker-month:lang(sd-Arab), +.win-datepicker .win-datepicker-month:lang(syr), +.win-datepicker .win-datepicker-month:lang(ug), +.win-datepicker .win-datepicker-month:lang(ur), +.win-datepicker .win-datepicker-month:lang(qps-plocm), +.win-datepicker .win-datepicker-date.win-order0:lang(ar), +.win-datepicker .win-datepicker-date.win-order0:lang(dv), +.win-datepicker .win-datepicker-date.win-order0:lang(fa), +.win-datepicker .win-datepicker-date.win-order0:lang(he), +.win-datepicker .win-datepicker-date.win-order0:lang(ku-Arab), +.win-datepicker .win-datepicker-date.win-order0:lang(pa-Arab), +.win-datepicker .win-datepicker-date.win-order0:lang(prs), +.win-datepicker .win-datepicker-date.win-order0:lang(ps), +.win-datepicker .win-datepicker-date.win-order0:lang(sd-Arab), +.win-datepicker .win-datepicker-date.win-order0:lang(syr), +.win-datepicker .win-datepicker-date.win-order0:lang(ug), +.win-datepicker .win-datepicker-date.win-order0:lang(ur), +.win-datepicker .win-datepicker-date.win-order0:lang(qps-plocm), +.win-datepicker .win-datepicker-date.win-order1:lang(ar), +.win-datepicker .win-datepicker-date.win-order1:lang(dv), +.win-datepicker .win-datepicker-date.win-order1:lang(fa), +.win-datepicker .win-datepicker-date.win-order1:lang(he), +.win-datepicker .win-datepicker-date.win-order1:lang(ku-Arab), +.win-datepicker .win-datepicker-date.win-order1:lang(pa-Arab), +.win-datepicker .win-datepicker-date.win-order1:lang(prs), +.win-datepicker .win-datepicker-date.win-order1:lang(ps), +.win-datepicker .win-datepicker-date.win-order1:lang(sd-Arab), +.win-datepicker .win-datepicker-date.win-order1:lang(syr), +.win-datepicker .win-datepicker-date.win-order1:lang(ug), +.win-datepicker .win-datepicker-date.win-order1:lang(ur), +.win-datepicker .win-datepicker-date.win-order1:lang(qps-plocm), +.win-datepicker .win-datepicker-year.win-order0:lang(ar), +.win-datepicker .win-datepicker-year.win-order0:lang(dv), +.win-datepicker .win-datepicker-year.win-order0:lang(fa), +.win-datepicker .win-datepicker-year.win-order0:lang(he), +.win-datepicker .win-datepicker-year.win-order0:lang(ku-Arab), +.win-datepicker .win-datepicker-year.win-order0:lang(pa-Arab), +.win-datepicker .win-datepicker-year.win-order0:lang(prs), +.win-datepicker .win-datepicker-year.win-order0:lang(ps), +.win-datepicker .win-datepicker-year.win-order0:lang(sd-Arab), +.win-datepicker .win-datepicker-year.win-order0:lang(syr), +.win-datepicker .win-datepicker-year.win-order0:lang(ug), +.win-datepicker .win-datepicker-year.win-order0:lang(ur), +.win-datepicker .win-datepicker-year.win-order0:lang(qps-plocm) { + margin-right: 0; + margin-left: 20px; +} +.win-timepicker { + display: -ms-inline-flexbox; + display: -webkit-inline-flex; + display: inline-flex; + height: auto; + width: auto; +} +.win-timepicker select { + min-width: 80px; + margin-top: 4px; + margin-bottom: 4px; +} +.win-timepicker .win-timepicker-hour { + margin-right: 20px; +} +.win-timepicker .win-timepicker-period.win-order0 { + margin-right: 20px; +} +.win-timepicker .win-timepicker-minute.win-order1 { + margin-right: 20px; +} +.win-timepicker .win-timepicker-period.win-order0:lang(ar), +.win-timepicker .win-timepicker-period.win-order0:lang(dv), +.win-timepicker .win-timepicker-period.win-order0:lang(fa), +.win-timepicker .win-timepicker-period.win-order0:lang(he), +.win-timepicker .win-timepicker-period.win-order0:lang(ku-Arab), +.win-timepicker .win-timepicker-period.win-order0:lang(pa-Arab), +.win-timepicker .win-timepicker-period.win-order0:lang(prs), +.win-timepicker .win-timepicker-period.win-order0:lang(ps), +.win-timepicker .win-timepicker-period.win-order0:lang(sd-Arab), +.win-timepicker .win-timepicker-period.win-order0:lang(syr), +.win-timepicker .win-timepicker-period.win-order0:lang(ug), +.win-timepicker .win-timepicker-period.win-order0:lang(ur), +.win-timepicker .win-timepicker-period.win-order0:lang(qps-plocm), +.win-timepicker .win-timepicker-hour:lang(ar), +.win-timepicker .win-timepicker-hour:lang(dv), +.win-timepicker .win-timepicker-hour:lang(fa), +.win-timepicker .win-timepicker-hour:lang(he), +.win-timepicker .win-timepicker-hour:lang(ku-Arab), +.win-timepicker .win-timepicker-hour:lang(pa-Arab), +.win-timepicker .win-timepicker-hour:lang(prs), +.win-timepicker .win-timepicker-hour:lang(ps), +.win-timepicker .win-timepicker-hour:lang(sd-Arab), +.win-timepicker .win-timepicker-hour:lang(syr), +.win-timepicker .win-timepicker-hour:lang(ug), +.win-timepicker .win-timepicker-hour:lang(ur), +.win-timepicker .win-timepicker-hour:lang(qps-plocm) { + margin-right: 0; + margin-left: 20px; +} +.win-timepicker .win-timepicker-minute.win-order1:lang(ar), +.win-timepicker .win-timepicker-minute.win-order1:lang(dv), +.win-timepicker .win-timepicker-minute.win-order1:lang(fa), +.win-timepicker .win-timepicker-minute.win-order1:lang(he), +.win-timepicker .win-timepicker-minute.win-order1:lang(ku-Arab), +.win-timepicker .win-timepicker-minute.win-order1:lang(pa-Arab), +.win-timepicker .win-timepicker-minute.win-order1:lang(prs), +.win-timepicker .win-timepicker-minute.win-order1:lang(ps), +.win-timepicker .win-timepicker-minute.win-order1:lang(sd-Arab), +.win-timepicker .win-timepicker-minute.win-order1:lang(syr), +.win-timepicker .win-timepicker-minute.win-order1:lang(ug), +.win-timepicker .win-timepicker-minute.win-order1:lang(ur), +.win-timepicker .win-timepicker-minute.win-order1:lang(qps-plocm), +.win-timepicker .win-timepicker-minute.win-order0:lang(ar), +.win-timepicker .win-timepicker-minute.win-order0:lang(dv), +.win-timepicker .win-timepicker-minute.win-order0:lang(fa), +.win-timepicker .win-timepicker-minute.win-order0:lang(he), +.win-timepicker .win-timepicker-minute.win-order0:lang(ku-Arab), +.win-timepicker .win-timepicker-minute.win-order0:lang(pa-Arab), +.win-timepicker .win-timepicker-minute.win-order0:lang(prs), +.win-timepicker .win-timepicker-minute.win-order0:lang(ps), +.win-timepicker .win-timepicker-minute.win-order0:lang(sd-Arab), +.win-timepicker .win-timepicker-minute.win-order0:lang(syr), +.win-timepicker .win-timepicker-minute.win-order0:lang(ug), +.win-timepicker .win-timepicker-minute.win-order0:lang(ur), +.win-timepicker .win-timepicker-minute.win-order0:lang(qps-plocm) { + margin-left: 20px; + margin-right: 0; +} +body > .win-navigation-backbutton { + position: absolute; + top: 50px; + left: 20px; +} +.win-backbutton, +.win-navigation-backbutton, +.win-back { + touch-action: manipulation; + display: inline-block; + min-width: 0; + min-height: 0; + padding: 0; + text-align: center; + width: 41px; + height: 41px; + font-size: 24px; + line-height: 41px; + vertical-align: baseline; +} +.win-backbutton::before, +.win-back::before { + font-family: "Segoe MDL2 Assets", "Symbols"; + font-weight: normal; + content: "\E0D5"; + vertical-align: 50%; +} +.win-backbutton:lang(ar)::before, +.win-backbutton:lang(dv)::before, +.win-backbutton:lang(fa)::before, +.win-backbutton:lang(he)::before, +.win-backbutton:lang(ku-Arab)::before, +.win-backbutton:lang(pa-Arab)::before, +.win-backbutton:lang(prs)::before, +.win-backbutton:lang(ps)::before, +.win-backbutton:lang(sd-Arab)::before, +.win-backbutton:lang(syr)::before, +.win-backbutton:lang(ug)::before, +.win-backbutton:lang(ur)::before, +.win-backbutton:lang(qps-plocm)::before, +.win-back:lang(ar)::before, +.win-back:lang(dv)::before, +.win-back:lang(fa)::before, +.win-back:lang(he)::before, +.win-back:lang(ku-Arab)::before, +.win-back:lang(pa-Arab)::before, +.win-back:lang(prs)::before, +.win-back:lang(ps)::before, +.win-back:lang(sd-Arab)::before, +.win-back:lang(syr)::before, +.win-back:lang(ug)::before, +.win-back:lang(ur)::before, +.win-back:lang(qps-plocm)::before { + content: "\E0AE"; +} +button.win-navigation-backbutton, +button.win-navigation-backbutton:active, +html.win-hoverable button.win-navigation-backbutton:enabled:hover, +button.win-navigation-backbutton:enabled:hover:active { + background-color: transparent; + border: none; +} +@media (-ms-high-contrast) { + button.win-navigation-backbutton, + button.win-navigation-backbutton:active, + html.win-hoverable button.win-navigation-backbutton:enabled:hover, + button.win-navigation-backbutton:enabled:hover:active { + /* Overwrite default background and border styles from BackButton control's ]]> + /// The BackButton control itself + /// The Back Arrow glyph + /// + /// + BackButton: _Base.Namespace._lazy(function () { + // Statics + var strings = { + get ariaLabel() { return _Resources._getWinJSString("ui/backbuttonarialabel").value; }, + get duplicateConstruction() { return "Invalid argument: Controls may only be instantiated one time for each DOM element"; }, + get badButtonElement() { return "Invalid argument: For a button, toggle, or flyout command, the element must be null or a button element"; } + }; + + var BackButton = _Base.Class.define(function BackButton_ctor(element, options) { + /// + /// + /// Creates a new BackButton control + /// + /// + /// The DOM element that will host the control. If this parameter is null, this constructor creates one for you. + /// + /// + /// An object that contains one or more property/value pairs to apply to the new control. Each property of the options object corresponds to + /// one of the control's properties or events. + /// + /// + /// A BackButton control. + /// + /// + /// + + // Check to make sure we weren't duplicated + if (element && element.winControl) { + throw new _ErrorFromName("WinJS.UI.BackButton.DuplicateConstruction", strings.duplicateConstruction); + } + + this._element = element || _Global.document.createElement("button"); + options = options || {}; + + this._initializeButton(); // This will also set the aria-label and tooltip + + this._disposed = false; + + // Remember ourselves + this._element.winControl = this; + + _Control.setOptions(this, options); + + // Add event handlers for this back button instance + this._buttonClickHandler = this._handleBackButtonClick.bind(this); + this._element.addEventListener('click', this._buttonClickHandler, false); + this._navigatedHandler = this._handleNavigatedEvent.bind(this); + Navigation.addEventListener('navigated', this._navigatedHandler, false); + + // Increment reference count / manage add global event handlers + singleton.addRef(); + }, { + + /// + element: { + get: function () { + return this._element; + } + }, + + dispose: function () { + /// + /// + /// Disposes this control. + /// + /// + /// + if (this._disposed) { + return; + } + this._disposed = true; // Mark this control as disposed. + + // Remove 'navigated' eventhandler for this BackButton + Navigation.removeEventListener('navigated', this._navigatedHandler, false); + + singleton.release(); // Decrement reference count. + + }, + + refresh: function () { + /// + /// + /// Sets the 'disabled' attribute to correct the value based on the current navigation history stack. + /// + /// + /// + if (Navigation.canGoBack) { + this._element.disabled = false; + } else { + this._element.disabled = true; + } + }, + + _initializeButton: function () { + //Final EN-US HTML should be: + // + //Button will automatically be disabled if WinJS.Navigation.history.canGoBack is false. + + // Verify the HTML is a button + if (this._element.tagName !== "BUTTON") { + throw new _ErrorFromName("WinJS.UI.BackButton.BadButtonElement", strings.badButtonElement); + } + + // Attach our css classes + _ElementUtilities.addClass(this._element, navigationBackButtonClass); + + // Attach disposable class. + _ElementUtilities.addClass(this._element, "win-disposable"); + + // Create inner glyph element + this._element.innerHTML = ''; + + // Set the 'disabled' property to the correct value based on the current navigation history stack. + this.refresh(); + + // Set Aria-label and native tooltip to the same localized string equivalent of "Back" + this._element.setAttribute("aria-label", strings.ariaLabel); + this._element.setAttribute("title", strings.ariaLabel); + + // Explicitly set type attribute to avoid the default '; + this._headerTabStopElement = this._headerElement.firstElementChild; + // The purpose of headerWrapperElement is to lay out its children in a flexbox. Ideally, this flexbox would + // be on headerTabStopElement. However, firefox lays out flexboxes with display:flex differently. + // Firefox bug 1014285 (Button with display:inline-flex doesn't layout properly) + // https://bugzilla.mozilla.org/show_bug.cgi?id=1014285 + this._headerWrapperElement = this._headerTabStopElement.firstElementChild; + this._headerContentElement = this._headerWrapperElement.firstElementChild; + this._headerChevronElement = this._headerWrapperElement.lastElementChild; + element.appendChild(this._headerElement); + + this._winKeyboard = new _KeyboardBehavior._WinKeyboard(this._headerElement); + + this._contentElement = _Global.document.createElement("DIV"); + this._contentElement.className = HubSection._ClassName.hubSectionContent; + this._contentElement.style.visibility = "hidden"; + element.appendChild(this._contentElement); + + // Reparent any existing elements inside the new hub section content element. + var elementToMove = this.element.firstChild; + while (elementToMove !== this._headerElement) { + var nextElement = elementToMove.nextSibling; + this._contentElement.appendChild(elementToMove); + elementToMove = nextElement; + } + + this._processors = [ControlProcessor.processAll]; + + _Control.setOptions(this, options); + }, { + /// + element: { + get: function () { + return this._element; + } + }, + /// + /// Gets or sets a value that specifies whether the header is static. Set this value to true to disable clicks and other interactions. + /// + /// + isHeaderStatic: { + get: function () { + return this._isHeaderStatic; + }, + set: function (value) { + this._isHeaderStatic = value; + if (!this._isHeaderStatic) { + this._headerTabStopElement.setAttribute("role", "link"); + _ElementUtilities.addClass(this._headerTabStopElement, HubSection._ClassName.hubSectionInteractive); + } else { + this._headerTabStopElement.setAttribute("role", "heading"); + _ElementUtilities.removeClass(this._headerTabStopElement, HubSection._ClassName.hubSectionInteractive); + } + } + }, + /// + /// Gets the DOM element that hosts the HubSection's content. + /// + /// + contentElement: { + get: function () { + return this._contentElement; + } + }, + /// + /// Get or set the HubSection's header. After you set this property, the Hub renders the header again. + /// + /// + header: { + get: function () { + return this._header; + }, + set: function (value) { + // Render again even if it is equal to itself. + this._header = value; + this._renderHeader(); + } + }, + _setHeaderTemplate: function HubSection_setHeaderTemplate(template) { + this._template = _ElementUtilities._syncRenderer(template); + this._renderHeader(); + }, + _renderHeader: function HubSection_renderHeader() { + if (this._template) { + _Dispose._disposeElement(this._headerContentElement); + _ElementUtilities.empty(this._headerContentElement); + this._template(this, this._headerContentElement); + } + }, + _process: function HubSection_process() { + var that = this; + + this._processed = (this._processors || []).reduce(function (promise, processor) { + return promise.then(function () { + return processor(that.contentElement); + }); + }, this._processed || Promise.as()); + this._processors = null; + + return this._processed; + }, + dispose: function HubSection_dispose() { + /// + /// + /// Disposes this control. + /// + /// + /// + if (this._disposed) { + return; + } + this._disposed = true; + this._processors = null; + + _Dispose._disposeElement(this._headerContentElement); + _Dispose.disposeSubTree(this.contentElement); + } + }, { + // Names of classes used by the HubSection. + _ClassName: { + hubSection: "win-hub-section", + hubSectionHeader: "win-hub-section-header", + hubSectionHeaderTabStop: "win-hub-section-header-tabstop", + hubSectionHeaderWrapper: "win-hub-section-header-wrapper", + hubSectionInteractive: "win-hub-section-header-interactive", + hubSectionHeaderContent: "win-hub-section-header-content", + hubSectionHeaderChevron: "win-hub-section-header-chevron", + hubSectionContent: "win-hub-section-content" + }, + isDeclarativeControlContainer: _BaseUtils.markSupportedForProcessing(function (section, callback) { + if (callback === ControlProcessor.processAll) { + return; + } + + section._processors = section._processors || []; + section._processors.push(callback); + + // Once processed the first time synchronously queue up new processors as they come in + if (section._processed) { + section._process(); + } + }) + }); + + return HubSection; + }) + }); + +}); + + +define('require-style!less/styles-hub',[],function(){}); + +define('require-style!less/colors-hub',[],function(){}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('WinJS/Controls/Hub',[ + '../Core/_Global', + '../Core/_Base', + '../Core/_BaseUtils', + '../Core/_ErrorFromName', + '../Core/_Events', + '../Core/_Log', + '../Core/_Resources', + '../Core/_WriteProfilerMark', + '../_Accents', + '../Animations', + '../Animations/_TransitionAnimation', + '../BindingList', + '../ControlProcessor', + '../Promise', + '../_Signal', + '../Scheduler', + '../Utilities/_Control', + '../Utilities/_ElementUtilities', + '../Utilities/_Hoverable', + '../Utilities/_UI', + './Hub/_Section', + 'require-style!less/styles-hub', + 'require-style!less/colors-hub' +], function hubInit(_Global, _Base, _BaseUtils, _ErrorFromName, _Events, _Log, _Resources, _WriteProfilerMark, _Accents, Animations, _TransitionAnimation, BindingList, ControlProcessor, Promise, _Signal, Scheduler, _Control, _ElementUtilities, _Hoverable, _UI, _Section) { + "use strict"; + + _Accents.createAccentRule( + ".win-semanticzoom-zoomedoutview .win-hub-section-header-interactive .win-hub-section-header-content,\ + .win-hub-section-header-interactive .win-hub-section-header-chevron", + [{ name: "color", value: _Accents.ColorTypes.accent }]); + + _Base.Namespace.define("WinJS.UI", { + /// + /// + /// Displays sections of content. + /// + /// + /// + /// + /// + /// + ///
HubSection Content
+ /// ]]>
+ /// Raised when the Hub is about to play an entrance or a transition animation. + /// Raised when a header is invoked. + /// Raised when the loading state changes. + /// The entire Hub control. + /// The progress indicator for the Hub. + /// The viewport of the Hub. + /// The scrollable region of the Hub. + /// + /// + Hub: _Base.Namespace._lazy(function () { + var Key = _ElementUtilities.Key; + + function hubDefaultHeaderTemplate(section) { + var element = _Global.document.createTextNode(typeof section.header === "object" ? JSON.stringify(section.header) : ('' + section.header)); + return element; + } + + var createEvent = _Events._createEventProperty; + var eventNames = { + contentAnimating: "contentanimating", + headerInvoked: "headerinvoked", + loadingStateChanged: "loadingstatechanged" + }; + + // Delay time before progress dots are shown when loading hub section(s) on screen. + var progressDelay = 500; + + var verticalNames = { + scrollPos: "scrollTop", + scrollSize: "scrollHeight", + offsetPos: "offsetTop", + offsetSize: "offsetHeight", + oppositeOffsetSize: "offsetWidth", + marginStart: "marginTop", + marginEnd: "marginBottom", + borderStart: "borderTopWidth", + borderEnd: "borderBottomWidth", + paddingStart: "paddingTop", + paddingEnd: "paddingBottom" + }; + var rtlHorizontalNames = { + scrollPos: "scrollLeft", + scrollSize: "scrollWidth", + offsetPos: "offsetLeft", + offsetSize: "offsetWidth", + oppositeOffsetSize: "offsetHeight", + marginStart: "marginRight", + marginEnd: "marginLeft", + borderStart: "borderRightWidth", + borderEnd: "borderLeftWidth", + paddingStart: "paddingRight", + paddingEnd: "paddingLeft" + }; + var ltrHorizontalNames = { + scrollPos: "scrollLeft", + scrollSize: "scrollWidth", + offsetPos: "offsetLeft", + offsetSize: "offsetWidth", + oppositeOffsetSize: "offsetHeight", + marginStart: "marginLeft", + marginEnd: "marginRight", + borderStart: "borderLeftWidth", + borderEnd: "borderRightWidth", + paddingStart: "paddingLeft", + paddingEnd: "paddingRight" + }; + + var Hub = _Base.Class.define(function Hub_ctor(element, options) { + /// + /// + /// Creates a new Hub control. + /// + /// + /// The DOM element that hosts the Hub control. + /// + /// + /// An object that contains one or more property/value pairs to apply to the new control. + /// Each property of the options object corresponds to one of the control's properties or events. + /// Event names must begin with "on". For example, to provide a handler for the contentanimating event, + /// add a property named "oncontentanimating" to the options object and set its value to the event handler. + /// + /// + /// The new Hub. + /// + /// + /// + element = element || _Global.document.createElement("DIV"); + options = options || {}; + + if (element.winControl) { + throw new _ErrorFromName("WinJS.UI.Hub.DuplicateConstruction", strings.duplicateConstruction); + } + + this._id = element.id || _ElementUtilities._uniqueID(element); + this._writeProfilerMark("constructor,StartTM"); + + this._windowKeyDownHandlerBound = this._windowKeyDownHandler.bind(this); + _Global.addEventListener('keydown', this._windowKeyDownHandlerBound); + + // Attaching JS control to DOM element + element.winControl = this; + this._element = element; + _ElementUtilities.addClass(this.element, Hub._ClassName.hub); + _ElementUtilities.addClass(this.element, "win-disposable"); + + this._viewportElement = _Global.document.createElement("DIV"); + this._viewportElement.className = Hub._ClassName.hubViewport; + this._element.appendChild(this._viewportElement); + this._viewportElement.setAttribute("role", "group"); + this._viewportElement.setAttribute("aria-label", strings.hubViewportAriaLabel); + + this._surfaceElement = _Global.document.createElement("DIV"); + this._surfaceElement.className = Hub._ClassName.hubSurface; + this._viewportElement.appendChild(this._surfaceElement); + + // Start invisible so that you do not see the content loading until the sections are ready. + this._visible = false; + this._viewportElement.style.opacity = 0; + + if (!options.orientation) { + this._orientation = _UI.Orientation.horizontal; + _ElementUtilities.addClass(this.element, Hub._ClassName.hubHorizontal); + } + + this._fireEntrance = true; + this._animateEntrance = true; + this._loadId = 0; + this.runningAnimations = new Promise.wrap(); + this._currentIndexForSezo = 0; + + // This internally assigns this.sections which causes section to be used (even from options) before + // scrollPosition or sectionOnScreen. + this._parse(); + + _Control.setOptions(this, options); + + _ElementUtilities._addEventListener(this.element, "focusin", this._focusin.bind(this), false); + this.element.addEventListener("keydown", this._keyDownHandler.bind(this)); + this.element.addEventListener("click", this._clickHandler.bind(this)); + this._resizeHandlerBound = this._resizeHandler.bind(this); + this.element.addEventListener("mselementresize", this._resizeHandlerBound); + _ElementUtilities._resizeNotifier.subscribe(this.element, this._resizeHandlerBound); + this._viewportElement.addEventListener("scroll", this._scrollHandler.bind(this)); + this._surfaceElement.addEventListener("mselementresize", this._contentResizeHandler.bind(this)); + + this._handleSectionChangedBind = this._handleSectionChanged.bind(this); + this._handleSectionInsertedBind = this._handleSectionInserted.bind(this); + this._handleSectionMovedBind = this._handleSectionMoved.bind(this); + this._handleSectionRemovedBind = this._handleSectionRemoved.bind(this); + this._handleSectionReloadBind = this._handleSectionReload.bind(this); + + this._refresh(); + + this._writeProfilerMark("constructor,StopTM"); + }, { + /// + element: { + get: function () { + return this._element; + } + }, + /// + /// Gets or sets the orientation of sections within the Hub. + /// + /// + orientation: { + get: function () { + return this._orientation; + }, + set: function (value) { + if (value === this._orientation) { + return; + } + this._measured = false; + // clear existing scroll before we switch orientation + if (this._names) { // handle setting orientation before we measure + var newScrollPos = {}; + newScrollPos[this._names.scrollPos] = 0; + _ElementUtilities.setScrollPosition(this._viewportElement, newScrollPos); + } + if (value === _UI.Orientation.vertical) { + _ElementUtilities.removeClass(this.element, Hub._ClassName.hubHorizontal); + _ElementUtilities.addClass(this.element, Hub._ClassName.hubVertical); + } else { + value = _UI.Orientation.horizontal; + _ElementUtilities.removeClass(this.element, Hub._ClassName.hubVertical); + _ElementUtilities.addClass(this.element, Hub._ClassName.hubHorizontal); + } + this._orientation = value; + Scheduler.schedule(this._updateSnapList.bind(this), Scheduler.Priority.idle); + } + }, + /// + /// Gets or sets the WinJS.Binding.List of HubSection objects that belong to this Hub. + /// + /// + sections: { + get: function () { + if (this._pendingSections) { + return this._pendingSections; + } + return this._sections; + }, + set: function (value) { + var resetScrollPosition = !this._pendingSections; + this._pendingSections = value; + this._refresh(); + if (resetScrollPosition) { + this.scrollPosition = 0; + } + } + }, + /// + /// Gets or sets the WinJS.Binding.Template or template function that creates the DOM elements + /// which represent the header for each HubSection. Each header can + /// contain multiple DOM elements, but we recommend that it have a single + /// root element. + /// + /// + headerTemplate: { + get: function () { + if (this._pendingHeaderTemplate) { + return this._pendingHeaderTemplate; + } + + if (!this._headerTemplate) { + this._headerTemplate = hubDefaultHeaderTemplate; + } + + return this._headerTemplate; + }, + set: function (value) { + this._pendingHeaderTemplate = value || hubDefaultHeaderTemplate; + this._refresh(); + } + }, + /// + /// Gets or sets the position of the Hub's scrollbar. + /// + /// + scrollPosition: { + get: function () { + if (+this._pendingScrollLocation === this._pendingScrollLocation) { + return this._pendingScrollLocation; + } + + this._measure(); + return this._scrollPosition; + }, + set: function (value) { + value = Math.max(0, value); + if (this._pendingRefresh) { + // Unable to constrain length because sections may have changed. + this._pendingScrollLocation = value; + this._pendingSectionOnScreen = null; + } else { + this._measure(); + var targetScrollPos = Math.max(0, Math.min(this._scrollLength - this._viewportSize, value)); + this._scrollPosition = targetScrollPos; + var newScrollPos = {}; + newScrollPos[this._names.scrollPos] = targetScrollPos; + _ElementUtilities.setScrollPosition(this._viewportElement, newScrollPos); + } + } + }, + + /// + /// Gets or sets the index of first section in view. This property is useful for restoring a previous view when your app launches or resumes. + /// + /// + sectionOnScreen: { + get: function () { + if (+this._pendingSectionOnScreen === this._pendingSectionOnScreen) { + return this._pendingSectionOnScreen; + } + + this._measure(); + for (var i = 0; i < this._sectionSizes.length; i++) { + var sectionSize = this._sectionSizes[i]; + if ((sectionSize.offset + sectionSize.size - sectionSize.borderEnd - sectionSize.paddingEnd) > (this._scrollPosition + this._startSpacer + sectionSize.borderStart + sectionSize.paddingStart)) { + return i; + } + } + return -1; + }, + set: function (value) { + value = Math.max(0, value); + if (this._pendingRefresh) { + this._pendingSectionOnScreen = value; + this._pendingScrollLocation = null; + } else { + this._measure(); + if (value >= 0 && value < this._sectionSizes.length) { + this._scrollToSection(value); + } + } + } + }, + /// + /// Gets or sets the index of first section at least partially in view. Use for animations. + /// + /// + indexOfFirstVisible: { + get: function () { + this._measure(); + for (var i = 0; i < this._sectionSizes.length; i++) { + var sectionSize = this._sectionSizes[i]; + if ((sectionSize.offset + sectionSize.size - sectionSize.borderEnd - sectionSize.paddingEnd) > this._scrollPosition) { + return i; + } + } + return -1; + } + }, + /// + /// Gets or sets the index of last section at least partially in view. Use for animations. + /// + /// + indexOfLastVisible: { + get: function () { + this._measure(); + for (var i = this._sectionSizes.length - 1; i >= 0; i--) { + var sectionSize = this._sectionSizes[i]; + if ((sectionSize.offset + sectionSize.paddingStart + sectionSize.borderStart) < (this._scrollPosition + this._viewportSize)) { + return i; + } + } + return -1; + } + }, + + /// + /// Raised when the user clicks on an interactive header. + /// + /// + onheaderinvoked: createEvent(eventNames.headerInvoked), + + /// + /// Raised when the loadingState of the Hub changes. + /// + /// + onloadingstatechanged: createEvent(eventNames.loadingStateChanged), + + /// + /// Raised when Hub is about to play entrance, contentTransition, insert, or remove animations. + /// + /// + oncontentanimating: createEvent(eventNames.contentAnimating), + + _refresh: function hub_refresh() { + if (this._pendingRefresh) { + return; + } + + this._loadId++; + this._setState(Hub.LoadingState.loading); + // This is to coalesce property setting operations such as sections and scrollPosition. + this._pendingRefresh = true; + + Scheduler.schedule(this._refreshImpl.bind(this), Scheduler.Priority.high); + }, + _refreshImpl: function hub_refreshImpl() { + if (this._disposed) { + return; + } + + var fadeOutAnimation = Promise.wrap(); + if (this._pendingSections) { + this._animateEntrance = true; + this._fireEntrance = !this._visible; + if (!this._fireEntrance) { + this._visible = false; + this._viewportElement.style.opacity = 0; + + if (_TransitionAnimation.isAnimationEnabled()) { + var animateTransition = this._fireEvent(Hub._EventName.contentAnimating, { + type: Hub.AnimationType.contentTransition + }); + + if (animateTransition) { + this._viewportElement.style["-ms-overflow-style"] = "none"; + fadeOutAnimation = Animations.fadeOut(this._viewportElement).then(function () { + this._viewportElement.style["-ms-overflow-style"] = ""; + }.bind(this)); + } + this._animateEntrance = animateTransition; + } + } + } + + fadeOutAnimation.done(this._applyProperties.bind(this)); + }, + _applyProperties: function hub_applyProperties() { + if (this._disposed) { + return; + } + + this._pendingRefresh = false; + + var needsToLoadSections = false; + if (this._pendingSections) { + needsToLoadSections = true; + this._updateEvents(this._sections, this._pendingSections); + this._sections = this._pendingSections; + this._pendingSections = null; + // Remove any declaratively specified hub sections before attachSections. + while (this.element.firstElementChild !== this._viewportElement) { + var toRemove = this.element.firstElementChild; + toRemove.parentNode.removeChild(toRemove); + } + _ElementUtilities.empty(this._surfaceElement); + } + + if (this._pendingHeaderTemplate) { + this._headerTemplate = this._pendingHeaderTemplate; + this._pendingHeaderTemplate = null; + } + + this._assignHeaderTemplate(); + + if (needsToLoadSections) { + this._attachSections(); + } + + // Scroll after headers are rendered and sections are attached so the scroll thumb is correct. + if (+this._pendingSectionOnScreen === this._pendingSectionOnScreen) { + // If there are both pending section on screen and scroll location use section on screen. + this.sectionOnScreen = this._pendingSectionOnScreen; + } else if (+this._pendingScrollLocation === this._pendingScrollLocation) { + this.scrollPosition = this._pendingScrollLocation; + } else { + // Sections reset without sectionOnScreen or scrollPosition APIs. + this.scrollPosition = 0; + } + + this._pendingSectionOnScreen = null; + this._pendingScrollLocation = null; + + // Using current (or new) scroll location load the sections + this._setState(Hub.LoadingState.loading); + this._loadSections(); + }, + _handleSectionChanged: function hub_handleSectionChanged(ev) { + // Change is triggered by binding list setAt() API. + if (this._pendingSections) { + return; + } + + var newSection = ev.detail.newValue; + var oldSection = ev.detail.oldValue; + newSection._setHeaderTemplate(this.headerTemplate); + if (newSection.element !== oldSection.element) { + if (newSection.element.parentNode === this._surfaceElement) { + throw new _ErrorFromName("WinJS.UI.Hub.DuplicateSection", strings.duplicateSection); + } + + this._surfaceElement.insertBefore(newSection.element, oldSection.element); + this._surfaceElement.removeChild(oldSection.element); + this._measured = false; + + this._setState(Hub.LoadingState.loading); + this._loadSections(); + } + }, + _handleSectionInserted: function hub_handleSectionInserted(ev) { + // Insert is triggered by binding list insert APIs such as splice(), push(), and unshift(). + if (this._pendingSections) { + return; + } + + var index = ev.detail.index; + var section = ev.detail.value; + + if (section._animation) { + section._animation.cancel(); + } + + var animation; + var result = this._fireEvent(Hub._EventName.contentAnimating, { + type: Hub.AnimationType.insert, + index: index, + section: section + }); + + if (result) { + + var affectedElements = []; + + for (var i = index + 1; i < this.sections.length; i++) { + affectedElements.push(this.sections.getAt(i).element); + } + + animation = new Animations._createUpdateListAnimation([section.element], [], affectedElements); + } + + if (section.element.parentNode === this._surfaceElement) { + throw new _ErrorFromName("WinJS.UI.Hub.DuplicateSection", strings.duplicateSection); + } + + section._setHeaderTemplate(this.headerTemplate); + if (index < this.sections.length - 1) { + this._surfaceElement.insertBefore(section.element, this.sections.getAt(index + 1).element); + } else { + this._surfaceElement.appendChild(section.element); + } + this._measured = false; + + if (animation) { + var insertAnimation = animation.execute(); + this.runningAnimations = Promise.join([this.runningAnimations, insertAnimation]); + } + + this._setState(Hub.LoadingState.loading); + this._loadSections(); + }, + _handleSectionMoved: function hub_handleSectionMoved(ev) { + // Move is triggered by binding list move() API. + if (this._pendingSections) { + return; + } + + var newIndex = ev.detail.newIndex; + var section = ev.detail.value; + + if (newIndex < this.sections.length - 1) { + this._surfaceElement.insertBefore(section.element, this.sections.getAt(newIndex + 1).element); + } else { + this._surfaceElement.appendChild(section.element); + } + this._measured = false; + + this._setState(Hub.LoadingState.loading); + this._loadSections(); + }, + _handleSectionRemoved: function hub_handleSectionRemoved(ev) { + // Removed is triggered by binding list removal APIs such as splice(), pop(), and shift(). + if (this._pendingSections) { + return; + } + + var section = ev.detail.value; + var index = ev.detail.index; + + var animationPromise = Promise.wrap(); + var result = this._fireEvent(Hub._EventName.contentAnimating, { + type: Hub.AnimationType.remove, + index: index, + section: section + }); + + if (result) { + var affectedElements = []; + + for (var i = index; i < this.sections.length; i++) { + affectedElements.push(this.sections.getAt(i).element); + } + + var animation = new Animations._createUpdateListAnimation([], [section.element], affectedElements); + + this._measure(); + var offsetTop = section.element.offsetTop; + var offsetLeft = section.element.offsetLeft; + section.element.style.position = "absolute"; + section.element.style.top = offsetTop; + section.element.style.left = offsetLeft; + section.element.style.opacity = 0; + this._measured = false; + + animationPromise = animation.execute().then(function () { + section.element.style.position = ""; + section.element.style.top = ""; + section.element.style.left = ""; + section.element.style.opacity = 1; + }.bind(this)); + } + + animationPromise.done(function () { + if (!this._disposed) { + this._surfaceElement.removeChild(section.element); + this._measured = false; + } + }.bind(this)); + + // Store animation promise in case it is inserted before remove animation finishes. + section._animation = animationPromise; + this.runningAnimations = Promise.join([this.runningAnimations, animationPromise]); + + this._setState(Hub.LoadingState.loading); + this._loadSections(); + }, + _handleSectionReload: function hub_handleSectionReload() { + // Reload is triggered by large operations on the binding list such as reverse(). This causes + // _pendingSections to be true which ignores future insert/remove/modified/moved events until the new + // sections list is applied. + this.sections = this.sections; + }, + _updateEvents: function hub_updateEvents(oldSections, newSections) { + if (oldSections) { + oldSections.removeEventListener("itemchanged", this._handleSectionChangedBind); + oldSections.removeEventListener("iteminserted", this._handleSectionInsertedBind); + oldSections.removeEventListener("itemmoved", this._handleSectionMovedBind); + oldSections.removeEventListener("itemremoved", this._handleSectionRemovedBind); + oldSections.removeEventListener("reload", this._handleSectionReloadBind); + } + + if (newSections) { + newSections.addEventListener("itemchanged", this._handleSectionChangedBind); + newSections.addEventListener("iteminserted", this._handleSectionInsertedBind); + newSections.addEventListener("itemmoved", this._handleSectionMovedBind); + newSections.addEventListener("itemremoved", this._handleSectionRemovedBind); + newSections.addEventListener("reload", this._handleSectionReloadBind); + } + }, + _attachSections: function hub_attachSections() { + this._measured = false; + for (var i = 0; i < this.sections.length; i++) { + var section = this._sections.getAt(i); + if (section._animation) { + section._animation.cancel(); + } + if (section.element.parentNode === this._surfaceElement) { + throw new _ErrorFromName("WinJS.UI.Hub.DuplicateSection", strings.duplicateSection); + } + this._surfaceElement.appendChild(section.element); + } + }, + _assignHeaderTemplate: function hub_assignHeaderTemplate() { + this._measured = false; + for (var i = 0; i < this.sections.length; i++) { + var section = this._sections.getAt(i); + section._setHeaderTemplate(this.headerTemplate); + } + }, + _loadSection: function hub_loadSection(index) { + var section = this._sections.getAt(index); + return section._process().then(function resetVisibility() { + var style = section.contentElement.style; + if (style.visibility !== "") { + style.visibility = ""; + } + }); + }, + _loadSections: function hub_loadSections() { + // Used to know if another load has interrupted this one. + this._loadId++; + var loadId = this._loadId; + var that = this; + var onScreenItemsAnimatedPromise = Promise.wrap(); + var sectionIndicesToLoad = []; + var allSectionsLoadedPromise = Promise.wrap(); + + function loadNextSectionAfterPromise(promise) { + promise.then(function () { + Scheduler.schedule(loadNextSection, Scheduler.Priority.idle); + }); + } + + function loadNextSection() { + if (loadId === that._loadId && !that._disposed) { + if (sectionIndicesToLoad.length) { + var index = sectionIndicesToLoad.shift(); + var loadedPromise = that._loadSection(index); + loadNextSectionAfterPromise(loadedPromise); + } else { + allSectionsLoadedSignal.complete(); + } + } + } + + if (!this._showProgressPromise) { + this._showProgressPromise = Promise.timeout(progressDelay).then(function () { + if (this._disposed) { + return; + } + + if (!this._progressBar) { + this._progressBar = _Global.document.createElement("progress"); + _ElementUtilities.addClass(this._progressBar, Hub._ClassName.hubProgress); + this._progressBar.max = 100; + } + if (!this._progressBar.parentNode) { + this.element.insertBefore(this._progressBar, this._viewportElement); + } + this._showProgressPromise = null; + }.bind(this), function () { + this._showProgressPromise = null; + }.bind(this)); + } + + if (this.sections.length) { + var allSectionsLoadedSignal = new _Signal(); + allSectionsLoadedPromise = allSectionsLoadedSignal.promise; + // Synchronously load the sections on screen. + var synchronousProcessPromises = []; + var start = Math.max(0, this.indexOfFirstVisible); + var end = Math.max(0, this.indexOfLastVisible); + for (var i = start; i <= end; i++) { + synchronousProcessPromises.push(this._loadSection(i)); + } + + // Determine the order to load the rest of the sections. + start--; + end++; + while (start >= 0 || end < this.sections.length) { + if (end < this.sections.length) { + sectionIndicesToLoad.push(end); + end++; + } + if (start >= 0) { + sectionIndicesToLoad.push(start); + start--; + } + } + + var onScreenSectionsLoadedPromise = Promise.join(synchronousProcessPromises); + + // In case there are overlapping load calls + onScreenSectionsLoadedPromise.done(function () { + if (loadId === this._loadId && !that._disposed) { + if (this._showProgressPromise) { + this._showProgressPromise.cancel(); + } + + if (this._progressBar && this._progressBar.parentNode) { + this._progressBar.parentNode.removeChild(this._progressBar); + } + + Scheduler.schedule(function Hub_entranceAnimation() { + if (loadId === this._loadId && !that._disposed) { + if (!this._visible) { + this._visible = true; + this._viewportElement.style.opacity = 1; + + if (this._animateEntrance && _TransitionAnimation.isAnimationEnabled()) { + var eventDetail = { + type: Hub.AnimationType.entrance + }; + + if (!this._fireEntrance || this._fireEvent(Hub._EventName.contentAnimating, eventDetail)) { + this._viewportElement.style["-ms-overflow-style"] = "none"; + onScreenItemsAnimatedPromise = Animations.enterContent(this._viewportElement).then(function () { + this._viewportElement.style["-ms-overflow-style"] = ""; + }.bind(this)); + } + } + if (this._element === _Global.document.activeElement) { + this._moveFocusIn(this.sectionOnScreen); + } + } + } + }, Scheduler.Priority.high, this, "WinJS.UI.Hub.entranceAnimation"); + } + }.bind(this)); + + loadNextSectionAfterPromise(onScreenSectionsLoadedPromise); + } else { + if (this._showProgressPromise) { + this._showProgressPromise.cancel(); + } + + if (this._progressBar && this._progressBar.parentNode) { + this._progressBar.parentNode.removeChild(this._progressBar); + } + } + + Promise.join([this.runningAnimations, onScreenItemsAnimatedPromise, allSectionsLoadedPromise]).done(function () { + if (loadId === this._loadId && !that._disposed) { + this.runningAnimations = Promise.wrap(); + if (this._measured && this._scrollLength !== this._viewportElement[this._names.scrollSize]) { + // A section changed size during processing. Invalidate the Hub's measurements so that its + // API's work correctly within the loadingState=complete handler. + this._measured = false; + } + this._setState(Hub.LoadingState.complete); + Scheduler.schedule(this._updateSnapList.bind(this), Scheduler.Priority.idle); + } + }.bind(this)); + }, + /// + loadingState: { + get: function () { + return this._loadingState; + } + }, + _setState: function Hub_setState(state) { + if (state !== this._loadingState) { + this._writeProfilerMark("loadingStateChanged:" + state + ",info"); + this._loadingState = state; + var eventObject = _Global.document.createEvent("CustomEvent"); + eventObject.initCustomEvent(Hub._EventName.loadingStateChanged, true, false, { loadingState: state }); + this._element.dispatchEvent(eventObject); + } + }, + _parse: function hub_parse() { + var hubSections = []; + var hubSectionEl = this.element.firstElementChild; + + while (hubSectionEl !== this._viewportElement) { + ControlProcessor.processAll(hubSectionEl); + + var hubSectionContent = hubSectionEl.winControl; + if (hubSectionContent) { + hubSections.push(hubSectionContent); + } else { + throw new _ErrorFromName("WinJS.UI.Hub.InvalidContent", strings.invalidContent); + } + + var nextSectionEl = hubSectionEl.nextElementSibling; + hubSectionEl = nextSectionEl; + } + + this.sections = new BindingList.List(hubSections); + }, + _fireEvent: function hub_fireEvent(type, detail) { + // Returns true if ev.preventDefault() was not called + var event = _Global.document.createEvent("CustomEvent"); + event.initCustomEvent(type, true, true, detail); + return this.element.dispatchEvent(event); + }, + + _findHeaderTabStop: function hub_findHeaderTabStop(element) { + if (element.parentNode) { + if (_ElementUtilities._matchesSelector(element, ".win-hub-section-header-tabstop, .win-hub-section-header-tabstop *")) { + while (!_ElementUtilities.hasClass(element, "win-hub-section-header-tabstop")) { + element = element.parentElement; + } + return element; + } + } + return null; + }, + _isInteractive: function hub_isInteractive(element) { + // Helper method to skip keyboarding and clicks + + while (element && element !== _Global.document.body) { + if (element.classList.contains("win-interactive")) { + return true; + } + element = element.parentElement; + } + return false; + }, + _clickHandler: function hub_clickHandler(ev) { + var headerTabStopElement = this._findHeaderTabStop(ev.target); + if (headerTabStopElement && !this._isInteractive(ev.target)) { + var section = headerTabStopElement.parentElement.parentElement.winControl; + if (!section.isHeaderStatic) { + var sectionIndex = this.sections.indexOf(section); + this._fireEvent(Hub._EventName.headerInvoked, { + index: sectionIndex, + section: section + }); + } + } + }, + _resizeHandler: function hub_resizeHandler() { + // Viewport needs to be measured + this._measured = false; + Scheduler.schedule(this._updateSnapList.bind(this), Scheduler.Priority.idle); + }, + _contentResizeHandler: function hub_contentResizeHandler() { + // Sections and scroll length need to be measured + this._measured = false; + Scheduler.schedule(this._updateSnapList.bind(this), Scheduler.Priority.idle); + }, + _scrollHandler: function hub_scrollHandler() { + // Scroll location needs to be retrieved + this._measured = false; + + if (this._pendingSections) { + return; + } + + // Scroll events caused by users overwrite pending API modifications to scrollposition. + this._pendingScrollLocation = null; + this._pendingSectionOnScreen = null; + + if (!this._pendingScrollHandler) { + this._pendingScrollHandler = _BaseUtils._requestAnimationFrame(function () { + this._pendingScrollHandler = null; + + if (this._pendingSections) { + return; + } + + if (this.loadingState !== Hub.LoadingState.complete) { + this._loadSections(); + } + }.bind(this)); + } + }, + _measure: function hub_measure() { + // Any time a size changes (section growing, window resizing, etc) cachedSizes should be set to false + // and any time the variables need to be read again we should measure the variables. To avoid a lot of + // seperate layouts we measure the variables in a single batch. + if (!this._measured || this._scrollLength === 0) { + this._writeProfilerMark("measure,StartTM"); + this._measured = true; + + this._rtl = _Global.getComputedStyle(this._element, null).direction === "rtl"; + + if (this.orientation === _UI.Orientation.vertical) { + this._names = verticalNames; + } else { + if (this._rtl) { + this._names = rtlHorizontalNames; + } else { + this._names = ltrHorizontalNames; + } + } + + this._viewportSize = this._viewportElement[this._names.offsetSize]; + this._viewportOppositeSize = this._viewportElement[this._names.oppositeOffsetSize]; + this._scrollPosition = _ElementUtilities.getScrollPosition(this._viewportElement)[this._names.scrollPos]; + this._scrollLength = this._viewportElement[this._names.scrollSize]; + + var surfaceElementComputedStyle = _Global.getComputedStyle(this._surfaceElement); + this._startSpacer = parseFloat(surfaceElementComputedStyle[this._names.marginStart]) + parseFloat(surfaceElementComputedStyle[this._names.borderStart]) + parseFloat(surfaceElementComputedStyle[this._names.paddingStart]); + this._endSpacer = parseFloat(surfaceElementComputedStyle[this._names.marginEnd]) + parseFloat(surfaceElementComputedStyle[this._names.borderEnd]) + parseFloat(surfaceElementComputedStyle[this._names.paddingEnd]); + + this._sectionSizes = []; + for (var i = 0; i < this.sections.length; i++) { + var section = this.sections.getAt(i); + var computedSectionStyle = _Global.getComputedStyle(section.element); + this._sectionSizes[i] = { + offset: section.element[this._names.offsetPos], + // Reminder: offsetWidth doesn't include margins and also rounds. + size: section.element[this._names.offsetSize], + marginStart: parseFloat(computedSectionStyle[this._names.marginStart]), + marginEnd: parseFloat(computedSectionStyle[this._names.marginEnd]), + borderStart: parseFloat(computedSectionStyle[this._names.borderStart]), + borderEnd: parseFloat(computedSectionStyle[this._names.borderEnd]), + paddingStart: parseFloat(computedSectionStyle[this._names.paddingStart]), + paddingEnd: parseFloat(computedSectionStyle[this._names.paddingEnd]) + }; + + if (this._rtl && this.orientation === _UI.Orientation.horizontal) { + this._sectionSizes[i].offset = this._viewportSize - (this._sectionSizes[i].offset + this._sectionSizes[i].size); + } + } + + this._writeProfilerMark("measure,StopTM"); + } + }, + _updateSnapList: function hub_updateSnapList() { + this._writeProfilerMark("updateSnapList,StartTM"); + this._measure(); + + var snapList = "snapList("; + for (var i = 0; i < this._sectionSizes.length; i++) { + if (i > 0) { + snapList += ","; + } + var sectionSize = this._sectionSizes[i]; + snapList += (sectionSize.offset - sectionSize.marginStart - this._startSpacer) + "px"; + } + snapList += ")"; + + var snapListY = ""; + var snapListX = ""; + if (this.orientation === _UI.Orientation.vertical) { + snapListY = snapList; + } else { + snapListX = snapList; + } + + if (this._lastSnapPointY !== snapListY) { + this._lastSnapPointY = snapListY; + this._viewportElement.style['-ms-scroll-snap-points-y'] = snapListY; + } + + if (this._lastSnapPointX !== snapListX) { + this._lastSnapPointX = snapListX; + this._viewportElement.style['-ms-scroll-snap-points-x'] = snapListX; + } + + this._writeProfilerMark("updateSnapList,StopTM"); + }, + _scrollToSection: function Hub_scrollToSection(index, withAnimation) { + this._measure(); + var sectionSize = this._sectionSizes[index]; + var scrollPositionToShowStartMargin = Math.min(this._scrollLength - this._viewportSize, sectionSize.offset - sectionSize.marginStart - this._startSpacer); + + this._scrollTo(scrollPositionToShowStartMargin, withAnimation); + }, + _ensureVisible: function hub_ensureVisible(index, withAnimation) { + this._measure(); + var targetScrollPos = this._ensureVisibleMath(index, this._scrollPosition); + this._scrollTo(targetScrollPos, withAnimation); + }, + _ensureVisibleMath: function hub_ensureVisibleMath(index, targetScrollPos) { + this._measure(); + var sectionSize = this._sectionSizes[index]; + + var scrollPositionToShowStartMargin = Math.min(this._scrollLength - this._viewportSize, sectionSize.offset - sectionSize.marginStart - this._startSpacer); + var scrollPositionToShowEndMargin = Math.max(0, sectionSize.offset + sectionSize.size + sectionSize.marginEnd + this._endSpacer - this._viewportSize + 1); + if (targetScrollPos > scrollPositionToShowStartMargin) { + targetScrollPos = scrollPositionToShowStartMargin; + } else if (targetScrollPos < scrollPositionToShowEndMargin) { + targetScrollPos = Math.min(scrollPositionToShowStartMargin, scrollPositionToShowEndMargin); + } + + return targetScrollPos; + }, + _scrollTo: function hub_scrollTo(scrollPos, withAnimation) { + this._scrollPosition = scrollPos; + if (withAnimation) { + if (this.orientation === _UI.Orientation.vertical) { + _ElementUtilities._zoomTo(this._viewportElement, { contentX: 0, contentY: this._scrollPosition, viewportX: 0, viewportY: 0 }); + } else { + _ElementUtilities._zoomTo(this._viewportElement, { contentX: this._scrollPosition, contentY: 0, viewportX: 0, viewportY: 0 }); + } + } else { + var newScrollPos = {}; + newScrollPos[this._names.scrollPos] = this._scrollPosition; + _ElementUtilities.setScrollPosition(this._viewportElement, newScrollPos); + } + }, + _windowKeyDownHandler: function hub_windowKeyDownHandler(ev) { + // Include tab and shift tab. Note: Alt Key + Tab and Windows Key + Tab do not fire keydown with ev.key === "Tab". + if (ev.keyCode === Key.tab) { + this._tabSeenLast = true; + + var that = this; + _BaseUtils._yieldForEvents(function () { + that._tabSeenLast = false; + }); + } + }, + _focusin: function hub_focusin(ev) { + // On focus we call ensureVisible to handle the tab or shift/tab to header. However if the + // focus was caused by a pointer down event we skip the focus. + if (this._tabSeenLast) { + var headerTabStopElement = this._findHeaderTabStop(ev.target); + if (headerTabStopElement && !this._isInteractive(ev.target)) { + var sectionIndex = this.sections.indexOf(headerTabStopElement.parentElement.parentElement.winControl); + if (sectionIndex > -1) { + this._ensureVisible(sectionIndex, true); + } + } + } + + // Always remember the focused section for SemanticZoom. + var sectionElement = ev.target; + while (sectionElement && !_ElementUtilities.hasClass(sectionElement, _Section.HubSection._ClassName.hubSection)) { + sectionElement = sectionElement.parentElement; + } + if (sectionElement) { + var sectionIndex = this.sections.indexOf(sectionElement.winControl); + if (sectionIndex > -1) { + this._currentIndexForSezo = sectionIndex; + } + } + + if (ev.target === this.element) { + var indexToFocus; + if (+this._sectionToFocus === this._sectionToFocus && this._sectionToFocus >= 0 && this._sectionToFocus < this.sections.length) { + indexToFocus = this._sectionToFocus; + this._sectionToFocus = null; + } else { + indexToFocus = this.sectionOnScreen; + } + + this._moveFocusIn(indexToFocus); + } + }, + _moveFocusIn: function hub_moveFocusIn(indexToFocus) { + if (indexToFocus >= 0) { + for (var i = indexToFocus; i < this.sections.length; i++) { + var section = this.sections.getAt(i); + + var focusAttempt = _ElementUtilities._trySetActive(section._headerTabStopElement, this._viewportElement); + + if (focusAttempt) { + return; + } + + if (_ElementUtilities._setActiveFirstFocusableElement(section.contentElement, this._viewportElement)) { + return; + } + } + + for (var i = indexToFocus - 1; i >= 0; i--) { + var section = this.sections.getAt(i); + + if (_ElementUtilities._setActiveFirstFocusableElement(section.contentElement, this._viewportElement)) { + return; + } + + var focusAttempt = _ElementUtilities._trySetActive(section._headerTabStopElement, this._viewportElement); + + if (focusAttempt) { + return; + } + } + } + }, + _keyDownHandler: function hub_keyDownHandler(ev) { + if (this._isInteractive(ev.target) || _ElementUtilities._hasCursorKeysBehaviors(ev.target)) { + return; + } + + var leftKey = this._rtl ? Key.rightArrow : Key.leftArrow; + var rightKey = this._rtl ? Key.leftArrow : Key.rightArrow; + + if (ev.keyCode === Key.upArrow || ev.keyCode === Key.downArrow || ev.keyCode === Key.leftArrow || ev.keyCode === Key.rightArrow || ev.keyCode === Key.pageUp || ev.keyCode === Key.pageDown) { + var headerTabStopElement = this._findHeaderTabStop(ev.target); + if (headerTabStopElement) { + var currentSection = this.sections.indexOf(headerTabStopElement.parentElement.parentElement.winControl); + var targetSectionIndex; + var useEnsureVisible = false; + // Page up/down go to the next/previous header and line it up with the app header. Up/Right/Down/Left + // move focus to the next/previous header and move it on screen (app header distance from either edge). + if (ev.keyCode === Key.pageDown || + (this.orientation === _UI.Orientation.horizontal && ev.keyCode === rightKey) || + (this.orientation === _UI.Orientation.vertical && ev.keyCode === Key.downArrow)) { + // Do not include hidden headers. + for (var i = currentSection + 1; i < this.sections.length; i++) { + if (this._tryFocus(i)) { + targetSectionIndex = i; + break; + } + } + } else if (ev.keyCode === Key.pageUp || + (this.orientation === _UI.Orientation.horizontal && ev.keyCode === leftKey) || + (this.orientation === _UI.Orientation.vertical && ev.keyCode === Key.upArrow)) { + // Do not include hidden headers. + for (var i = currentSection - 1; i >= 0; i--) { + if (this._tryFocus(i)) { + targetSectionIndex = i; + break; + } + } + } + if (ev.keyCode === Key.upArrow || ev.keyCode === Key.downArrow || ev.keyCode === Key.leftArrow || ev.keyCode === Key.rightArrow) { + useEnsureVisible = true; + } + + if (+targetSectionIndex === targetSectionIndex) { + if (useEnsureVisible) { + this._ensureVisible(targetSectionIndex, true); + } else { + this._scrollToSection(targetSectionIndex, true); + } + ev.preventDefault(); + } + } + } else if (ev.keyCode === Key.home || ev.keyCode === Key.end) { + // Home/End scroll to start/end and leave focus where it is. + this._measure(); + var maxScrollPos = Math.max(0, this._scrollLength - this._viewportSize); + this._scrollTo(ev.keyCode === Key.home ? 0 : maxScrollPos, true); + ev.preventDefault(); + } + }, + _tryFocus: function hub_tryFocus(index) { + var targetSection = this.sections.getAt(index); + + _ElementUtilities._setActive(targetSection._headerTabStopElement, this._viewportElement); + + return _Global.document.activeElement === targetSection._headerTabStopElement; + }, + /// + /// Gets a ZoomableView. This API supports the SemanticZoom infrastructure + /// and is not intended to be used directly from your code. + /// + /// + zoomableView: { + get: function zoomableView_get() { + if (!this._zoomableView) { + this._zoomableView = new ZoomableView(this); + } + + return this._zoomableView; + } + }, + _getPanAxis: function hub_getPanAxis() { + return this.orientation === _UI.Orientation.horizontal ? "horizontal" : "vertical"; + }, + _configureForZoom: function hub_configureForZoom() { + // Nothing to configure. + }, + _setCurrentItem: function hub_setCurrentItem(x, y) { + var offset; + if (this.orientation === _UI.Orientation.horizontal) { + offset = x; + } else { + offset = y; + } + + this._measure(); + offset = offset + this._scrollPosition; + this._currentIndexForSezo = this._sectionSizes.length - 1; + for (var i = 1; i < this._sectionSizes.length; i++) { + var sectionSize = this._sectionSizes[i]; + if (sectionSize.offset - sectionSize.marginStart > offset) { + this._currentIndexForSezo = i - 1; + break; + } + } + }, + _getCurrentItem: function hub_getCurrentItem() { + var itemPosition; + if (this._sectionSizes.length > 0) { + this._measure(); + var index = Math.max(0, Math.min(this._currentIndexForSezo, this._sectionSizes.length)); + var sectionSize = this._sectionSizes[index]; + if (this.orientation === _UI.Orientation.horizontal) { + itemPosition = { + left: Math.max(0, sectionSize.offset - sectionSize.marginStart - this._scrollPosition), + top: 0, + width: sectionSize.size, + height: this._viewportOppositeSize + }; + } else { + itemPosition = { + left: 0, + top: Math.max(0, sectionSize.offset - sectionSize.marginStart - this._scrollPosition), + width: this._viewportOppositeSize, + height: sectionSize.size, + }; + } + + var section = this.sections.getAt(index); + // BUGBUG: 53301 ListView and Hub should document what they expect to be returned from the + // getCurrentItem so that positionItem apis line up. ListView zoomed out expects an object with + // groupIndexHint, groupKey, or groupDescription. Hub expects an object with index. + return Promise.wrap({ item: { data: section, index: index, groupIndexHint: index }, position: itemPosition }); + } + }, + _beginZoom: function hub_beginZoom() { + // Hide scroll thumb. + this._viewportElement.style["-ms-overflow-style"] = "none"; + }, + _positionItem: function hub_positionItem(item, position) { + if (item.index >= 0 && item.index < this._sectionSizes.length) { + this._measure(); + var sectionSize = this._sectionSizes[item.index]; + + var offsetFromViewport; + if (this.orientation === _UI.Orientation.horizontal) { + offsetFromViewport = position.left; + } else { + offsetFromViewport = position.top; + } + + this._sectionToFocus = item.index; + + var targetScrollPosition = sectionSize.offset - offsetFromViewport; + // clamp section: + var targetScrollPosition = this._ensureVisibleMath(item.index, targetScrollPosition); + + this._scrollPosition = targetScrollPosition; + var newScrollPos = {}; + newScrollPos[this._names.scrollPos] = this._scrollPosition; + _ElementUtilities.setScrollPosition(this._viewportElement, newScrollPos); + } + }, + _endZoom: function hub_endZoom() { + // Show scroll thumb. + this._viewportElement.style["-ms-overflow-style"] = ""; + }, + _writeProfilerMark: function hub_writeProfilerMark(text) { + var message = "WinJS.UI.Hub:" + this._id + ":" + text; + _WriteProfilerMark(message); + _Log.log && _Log.log(message, null, "hubprofiler"); + }, + dispose: function hub_dispose() { + /// + /// + /// Disposes this control. + /// + /// + /// + if (this._disposed) { + return; + } + this._disposed = true; + + _Global.removeEventListener('keydown', this._windowKeyDownHandlerBound); + _ElementUtilities._resizeNotifier.unsubscribe(this.element, this._resizeHandlerBound); + + this._updateEvents(this._sections); + + for (var i = 0; i < this.sections.length; i++) { + this.sections.getAt(i).dispose(); + } + } + }, { + /// + /// Specifies whether the Hub animation is an entrance animation or a transition animation. + /// + /// + AnimationType: { + /// + /// The animation plays when the Hub is first displayed. + /// + /// + entrance: "entrance", + /// + /// The animation plays when the Hub is changing its content. + /// + /// + contentTransition: "contentTransition", + /// + /// The animation plays when a section is inserted into the Hub. + /// + /// + insert: "insert", + /// + /// The animation plays when a section is removed into the Hub. + /// + /// + remove: "remove", + }, + /// + /// Gets the current loading state of the Hub. + /// + /// + LoadingState: { + /// + /// The Hub is loading sections. + /// + /// + loading: "loading", + /// + /// All sections are loaded and animations are complete. + /// + /// + complete: "complete" + }, + // Names of classes used by the Hub. + _ClassName: { + hub: "win-hub", + hubSurface: "win-hub-surface", + hubProgress: "win-hub-progress", + hubViewport: "win-hub-viewport", + hubVertical: "win-hub-vertical", + hubHorizontal: "win-hub-horizontal", + }, + // Names of events fired by the Hub. + _EventName: { + contentAnimating: eventNames.contentAnimating, + headerInvoked: eventNames.headerInvoked, + loadingStateChanged: eventNames.loadingStateChanged + }, + }); + + _Base.Class.mix(Hub, _Control.DOMEventMixin); + + var ZoomableView = _Base.Class.define(function ZoomableView_ctor(hub) { + this._hub = hub; + }, { + getPanAxis: function () { + return this._hub._getPanAxis(); + }, + configureForZoom: function (isZoomedOut, isCurrentView, triggerZoom, prefetchedPages) { + this._hub._configureForZoom(isZoomedOut, isCurrentView, triggerZoom, prefetchedPages); + }, + setCurrentItem: function (x, y) { + this._hub._setCurrentItem(x, y); + }, + getCurrentItem: function () { + return this._hub._getCurrentItem(); + }, + beginZoom: function () { + this._hub._beginZoom(); + }, + positionItem: function (item, position) { + return this._hub._positionItem(item, position); + }, + endZoom: function (isCurrentView) { + this._hub._endZoom(isCurrentView); + } + }); + + var strings = { + get duplicateConstruction() { return "Invalid argument: Controls may only be instantiated one time for each DOM element"; }, + get duplicateSection() { return "Hub duplicate sections: Each HubSection must be unique"; }, + get invalidContent() { return "Invalid content: Hub content must be made up of HubSections."; }, + get hubViewportAriaLabel() { return _Resources._getWinJSString("ui/hubViewportAriaLabel").value; } + }; + + return Hub; + }) + }); + +}); + +define('require-style!less/styles-lightdismissservice',[],function(){}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +define('WinJS/_LightDismissService',["require", "exports", './Application', './Core/_Base', './Core/_BaseUtils', './Utilities/_ElementUtilities', './Core/_Global', './Utilities/_KeyboardBehavior', './Core/_Log', './Core/_Resources'], function (require, exports, Application, _Base, _BaseUtils, _ElementUtilities, _Global, _KeyboardBehavior, _Log, _Resources) { + require(["require-style!less/styles-lightdismissservice"]); + "use strict"; + var baseZIndex = 1000; + var Strings = { + get closeOverlay() { + return _Resources._getWinJSString("ui/closeOverlay").value; + } + }; + exports._ClassNames = { + _clickEater: "win-clickeater" + }; + var EventNames = { + requestingFocusOnKeyboardInput: "requestingfocusonkeyboardinput" + }; + exports.LightDismissalReasons = { + tap: "tap", + lostFocus: "lostFocus", + escape: "escape", + hardwareBackButton: "hardwareBackButton", + windowResize: "windowResize", + windowBlur: "windowBlur" + }; + // Built-in implementations of ILightDismissable's onShouldLightDismiss. + exports.DismissalPolicies = { + light: function LightDismissalPolicies_light_onShouldLightDismiss(info) { + switch (info.reason) { + case exports.LightDismissalReasons.tap: + case exports.LightDismissalReasons.escape: + if (info.active) { + return true; + } + else { + info.stopPropagation(); + return false; + } + break; + case exports.LightDismissalReasons.hardwareBackButton: + if (info.active) { + info.preventDefault(); // prevent backwards navigation in the app + return true; + } + else { + info.stopPropagation(); + return false; + } + break; + case exports.LightDismissalReasons.lostFocus: + case exports.LightDismissalReasons.windowResize: + case exports.LightDismissalReasons.windowBlur: + return true; + } + }, + modal: function LightDismissalPolicies_modal_onShouldLightDismiss(info) { + // Light dismiss cues should not be seen by dismissables behind the modal + info.stopPropagation(); + switch (info.reason) { + case exports.LightDismissalReasons.tap: + case exports.LightDismissalReasons.lostFocus: + case exports.LightDismissalReasons.windowResize: + case exports.LightDismissalReasons.windowBlur: + return false; + break; + case exports.LightDismissalReasons.escape: + return info.active; + break; + case exports.LightDismissalReasons.hardwareBackButton: + info.preventDefault(); // prevent backwards navigation in the app + return info.active; + break; + } + }, + sticky: function LightDismissalPolicies_sticky_onShouldLightDismiss(info) { + info.stopPropagation(); + return false; + } + }; + var KeyboardInfoType = { + keyDown: "keyDown", + keyUp: "keyUp", + keyPress: "keyPress" + }; + var AbstractDismissableElement = (function () { + function AbstractDismissableElement(args) { + this.element = args.element; + this.element.tabIndex = args.tabIndex; + this.onLightDismiss = args.onLightDismiss; + // Allow the caller to override the default implementations of our ILightDismissable methods. + if (args.onTakeFocus) { + this.onTakeFocus = args.onTakeFocus; + } + if (args.onShouldLightDismiss) { + this.onShouldLightDismiss = args.onShouldLightDismiss; + } + this._ldeOnKeyDownBound = this._ldeOnKeyDown.bind(this); + this._ldeOnKeyUpBound = this._ldeOnKeyUp.bind(this); + this._ldeOnKeyPressBound = this._ldeOnKeyPress.bind(this); + } + AbstractDismissableElement.prototype.restoreFocus = function () { + var activeElement = _Global.document.activeElement; + if (activeElement && this.containsElement(activeElement)) { + this._ldeCurrentFocus = activeElement; + return true; + } + else { + // If the last input type was keyboard, use focus() so a keyboard focus visual is drawn. + // Otherwise, use setActive() so no focus visual is drawn. + var useSetActive = !_KeyboardBehavior._keyboardSeenLast; + return this._ldeCurrentFocus && this.containsElement(this._ldeCurrentFocus) && _ElementUtilities._tryFocusOnAnyElement(this._ldeCurrentFocus, useSetActive); + } + }; + AbstractDismissableElement.prototype._ldeOnKeyDown = function (eventObject) { + this._ldeService.keyDown(this, eventObject); + }; + AbstractDismissableElement.prototype._ldeOnKeyUp = function (eventObject) { + this._ldeService.keyUp(this, eventObject); + }; + AbstractDismissableElement.prototype._ldeOnKeyPress = function (eventObject) { + this._ldeService.keyPress(this, eventObject); + }; + // ILightDismissable + // + AbstractDismissableElement.prototype.setZIndex = function (zIndex) { + this.element.style.zIndex = zIndex; + }; + AbstractDismissableElement.prototype.getZIndexCount = function () { + return 1; + }; + AbstractDismissableElement.prototype.containsElement = function (element) { + return this.element.contains(element); + }; + AbstractDismissableElement.prototype.onTakeFocus = function (useSetActive) { + this.restoreFocus() || _ElementUtilities._focusFirstFocusableElement(this.element, useSetActive) || _ElementUtilities._tryFocusOnAnyElement(this.element, useSetActive); + }; + AbstractDismissableElement.prototype.onFocus = function (element) { + this._ldeCurrentFocus = element; + }; + AbstractDismissableElement.prototype.onShow = function (service) { + this._ldeService = service; + this.element.addEventListener("keydown", this._ldeOnKeyDownBound); + this.element.addEventListener("keyup", this._ldeOnKeyUpBound); + this.element.addEventListener("keypress", this._ldeOnKeyPressBound); + }; + AbstractDismissableElement.prototype.onHide = function () { + this._ldeCurrentFocus = null; + this._ldeService = null; + this.element.removeEventListener("keydown", this._ldeOnKeyDownBound); + this.element.removeEventListener("keyup", this._ldeOnKeyUpBound); + this.element.removeEventListener("keypress", this._ldeOnKeyPressBound); + }; + // Concrete subclasses are expected to implement these. + AbstractDismissableElement.prototype.onKeyInStack = function (info) { + }; + AbstractDismissableElement.prototype.onShouldLightDismiss = function (info) { + return false; + }; + // Consumers of concrete subclasses of AbstractDismissableElement are expected to + // provide these as parameters to the constructor. + AbstractDismissableElement.prototype.onLightDismiss = function (info) { + }; + return AbstractDismissableElement; + })(); + var LightDismissableElement = (function (_super) { + __extends(LightDismissableElement, _super); + function LightDismissableElement() { + _super.apply(this, arguments); + } + LightDismissableElement.prototype.onKeyInStack = function (info) { + }; + LightDismissableElement.prototype.onShouldLightDismiss = function (info) { + return exports.DismissalPolicies.light(info); + }; + return LightDismissableElement; + })(AbstractDismissableElement); + exports.LightDismissableElement = LightDismissableElement; + var ModalElement = (function (_super) { + __extends(ModalElement, _super); + function ModalElement() { + _super.apply(this, arguments); + } + ModalElement.prototype.onKeyInStack = function (info) { + // stopPropagation so that none of the app's other event handlers will see the event. + // Don't preventDefault so that the browser's hotkeys will still work. + info.stopPropagation(); + }; + ModalElement.prototype.onShouldLightDismiss = function (info) { + return exports.DismissalPolicies.modal(info); + }; + return ModalElement; + })(AbstractDismissableElement); + exports.ModalElement = ModalElement; + // An implementation of ILightDismissable that represents the HTML body element. It can never be dismissed. The + // service should instantiate one of these to act as the bottommost light dismissable at all times (it isn't expected + // for anybody else to instantiate one). It takes care of restoring focus when the last dismissable is dismissed. + var LightDismissableBody = (function () { + function LightDismissableBody() { + } + LightDismissableBody.prototype.setZIndex = function (zIndex) { + }; + LightDismissableBody.prototype.getZIndexCount = function () { + return 1; + }; + LightDismissableBody.prototype.containsElement = function (element) { + return _Global.document.body.contains(element); + }; + LightDismissableBody.prototype.onTakeFocus = function (useSetActive) { + this.currentFocus && this.containsElement(this.currentFocus) && _ElementUtilities._tryFocusOnAnyElement(this.currentFocus, useSetActive); + }; + LightDismissableBody.prototype.onFocus = function (element) { + this.currentFocus = element; + }; + LightDismissableBody.prototype.onShow = function (service) { + }; + LightDismissableBody.prototype.onHide = function () { + this.currentFocus = null; + }; + LightDismissableBody.prototype.onKeyInStack = function (info) { + }; + LightDismissableBody.prototype.onShouldLightDismiss = function (info) { + return false; + }; + LightDismissableBody.prototype.onLightDismiss = function (info) { + }; + return LightDismissableBody; + })(); + ; + var LightDismissService = (function () { + function LightDismissService() { + this._debug = false; // Disables dismiss due to window blur. Useful during debugging. + this._clients = []; + this._notifying = false; + this._bodyClient = new LightDismissableBody(); + // State private to _updateDom. No other method should make use of it. + this._updateDom_rendered = { + serviceActive: false + }; + this._clickEaterEl = this._createClickEater(); + this._onBeforeRequestingFocusOnKeyboardInputBound = this._onBeforeRequestingFocusOnKeyboardInput.bind(this); + this._onFocusInBound = this._onFocusIn.bind(this); + this._onKeyDownBound = this._onKeyDown.bind(this); + this._onWindowResizeBound = this._onWindowResize.bind(this); + this._onClickEaterPointerUpBound = this._onClickEaterPointerUp.bind(this); + this._onClickEaterPointerCancelBound = this._onClickEaterPointerCancel.bind(this); + // Register for infrequent events. + Application.addEventListener("backclick", this._onBackClick.bind(this)); + // Focus handlers generally use _ElementUtilities._addEventListener with focusout/focusin. This + // uses the browser's blur event directly beacuse _addEventListener doesn't support focusout/focusin + // on window. + _Global.window.addEventListener("blur", this._onWindowBlur.bind(this)); + this.shown(this._bodyClient); + } + // Dismissables should call this as soon as they are ready to be shown. More specifically, they should call this: + // - After they are in the DOM and ready to receive focus (e.g. style.display cannot = "none") + // - Before their entrance animation is played + LightDismissService.prototype.shown = function (client) { + var index = this._clients.indexOf(client); + if (index === -1) { + this._clients.push(client); + client.onShow(this); + this._updateDom(); + } + }; + // Dismissables should call this when they are done being dismissed (i.e. after their exit animation has finished) + LightDismissService.prototype.hidden = function (client) { + var index = this._clients.indexOf(client); + if (index !== -1) { + this._clients.splice(index, 1); + client.setZIndex(""); + client.onHide(); + this._updateDom(); + } + }; + // Dismissables should call this when their state has changed such that it'll affect the behavior of some method + // in its ILightDismissable interface. For example, if the dismissable was altered such that getZIndexCount will + // now return 2 instead of 1, that dismissable should call *updated* so the LightDismissService can find out about + // this change. + LightDismissService.prototype.updated = function (client) { + this._updateDom(); + }; + LightDismissService.prototype.keyDown = function (client, eventObject) { + if (eventObject.keyCode === _ElementUtilities.Key.escape) { + this._escapePressed(eventObject); + } + else { + this._dispatchKeyboardEvent(client, KeyboardInfoType.keyDown, eventObject); + } + }; + LightDismissService.prototype.keyUp = function (client, eventObject) { + this._dispatchKeyboardEvent(client, KeyboardInfoType.keyUp, eventObject); + }; + LightDismissService.prototype.keyPress = function (client, eventObject) { + this._dispatchKeyboardEvent(client, KeyboardInfoType.keyPress, eventObject); + }; + LightDismissService.prototype.isShown = function (client) { + return this._clients.indexOf(client) !== -1; + }; + LightDismissService.prototype.isTopmost = function (client) { + return client === this._clients[this._clients.length - 1]; + }; + // Disables dismiss due to window blur. Useful during debugging. + LightDismissService.prototype._setDebug = function (debug) { + this._debug = debug; + }; + LightDismissService.prototype._updateDom = function (options) { + options = options || {}; + var activeDismissableNeedsFocus = !!options.activeDismissableNeedsFocus; + var rendered = this._updateDom_rendered; + if (this._notifying) { + return; + } + var serviceActive = this._clients.length > 1; + if (serviceActive !== rendered.serviceActive) { + // Unregister/register for events that occur frequently. + if (serviceActive) { + Application.addEventListener("beforerequestingfocusonkeyboardinput", this._onBeforeRequestingFocusOnKeyboardInputBound); + _ElementUtilities._addEventListener(_Global.document.documentElement, "focusin", this._onFocusInBound); + _Global.document.documentElement.addEventListener("keydown", this._onKeyDownBound); + _Global.window.addEventListener("resize", this._onWindowResizeBound); + this._bodyClient.currentFocus = _Global.document.activeElement; + _Global.document.body.appendChild(this._clickEaterEl); + } + else { + Application.removeEventListener("beforerequestingfocusonkeyboardinput", this._onBeforeRequestingFocusOnKeyboardInputBound); + _ElementUtilities._removeEventListener(_Global.document.documentElement, "focusin", this._onFocusInBound); + _Global.document.documentElement.removeEventListener("keydown", this._onKeyDownBound); + _Global.window.removeEventListener("resize", this._onWindowResizeBound); + var parent = this._clickEaterEl.parentNode; + parent && parent.removeChild(this._clickEaterEl); + } + rendered.serviceActive = serviceActive; + } + var zIndexGap = 0; + var lastUsedZIndex = baseZIndex + 1; + this._clients.forEach(function (c, i) { + var currentZIndex = lastUsedZIndex + zIndexGap; + c.setZIndex("" + currentZIndex); + lastUsedZIndex = currentZIndex; + // count + 1 so that there's an unused zIndex between each pair of + // dismissables that can be used by the click eater. + zIndexGap = c.getZIndexCount() + 1; + }); + if (serviceActive) { + this._clickEaterEl.style.zIndex = "" + (lastUsedZIndex - 1); + } + var activeDismissable = this._clients.length > 0 ? this._clients[this._clients.length - 1] : null; + if (this._activeDismissable !== activeDismissable) { + this._activeDismissable = activeDismissable; + activeDismissableNeedsFocus = true; + } + if (activeDismissableNeedsFocus) { + // If the last input type was keyboard, use focus() so a keyboard focus visual is drawn. + // Otherwise, use setActive() so no focus visual is drawn. + var useSetActive = !_KeyboardBehavior._keyboardSeenLast; + this._activeDismissable && this._activeDismissable.onTakeFocus(useSetActive); + } + }; + LightDismissService.prototype._dispatchKeyboardEvent = function (client, keyboardInfoType, eventObject) { + var index = this._clients.indexOf(client); + if (index !== -1) { + var info = { + type: keyboardInfoType, + keyCode: eventObject.keyCode, + propagationStopped: false, + stopPropagation: function () { + this.propagationStopped = true; + eventObject.stopPropagation(); + } + }; + var clients = this._clients.slice(0, index + 1); + for (var i = clients.length - 1; i >= 0 && !info.propagationStopped; i--) { + clients[i].onKeyInStack(info); + } + } + }; + LightDismissService.prototype._dispatchLightDismiss = function (reason, clients, options) { + if (this._notifying) { + _Log.log && _Log.log('_LightDismissService ignored dismiss trigger to avoid re-entrancy: "' + reason + '"', "winjs _LightDismissService", "warning"); + return; + } + clients = clients || this._clients.slice(0); + if (clients.length === 0) { + return; + } + this._notifying = true; + var lightDismissInfo = { + // Which of the LightDismissalReasons caused this event to fire? + reason: reason, + // Is this dismissable currently the active dismissable? + active: false, + _stop: false, + stopPropagation: function () { + this._stop = true; + }, + _doDefault: true, + preventDefault: function () { + this._doDefault = false; + } + }; + for (var i = clients.length - 1; i >= 0 && !lightDismissInfo._stop; i--) { + lightDismissInfo.active = this._activeDismissable === clients[i]; + if (clients[i].onShouldLightDismiss(lightDismissInfo)) { + clients[i].onLightDismiss(lightDismissInfo); + } + } + this._notifying = false; + this._updateDom(options); + return lightDismissInfo._doDefault; + }; + LightDismissService.prototype._onBeforeRequestingFocusOnKeyboardInput = function (eventObject) { + // Suppress the requestingFocusOnKeyboardInput event. + return true; + }; + // + // Light dismiss triggers + // + // Called by tests. + LightDismissService.prototype._clickEaterTapped = function () { + this._dispatchLightDismiss(exports.LightDismissalReasons.tap); + }; + LightDismissService.prototype._onFocusIn = function (eventObject) { + var target = eventObject.target; + for (var i = this._clients.length - 1; i >= 0; i--) { + if (this._clients[i].containsElement(target)) { + break; + } + } + if (i !== -1) { + this._clients[i].onFocus(target); + } + if (i + 1 < this._clients.length) { + this._dispatchLightDismiss(exports.LightDismissalReasons.lostFocus, this._clients.slice(i + 1), { + activeDismissableNeedsFocus: true + }); + } + }; + LightDismissService.prototype._onKeyDown = function (eventObject) { + if (eventObject.keyCode === _ElementUtilities.Key.escape) { + this._escapePressed(eventObject); + } + }; + LightDismissService.prototype._escapePressed = function (eventObject) { + eventObject.preventDefault(); + eventObject.stopPropagation(); + this._dispatchLightDismiss(exports.LightDismissalReasons.escape); + }; + // Called by tests. + LightDismissService.prototype._onBackClick = function (eventObject) { + var doDefault = this._dispatchLightDismiss(exports.LightDismissalReasons.hardwareBackButton); + return !doDefault; // Returns whether or not the event was handled. + }; + LightDismissService.prototype._onWindowResize = function (eventObject) { + this._dispatchLightDismiss(exports.LightDismissalReasons.windowResize); + }; + LightDismissService.prototype._onWindowBlur = function (eventObject) { + if (this._debug) { + return; + } + // Want to trigger a light dismiss on window blur. + // We get blur if we click off the window, including into an iframe within our window. + // Both blurs call this function, but fortunately document.hasFocus is true if either + // the document window or our iframe window has focus. + if (!_Global.document.hasFocus()) { + // The document doesn't have focus, so they clicked off the app, so light dismiss. + this._dispatchLightDismiss(exports.LightDismissalReasons.windowBlur); + } + else { + // We were trying to unfocus the window, but document still has focus, + // so make sure the iframe that took the focus will check for blur next time. + var active = _Global.document.activeElement; + if (active && active.tagName === "IFRAME" && !active["msLightDismissBlur"]) { + // - This will go away when the IFRAME goes away, and we only create one. + // - This only works in IE because other browsers don't fire focus events on iframe elements. + // - Can't use _ElementUtilities._addEventListener's focusout because it doesn't fire when an + // iframe loses focus due to changing windows. + active.addEventListener("blur", this._onWindowBlur.bind(this), false); + active["msLightDismissBlur"] = true; + } + } + }; + LightDismissService.prototype._createClickEater = function () { + var clickEater = _Global.document.createElement("section"); + clickEater.className = exports._ClassNames._clickEater; + _ElementUtilities._addEventListener(clickEater, "pointerdown", this._onClickEaterPointerDown.bind(this), true); + clickEater.addEventListener("click", this._onClickEaterClick.bind(this), true); + // Tell Aria that it's clickable + clickEater.setAttribute("role", "menuitem"); + clickEater.setAttribute("aria-label", Strings.closeOverlay); + // Prevent CED from removing any current selection + clickEater.setAttribute("unselectable", "on"); + return clickEater; + }; + LightDismissService.prototype._onClickEaterPointerDown = function (eventObject) { + eventObject.stopPropagation(); + eventObject.preventDefault(); + this._clickEaterPointerId = eventObject.pointerId; + if (!this._registeredClickEaterCleanUp) { + _ElementUtilities._addEventListener(_Global.window, "pointerup", this._onClickEaterPointerUpBound); + _ElementUtilities._addEventListener(_Global.window, "pointercancel", this._onClickEaterPointerCancelBound); + this._registeredClickEaterCleanUp = true; + } + }; + LightDismissService.prototype._onClickEaterPointerUp = function (eventObject) { + var _this = this; + eventObject.stopPropagation(); + eventObject.preventDefault(); + if (eventObject.pointerId === this._clickEaterPointerId) { + this._resetClickEaterPointerState(); + var element = _Global.document.elementFromPoint(eventObject.clientX, eventObject.clientY); + if (element === this._clickEaterEl) { + this._skipClickEaterClick = true; + _BaseUtils._yieldForEvents(function () { + _this._skipClickEaterClick = false; + }); + this._clickEaterTapped(); + } + } + }; + LightDismissService.prototype._onClickEaterClick = function (eventObject) { + eventObject.stopPropagation(); + eventObject.preventDefault(); + if (!this._skipClickEaterClick) { + // Handle the UIA invoke action on the click eater. this._skipClickEaterClick is false which tells + // us that we received a click event without an associated PointerUp event. This means that the click + // event was triggered thru UIA rather than thru the GUI. + this._clickEaterTapped(); + } + }; + LightDismissService.prototype._onClickEaterPointerCancel = function (eventObject) { + if (eventObject.pointerId === this._clickEaterPointerId) { + this._resetClickEaterPointerState(); + } + }; + LightDismissService.prototype._resetClickEaterPointerState = function () { + if (this._registeredClickEaterCleanUp) { + _ElementUtilities._removeEventListener(_Global.window, "pointerup", this._onClickEaterPointerUpBound); + _ElementUtilities._removeEventListener(_Global.window, "pointercancel", this._onClickEaterPointerCancelBound); + } + this._clickEaterPointerId = null; + this._registeredClickEaterCleanUp = false; + }; + return LightDismissService; + })(); + var service = new LightDismissService(); + exports.shown = service.shown.bind(service); + exports.hidden = service.hidden.bind(service); + exports.updated = service.updated.bind(service); + exports.isShown = service.isShown.bind(service); + exports.isTopmost = service.isTopmost.bind(service); + exports.keyDown = service.keyDown.bind(service); + exports.keyUp = service.keyUp.bind(service); + exports.keyPress = service.keyPress.bind(service); + exports._clickEaterTapped = service._clickEaterTapped.bind(service); + exports._onBackClick = service._onBackClick.bind(service); + exports._setDebug = service._setDebug.bind(service); + _Base.Namespace.define("WinJS.UI._LightDismissService", { + shown: exports.shown, + hidden: exports.hidden, + updated: exports.updated, + isShown: exports.isShown, + isTopmost: exports.isTopmost, + keyDown: exports.keyDown, + keyUp: exports.keyUp, + keyPress: exports.keyPress, + _clickEaterTapped: exports._clickEaterTapped, + _onBackClick: exports._onBackClick, + _setDebug: exports._setDebug, + LightDismissableElement: LightDismissableElement, + DismissalPolicies: exports.DismissalPolicies, + LightDismissalReasons: exports.LightDismissalReasons, + _ClassNames: exports._ClassNames, + _service: service + }); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('WinJS/Controls/_LegacyAppBar/_Constants',[ + 'exports', + '../../Core/_Base', +], function appBarConstantsInit(exports, _Base) { + "use strict"; + + _Base.Namespace._moduleDefine(exports, null, { + // AppBar class names. + appBarClass: "win-navbar", + firstDivClass: "win-firstdiv", + finalDivClass: "win-finaldiv", + invokeButtonClass: "win-navbar-invokebutton", + ellipsisClass: "win-navbar-ellipsis", + primaryCommandsClass: "win-primarygroup", + secondaryCommandsClass: "win-secondarygroup", + commandLayoutClass: "win-commandlayout", + menuLayoutClass: "win-menulayout", + topClass: "win-top", + bottomClass: "win-bottom", + showingClass : "win-navbar-opening", + shownClass : "win-navbar-opened", + hidingClass : "win-navbar-closing", + hiddenClass: "win-navbar-closed", + compactClass: "win-navbar-compact", + minimalClass: "win-navbar-minimal", + menuContainerClass: "win-navbar-menu", + + // Constants for AppBar placement + appBarPlacementTop: "top", + appBarPlacementBottom: "bottom", + + // Constants for AppBar layouts + appBarLayoutCustom: "custom", + appBarLayoutCommands: "commands", + appBarLayoutMenu: "menu", + + // Constant for AppBar invokebutton width + appBarInvokeButtonWidth: 32, + + // Constants for Commands + typeSeparator: "separator", + typeContent: "content", + typeButton: "button", + typeToggle: "toggle", + typeFlyout: "flyout", + appBarCommandClass: "win-command", + appBarCommandGlobalClass: "win-global", + appBarCommandSelectionClass: "win-selection", + sectionSelection: "selection", /* deprecated, use sectionSecondary */ + sectionGlobal: "global", /* deprecated, use sectionPrimary */ + sectionPrimary: "primary", + sectionSecondary: "secondary", + + // Constants for Menus + menuCommandClass: "win-command", + menuCommandButtonClass: "win-command-button", + menuCommandToggleClass: "win-command-toggle", + menuCommandFlyoutClass: "win-command-flyout", + menuCommandFlyoutActivatedClass: "win-command-flyout-activated", + menuCommandSeparatorClass: "win-command-separator", + _menuCommandInvokedEvent: "_invoked", // Private event + menuClass: "win-menu", + menuContainsToggleCommandClass: "win-menu-containstogglecommand", + menuContainsFlyoutCommandClass: "win-menu-containsflyoutcommand", + menuMouseSpacingClass: "win-menu-mousespacing", + menuTouchSpacingClass: "win-menu-touchspacing", + menuCommandHoverDelay: 400, + + // Other class names + overlayClass: "win-overlay", + flyoutClass: "win-flyout", + flyoutLightClass: "win-ui-light", + settingsFlyoutClass: "win-settingsflyout", + scrollsClass: "win-scrolls", + pinToRightEdge: -1, + pinToBottomEdge: -1, + + // Constants for AppBarCommand full-size widths. + separatorWidth: 34, + buttonWidth: 68, + + narrowClass: "win-narrow", + wideClass: "win-wide", + _visualViewportClass: "win-visualviewport-space", + + // Event names + commandPropertyMutated: "_commandpropertymutated", + commandVisibilityChanged: "commandvisibilitychanged", + }); +}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// +define('WinJS/Utilities/_KeyboardInfo',["require", "exports", '../Core/_BaseCoreUtils', '../Core/_Global', '../Core/_WinRT'], function (require, exports, _BaseCoreUtils, _Global, _WinRT) { + "use strict"; + var _Constants = { + visualViewportClass: "win-visualviewport-space", + scrollTimeout: 150, + }; + // This private module provides accurate metrics for the Visual Viewport and WWA's IHM offsets in Win10 WWA + // where "-ms-device-fixed" CSS positioning is supported. WinJS controls will also use this module for + // positoning themselves relative to the viewport in a web browser outside of WWA. Their preference is still + // to rely on "-ms-device-fixed" positioning, but currently fallback to "fixed" positioning in enviornments where + // "-ms-device-fixed" is not supported. + exports._KeyboardInfo; + // WWA Soft Keyboard offsets + exports._KeyboardInfo = { + // Determine if the keyboard is visible or not. + get _visible() { + try { + return (_WinRT.Windows.UI.ViewManagement.InputPane && _WinRT.Windows.UI.ViewManagement.InputPane.getForCurrentView().occludedRect.height > 0); + } + catch (e) { + return false; + } + }, + // See if we have to reserve extra space for the IHM + get _extraOccluded() { + var occluded = 0; + // Controls using -ms-device-fixed positioning only need to reposition themselves to remain visible + // If the IHM has not resized the viewport. + if (!exports._KeyboardInfo._isResized && _WinRT.Windows.UI.ViewManagement.InputPane) { + occluded = _WinRT.Windows.UI.ViewManagement.InputPane.getForCurrentView().occludedRect.height; + } + return occluded; + }, + // See if the view has been resized to fit a keyboard + get _isResized() { + // Compare ratios. Very different includes IHM space. + var heightRatio = _Global.document.documentElement.clientHeight / _Global.innerHeight, widthRatio = _Global.document.documentElement.clientWidth / _Global.innerWidth; + // If they're nearly identical, then the view hasn't been resized for the IHM + // Only check one bound because we know the IHM will make it shorter, not skinnier. + return (widthRatio / heightRatio < 0.99); + }, + // Get the bottom of the visible area, relative to the top edge of the visible area. + get _visibleDocBottom() { + return exports._KeyboardInfo._visibleDocTop + exports._KeyboardInfo._visibleDocHeight; + }, + // Get the height of the visible area, e.g. the height of the visual viewport minus any IHM occlusion. + get _visibleDocHeight() { + return exports._KeyboardInfo._visualViewportHeight - exports._KeyboardInfo._extraOccluded; + }, + // Get the top offset of our visible area, aka the top of the visual viewport. + // This is always 0 when elements use -ms-device-fixed positioning. + get _visibleDocTop() { + return 0; + }, + // Get the offset for, and relative to, the bottom edge of the visual viewport plus any IHM occlusion. + get _visibleDocBottomOffset() { + // For -ms-device-fixed positioned elements, the bottom is just 0 when there's no IHM. + // When the IHM appears, the text input that invoked it may be in a position on the page that is occluded by the IHM. + // In that instance, the default browser behavior is to resize the visual viewport and scroll the input back into view. + // However, if the viewport resize is prevented by an IHM event listener, the keyboard will still occlude + // -ms-device-fixed elements, so we adjust the bottom offset of the appbar by the height of the occluded rect of the IHM. + return exports._KeyboardInfo._extraOccluded; + }, + // Get the visual viewport height. window.innerHeight doesn't return floating point values which are present with high DPI. + get _visualViewportHeight() { + var boundingRect = exports._KeyboardInfo._visualViewportSpace; + return boundingRect.height; + }, + // Get the visual viewport width. window.innerWidth doesn't return floating point values which are present with high DPI. + get _visualViewportWidth() { + var boundingRect = exports._KeyboardInfo._visualViewportSpace; + return boundingRect.width; + }, + // The visual viewport space element is hidden given -ms-device-fixed positioning and used to calculate + // the 4 edges of the visual viewport with floating point precision. + get _visualViewportSpace() { + var visualViewportSpace = _Global.document.body.querySelector("." + _Constants.visualViewportClass); + if (!visualViewportSpace) { + visualViewportSpace = _Global.document.createElement("DIV"); + visualViewportSpace.className = _Constants.visualViewportClass; + _Global.document.body.appendChild(visualViewportSpace); + } + return visualViewportSpace.getBoundingClientRect(); + }, + // Get total length of the IHM showPanel animation + get _animationShowLength() { + if (_BaseCoreUtils.hasWinRT) { + if (_WinRT.Windows.UI.Core.AnimationMetrics) { + // Desktop exposes the AnimationMetrics API that allows us to look up the relevant IHM animation metrics. + var a = _WinRT.Windows.UI.Core.AnimationMetrics, animationDescription = new a.AnimationDescription(a.AnimationEffect.showPanel, a.AnimationEffectTarget.primary); + var animations = animationDescription.animations; + var max = 0; + for (var i = 0; i < animations.size; i++) { + var animation = animations[i]; + max = Math.max(max, animation.delay + animation.duration); + } + return max; + } + else { + // Phone platform does not yet expose the Animation Metrics API. + // Hard code the correct values for the time being. + // https://github.com/winjs/winjs/issues/1060 + var animationDuration = 300; + var animationDelay = 50; + return animationDelay + animationDuration; + } + } + else { + return 0; + } + }, + // Padding for IHM timer to allow for first scroll event. Tpyically used in conjunction with the + // _animationShowLength to determine the length of time in which a showing IHM would have triggered + // a window resize to occur. + get _scrollTimeout() { + return _Constants.scrollTimeout; + }, + // _layoutViewportCoords is used with elements that use position:fixed instead of position:-ms-device-fixed + get _layoutViewportCoords() { + var topOffset = _Global.window.pageYOffset - _Global.document.documentElement.scrollTop; + var bottomOffset = _Global.document.documentElement.clientHeight - (topOffset + this._visibleDocHeight); + return { + visibleDocTop: topOffset, + visibleDocBottom: bottomOffset + }; + } + }; +}); + + +define('require-style!less/styles-overlay',[],function(){}); + +define('require-style!less/colors-overlay',[],function(){}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// animatable,appbar,appbars,divs,Flyout,Flyouts,iframe,Statics,unfocus,unselectable +define('WinJS/Controls/Flyout/_Overlay',[ + 'exports', + '../../Core/_Global', + '../../Core/_WinRT', + '../../Core/_Base', + '../../Core/_BaseUtils', + '../../Core/_ErrorFromName', + '../../Core/_Events', + '../../Core/_Resources', + '../../Core/_WriteProfilerMark', + '../../_Accents', + '../../Animations', + '../../Application', + '../../ControlProcessor', + '../../Promise', + '../../Scheduler', + '../../Utilities/_Control', + '../../Utilities/_ElementUtilities', + '../../Utilities/_KeyboardInfo', + '../_LegacyAppBar/_Constants', + 'require-style!less/styles-overlay', + 'require-style!less/colors-overlay' +], function overlayInit(exports, _Global, _WinRT, _Base, _BaseUtils, _ErrorFromName, _Events, _Resources, _WriteProfilerMark, _Accents, Animations, Application, ControlProcessor, Promise, Scheduler, _Control, _ElementUtilities, _KeyboardInfo, _Constants) { + "use strict"; + + _Accents.createAccentRule( + "button[aria-checked=true].win-command:before,\ + .win-menu-containsflyoutcommand button.win-command-flyout-activated:before", [ + { name: "background-color", value: _Accents.ColorTypes.accent }, + { name: "border-color", value: _Accents.ColorTypes.accent }, + ]); + + _Accents.createAccentRule(".win-flyout, .win-settingsflyout", [{ name: "border-color", value: _Accents.ColorTypes.accent }]); + + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + _Overlay: _Base.Namespace._lazy(function () { + + // Helper for Global Event listeners. Invokes the specified callback member function on each _Overlay in the DOM. + function _allOverlaysCallback(event, nameOfFunctionCall, stopImmediatePropagationWhenHandled) { + var elements = _Global.document.querySelectorAll("." + _Constants.overlayClass); + if (elements) { + var len = elements.length; + for (var i = 0; i < len; i++) { + var element = elements[i]; + var overlay = element.winControl; + if (!overlay._disposed) { + if (overlay) { + var handled = overlay[nameOfFunctionCall](event); + if (stopImmediatePropagationWhenHandled && handled) { + // The caller has indicated we should exit as soon as the event is handled. + return handled; + } + } + } + } + } + } + + // _Overlay Global Events Listener Class. We hang a singleton instance of this class off of a static _Overlay property. + var _GlobalListener = _Base.Class.define(function _GlobalListener_ctor() { + this._currentState = _GlobalListener.states.off; + + this._inputPaneShowing = this._inputPaneShowing.bind(this); + this._inputPaneHiding = this._inputPaneHiding.bind(this); + this._documentScroll = this._documentScroll.bind(this); + this._windowResized = this._windowResized.bind(this); + }, { + initialize: function _GlobalListener_initialize() { + this._toggleListeners(_GlobalListener.states.on); + }, + // Expose this for unit tests. + reset: function _GlobalListener_reset() { + this._toggleListeners(_GlobalListener.states.off); + this._toggleListeners(_GlobalListener.states.on); + }, + _inputPaneShowing: function _GlobalListener_inputePaneShowing(event) { + _WriteProfilerMark(_GlobalListener.profilerString + "_showingKeyboard,StartTM"); + _allOverlaysCallback(event, "_showingKeyboard"); + _WriteProfilerMark(_GlobalListener.profilerString + "_showingKeyboard,StopTM"); + }, + _inputPaneHiding: function _GlobalListener_inputPaneHiding(event) { + _WriteProfilerMark(_GlobalListener.profilerString + "_hidingKeyboard,StartTM"); + _allOverlaysCallback(event, "_hidingKeyboard"); + _WriteProfilerMark(_GlobalListener.profilerString + "_hidingKeyboard,StopTM"); + }, + _documentScroll: function _GlobalListener_documentScroll(event) { + _WriteProfilerMark(_GlobalListener.profilerString + "_checkScrollPosition,StartTM"); + _allOverlaysCallback(event, "_checkScrollPosition"); + _WriteProfilerMark(_GlobalListener.profilerString + "_checkScrollPosition,StopTM"); + }, + _windowResized: function _GlobalListener_windowResized(event) { + _WriteProfilerMark(_GlobalListener.profilerString + "_baseResize,StartTM"); + _allOverlaysCallback(event, "_baseResize"); + _WriteProfilerMark(_GlobalListener.profilerString + "_baseResize,StopTM"); + }, + _toggleListeners: function _GlobalListener_toggleListeners(newState) { + // Add/Remove global event listeners for all _Overlays + var listenerOperation; + if (this._currentState !== newState) { + if (newState === _GlobalListener.states.on) { + listenerOperation = "addEventListener"; + } else if (newState === _GlobalListener.states.off) { + listenerOperation = "removeEventListener"; + } + + if (_WinRT.Windows.UI.ViewManagement.InputPane) { + // React to Soft Keyboard events + var inputPane = _WinRT.Windows.UI.ViewManagement.InputPane.getForCurrentView(); + inputPane[listenerOperation]("showing", this._inputPaneShowing, false); + inputPane[listenerOperation]("hiding", this._inputPaneHiding, false); + + _Global.document[listenerOperation]("scroll", this._documentScroll, false); + } + + // Window resize event + _Global.addEventListener("resize", this._windowResized, false); + + this._currentState = newState; + } + }, + }, { + // Statics + profilerString: { + get: function () { + return "WinJS.UI._Overlay Global Listener:"; + } + }, + states: { + get: function () { + return { + off: 0, + on: 1, + }; + }, + }, + }); + + // Helper to get DOM elements from input single object or array or IDs/toolkit/dom elements + function _resolveElements(elements) { + // No input is just an empty array + if (!elements) { + return []; + } + + // Make sure it's in array form. + if (typeof elements === "string" || !elements || !elements.length) { + elements = [elements]; + } + + // Make sure we have a DOM element for each one, (could be string id name or toolkit object) + var i, + realElements = []; + for (i = 0; i < elements.length; i++) { + if (elements[i]) { + if (typeof elements[i] === "string") { + var element = _Global.document.getElementById(elements[i]); + if (element) { + realElements.push(element); + } + } else if (elements[i].element) { + realElements.push(elements[i].element); + } else { + realElements.push(elements[i]); + } + } + } + + return realElements; + } + + var strings = { + get duplicateConstruction() { return "Invalid argument: Controls may only be instantiated one time for each DOM element"; }, + get mustContainCommands() { return "Invalid HTML: AppBars/Menus must contain only AppBarCommands/MenuCommands"; }, + get closeOverlay() { return _Resources._getWinJSString("ui/closeOverlay").value; }, + }; + + var _Overlay = _Base.Class.define(function _Overlay_ctor(element, options) { + /// + /// + /// Constructs the Overlay control and associates it with the underlying DOM element. + /// + /// + /// The DOM element to be associated with the Overlay control. + /// + /// + /// The set of options to be applied initially to the Overlay control. + /// + /// A fully constructed Overlay control. + /// + this._baseOverlayConstructor(element, options); + }, { + // Functions/properties + _baseOverlayConstructor: function _Overlay_baseOverlayConstructor(element, options) { + + this._disposed = false; + + // Make sure there's an input element + if (!element) { + element = _Global.document.createElement("div"); + } + + // Check to make sure we weren't duplicated + var overlay = element.winControl; + if (overlay) { + throw new _ErrorFromName("WinJS.UI._Overlay.DuplicateConstruction", strings.duplicateConstruction); + } + + if (!this._element) { + this._element = element; + } + + if (!this._element.hasAttribute("tabIndex")) { + this._element.tabIndex = -1; + } + + this._sticky = false; + this._doNext = ""; + + this._element.style.visibility = "hidden"; + this._element.style.opacity = 0; + + // Remember ourselves + element.winControl = this; + + // Attach our css class + _ElementUtilities.addClass(this._element, _Constants.overlayClass); + _ElementUtilities.addClass(this._element, "win-disposable"); + + // We don't want to be selectable, set UNSELECTABLE + var unselectable = this._element.getAttribute("unselectable"); + if (unselectable === null || unselectable === undefined) { + this._element.setAttribute("unselectable", "on"); + } + + // Base animation is popIn/popOut + this._currentAnimateIn = this._baseAnimateIn; + this._currentAnimateOut = this._baseAnimateOut; + this._animationPromise = Promise.as(); + + // Command Animations to Queue + this._queuedToShow = []; + this._queuedToHide = []; + this._queuedCommandAnimation = false; + + if (options) { + _Control.setOptions(this, options); + } + + // Make sure _Overlay event handlers are hooked up (this aids light dismiss) + _Overlay._globalEventListeners.initialize(); + }, + + /// + element: { + get: function () { + return this._element; + } + }, + + dispose: function () { + /// + /// + /// Disposes this Overlay. + /// + /// + if (this._disposed) { + return; + } + + this._disposed = true; + this._dispose(); + }, + + _dispose: function _Overlay_dispose() { + // To be overridden by subclasses + }, + + _show: function _Overlay_show() { + // We call our base _baseShow because AppBar may need to override show + this._baseShow(); + }, + + _hide: function _Overlay_hide() { + // We call our base _baseHide because AppBar may need to override hide + this._baseHide(); + }, + + // Is the overlay "hidden"? + /// + hidden: { + get: function () { + return (this._element.style.visibility === "hidden" || + this._element.winAnimating === "hiding" || + this._doNext === "hide"); + }, + set: function (hidden) { + var currentlyHidden = this.hidden; + if (!hidden && currentlyHidden) { + this._show(); + } else if (hidden && !currentlyHidden) { + this._hide(); + } + } + }, + + addEventListener: function (type, listener, useCapture) { + /// + /// + /// Add an event listener to the DOM element for this Overlay + /// + /// Required. Event type to add, "beforehide", "afterhide", "beforeshow", or "aftershow" + /// Required. The event handler function to associate with this event. + /// Optional. True, register for the event capturing phase. False for the event bubbling phase. + /// + return this._element.addEventListener(type, listener, useCapture); + }, + + removeEventListener: function (type, listener, useCapture) { + /// + /// + /// Remove an event listener to the DOM element for this Overlay + /// + /// Required. Event type to remove, "beforehide", "afterhide", "beforeshow", or "aftershow" + /// Required. The event handler function to associate with this event. + /// Optional. True, register for the event capturing phase. False for the event bubbling phase. + /// + return this._element.removeEventListener(type, listener, useCapture); + }, + + _baseShow: function _Overlay_baseShow() { + // If we are already animating, just remember this for later + if (this._animating || this._needToHandleHidingKeyboard) { + this._doNext = "show"; + return false; + } + + if (this._element.style.visibility !== "visible") { + // Let us know we're showing. + this._element.winAnimating = "showing"; + + // Hiding, but not none + this._element.style.display = ""; + this._element.style.visibility = "hidden"; + + // In case their event is going to manipulate commands, see if there are + // any queued command animations we can handle while we're still hidden. + if (this._queuedCommandAnimation) { + this._showAndHideFast(this._queuedToShow, this._queuedToHide); + this._queuedToShow = []; + this._queuedToHide = []; + } + + // Send our "beforeShow" event + this._sendEvent(_Overlay.beforeShow); + + // Need to measure + this._findPosition(); + + // Make sure it's visible, and fully opaque. + // Do the popup thing, sending event afterward. + var that = this; + this._animationPromise = this._currentAnimateIn(). + then(function () { + that._baseEndShow(); + }, function () { + that._baseEndShow(); + }); + return true; + } + return false; + }, + + // Flyout in particular will need to measure our positioning. + _findPosition: function _Overlay_findPosition() { + }, + + _baseEndShow: function _Overlay_baseEndShow() { + if (this._disposed) { + return; + } + + // Make sure it's visible after showing + this._element.setAttribute("aria-hidden", "false"); + + this._element.winAnimating = ""; + + // Do our derived classes show stuff + this._endShow(); + + // We're shown now + if (this._doNext === "show") { + this._doNext = ""; + } + + // After showing, send the after showing event + this._sendEvent(_Overlay.afterShow); + this._writeProfilerMark("show,StopTM"); // Overlay writes the stop profiler mark for all of its derived classes. + + // If we had something queued, do that + Scheduler.schedule(this._checkDoNext, Scheduler.Priority.normal, this, "WinJS.UI._Overlay._checkDoNext"); + + }, + + _endShow: function _Overlay_endShow() { + // Nothing by default + }, + + _baseHide: function _Overlay_baseHide() { + // If we are already animating, just remember this for later + if (this._animating) { + this._doNext = "hide"; + return false; + } + + // In the unlikely event we're between the hiding keyboard and the resize events, just snap it away: + if (this._needToHandleHidingKeyboard) { + // use the "uninitialized" flag + this._element.style.visibility = ""; + } + + if (this._element.style.visibility !== "hidden") { + // Let us know we're hiding, accessibility as well. + this._element.winAnimating = "hiding"; + this._element.setAttribute("aria-hidden", "true"); + + // Send our "beforeHide" event + this._sendEvent(_Overlay.beforeHide); + + // If our visibility is empty, then this is the first time, just hide it + if (this._element.style.visibility === "") { + // Initial hiding, just hide it + this._element.style.opacity = 0; + this._baseEndHide(); + } else { + // Make sure it's hidden, and fully transparent. + var that = this; + this._animationPromise = this._currentAnimateOut(). + then(function () { + that._baseEndHide(); + }, function () { + that._baseEndHide(); + }); + } + return true; + } + + return false; + }, + + _baseEndHide: function _Overlay_baseEndHide() { + if (this._disposed) { + return; + } + + // Do our derived classes hide stuff + this._beforeEndHide(); + + // Make sure animation is finished. + this._element.style.visibility = "hidden"; + this._element.style.display = "none"; + this._element.winAnimating = ""; + + // In case their event is going to manipulate commands, see if there + // are any queued command animations we can handle now we're hidden. + if (this._queuedCommandAnimation) { + this._showAndHideFast(this._queuedToShow, this._queuedToHide); + this._queuedToShow = []; + this._queuedToHide = []; + } + + // We're hidden now + if (this._doNext === "hide") { + this._doNext = ""; + } + + // After hiding, send our "afterHide" event + this._sendEvent(_Overlay.afterHide); + this._writeProfilerMark("hide,StopTM"); // Overlay writes the stop profiler mark for all of its derived classes. + + + // If we had something queued, do that. This has to be after + // the afterHide event in case it triggers a show() and they + // have something to do in beforeShow that requires afterHide first. + Scheduler.schedule(this._checkDoNext, Scheduler.Priority.normal, this, "WinJS.UI._Overlay._checkDoNext"); + }, + + // Called after the animation but while the Overlay is still visible. It's + // important that this runs while the Overlay is visible because hiding + // a DOM element (e.g. visibility="hidden", display="none") while it contains + // focus has the side effect of moving focus to the body or null and triggering + // focus move events. _beforeEndHide is a good hook for the Overlay to move focus + // elsewhere before its DOM element gets hidden. + _beforeEndHide: function _Overlay_beforeEndHide() { + // Nothing by default + }, + + _checkDoNext: function _Overlay_checkDoNext() { + // Do nothing if we're still animating + if (this._animating || this._needToHandleHidingKeyboard || this._disposed) { + return; + } + + if (this._doNext === "hide") { + // Do hide first because animating commands would be easier + this._hide(); + this._doNext = ""; + } else if (this._queuedCommandAnimation) { + // Do queued commands before showing if possible + this._showAndHideQueue(); + } else if (this._doNext === "show") { + // Show last so that we don't unnecessarily animate commands + this._show(); + this._doNext = ""; + } + }, + + // Default animations + _baseAnimateIn: function _Overlay_baseAnimateIn() { + this._element.style.opacity = 0; + this._element.style.visibility = "visible"; + // touch opacity so that IE fades from the 0 we just set to 1 + _Global.getComputedStyle(this._element, null).opacity; + return Animations.fadeIn(this._element); + }, + + _baseAnimateOut: function _Overlay_baseAnimateOut() { + this._element.style.opacity = 1; + // touch opacity so that IE fades from the 1 we just set to 0 + _Global.getComputedStyle(this._element, null).opacity; + return Animations.fadeOut(this._element); + }, + + _animating: { + get: function _Overlay_animating_get() { + // Ensure it's a boolean because we're using the DOM element to keep in-sync + return !!this._element.winAnimating; + } + }, + + // Send one of our events + _sendEvent: function _Overlay_sendEvent(eventName, detail) { + if (this._disposed) { + return; + } + var event = _Global.document.createEvent("CustomEvent"); + event.initEvent(eventName, true, true, (detail || {})); + this._element.dispatchEvent(event); + }, + + // Show commands + _showCommands: function _Overlay_showCommands(commands, immediate) { + var showHide = this._resolveCommands(commands); + this._showAndHideCommands(showHide.commands, [], immediate); + }, + + // Hide commands + _hideCommands: function _Overlay_hideCommands(commands, immediate) { + var showHide = this._resolveCommands(commands); + this._showAndHideCommands([], showHide.commands, immediate); + }, + + // Hide commands + _showOnlyCommands: function _Overlay_showOnlyCommands(commands, immediate) { + var showHide = this._resolveCommands(commands); + this._showAndHideCommands(showHide.commands, showHide.others, immediate); + }, + + _showAndHideCommands: function _Overlay_showAndHideCommands(showCommands, hideCommands, immediate) { + // Immediate is "easy" + if (immediate || (this.hidden && !this._animating)) { + // Immediate mode (not animated) + this._showAndHideFast(showCommands, hideCommands); + // Need to remove them from queues, but others could be queued + this._removeFromQueue(showCommands, this._queuedToShow); + this._removeFromQueue(hideCommands, this._queuedToHide); + } else { + + // Queue Commands + this._updateAnimateQueue(showCommands, this._queuedToShow, this._queuedToHide); + this._updateAnimateQueue(hideCommands, this._queuedToHide, this._queuedToShow); + } + }, + + _removeFromQueue: function _Overlay_removeFromQueue(commands, queue) { + // remove commands from queue. + var count; + for (count = 0; count < commands.length; count++) { + // Remove if it was in queue + var countQ; + for (countQ = 0; countQ < queue.length; countQ++) { + if (queue[countQ] === commands[count]) { + queue.splice(countQ, 1); + break; + } + } + } + }, + + _updateAnimateQueue: function _Overlay_updateAnimateQueue(addCommands, toQueue, fromQueue) { + if (this._disposed) { + return; + } + + // Add addCommands to toQueue and remove addCommands from fromQueue. + var count; + for (count = 0; count < addCommands.length; count++) { + // See if it's already in toQueue + var countQ; + for (countQ = 0; countQ < toQueue.length; countQ++) { + if (toQueue[countQ] === addCommands[count]) { + break; + } + } + if (countQ === toQueue.length) { + // Not found, add it + toQueue[countQ] = addCommands[count]; + } + // Remove if it was in fromQueue + for (countQ = 0; countQ < fromQueue.length; countQ++) { + if (fromQueue[countQ] === addCommands[count]) { + fromQueue.splice(countQ, 1); + break; + } + } + } + // If we haven't queued the actual animation + if (!this._queuedCommandAnimation) { + // If not already animating, we'll need to call _checkDoNext + if (!this._animating) { + Scheduler.schedule(this._checkDoNext, Scheduler.Priority.normal, this, "WinJS.UI._Overlay._checkDoNext"); + } + this._queuedCommandAnimation = true; + } + }, + + // show/hide commands without doing any animation. + _showAndHideFast: function _Overlay_showAndHideFast(showCommands, hideCommands) { + var count; + var command; + for (count = 0; count < showCommands.length; count++) { + command = showCommands[count]; + if (command && command.style) { + command.style.visibility = ""; + command.style.display = ""; + } + } + for (count = 0; count < hideCommands.length; count++) { + command = hideCommands[count]; + if (command && command.style) { + command.style.visibility = "hidden"; + command.style.display = "none"; + } + } + + this._commandsUpdated(); + + }, + + // show and hide the queued commands, perhaps animating if overlay isn't hidden. + _showAndHideQueue: function _Overlay_showAndHideQueue() { + // Only called if not currently animating. + // We'll be done with the queued stuff when we return. + this._queuedCommandAnimation = false; + + // Shortcut if hidden + if (this.hidden) { + this._showAndHideFast(this._queuedToShow, this._queuedToHide); + // Might be something else to do + Scheduler.schedule(this._checkDoNext, Scheduler.Priority.normal, this, "WinJS.UI._Overlay._checkDoNext"); + } else { + // Animation has 3 parts: "hiding", "showing", and "moving" + // PVL has "addToList" and "deleteFromList", both of which allow moving parts. + // So we'll set up "add" for showing, and use "delete" for "hiding" + moving, + // then trigger both at the same time. + var showCommands = this._queuedToShow; + var hideCommands = this._queuedToHide; + var siblings = this._findSiblings(showCommands.concat(hideCommands)); + + // Filter out the commands queued for animation that don't need to be animated. + var count; + for (count = 0; count < showCommands.length; count++) { + // If this one's not real or not attached, skip it + if (!showCommands[count] || + !showCommands[count].style || + !_Global.document.body.contains(showCommands[count])) { + // Not real, skip it + showCommands.splice(count, 1); + count--; + } else if (showCommands[count].style.visibility !== "hidden" && showCommands[count].style.opacity !== "0") { + // Don't need to animate showing this one, already visible, so now it's a sibling + siblings.push(showCommands[count]); + showCommands.splice(count, 1); + count--; + } + } + for (count = 0; count < hideCommands.length; count++) { + // If this one's not real or not attached, skip it + if (!hideCommands[count] || + !hideCommands[count].style || + !_Global.document.body.contains(hideCommands[count]) || + hideCommands[count].style.visibility === "hidden" || + hideCommands[count].style.opacity === "0") { + // Don't need to animate hiding this one, not real, or it's hidden, + // so don't even need it as a sibling. + hideCommands.splice(count, 1); + count--; + } + } + + // Start command animations. + var commandsAnimationPromise = this._baseBeginAnimateCommands(showCommands, hideCommands, siblings); + + // Hook end animations + var that = this; + if (commandsAnimationPromise) { + // Needed to animate + commandsAnimationPromise.done( + function () { that._baseEndAnimateCommands(hideCommands); }, + function () { that._baseEndAnimateCommands(hideCommands); } + ); + } else { + // Already positioned correctly + Scheduler.schedule(function Overlay_async_baseEndAnimationCommands() { that._baseEndAnimateCommands([]); }, + Scheduler.Priority.normal, null, + "WinJS.UI._Overlay._endAnimateCommandsWithoutAnimation"); + } + } + + // Done, clear queues + this._queuedToShow = []; + this._queuedToHide = []; + }, + + _baseBeginAnimateCommands: function _Overlay_baseBeginAnimateCommands(showCommands, hideCommands, siblings) { + // The parameters are 3 mutually exclusive arrays of win-command elements contained in this Overlay. + // 1) showCommands[]: All of the HIDDEN win-command elements that ARE scheduled to show. + // 2) hideCommands[]: All of the VISIBLE win-command elements that ARE shceduled to hide. + // 3) siblings[]: i. All VISIBLE win-command elements that ARE NOT scheduled to hide. + // ii. All HIDDEN win-command elements that ARE NOT scheduled to hide OR show. + this._beginAnimateCommands(showCommands, hideCommands, this._getVisibleCommands(siblings)); + + var showAnimated = null, + hideAnimated = null; + + // Hide commands first, with siblings if necessary, + // so that the showing commands don't disrupt the hiding commands position. + if (hideCommands.length > 0) { + hideAnimated = Animations.createDeleteFromListAnimation(hideCommands, showCommands.length === 0 ? siblings : undefined); + } + if (showCommands.length > 0) { + showAnimated = Animations.createAddToListAnimation(showCommands, siblings); + } + + // Update hiding commands + for (var count = 0, len = hideCommands.length; count < len; count++) { + // Need to fix our position + var rectangle = hideCommands[count].getBoundingClientRect(), + style = _Global.getComputedStyle(hideCommands[count]); + + // Use the bounding box, adjusting for margins + hideCommands[count].style.top = (rectangle.top - parseFloat(style.marginTop)) + "px"; + hideCommands[count].style.left = (rectangle.left - parseFloat(style.marginLeft)) + "px"; + hideCommands[count].style.opacity = 0; + hideCommands[count].style.position = "fixed"; + } + + // Mark as animating + this._element.winAnimating = "rearranging"; + + // Start hiding animations + // Hide needs extra cleanup when done + var promise = null; + if (hideAnimated) { + promise = hideAnimated.execute(); + } + + // Update showing commands, + // After hiding commands so that the hiding ones fade in the right place. + for (count = 0; count < showCommands.length; count++) { + showCommands[count].style.visibility = ""; + showCommands[count].style.display = ""; + showCommands[count].style.opacity = 1; + } + + // Start showing animations + if (showAnimated) { + var newPromise = showAnimated.execute(); + if (promise) { + promise = Promise.join([promise, newPromise]); + } else { + promise = newPromise; + } + } + + return promise; + }, + + _beginAnimateCommands: function _Overlay_beginAnimateCommands() { + // Nothing by default + }, + + _getVisibleCommands: function _Overlay_getVisibleCommands(commandSubSet) { + var command, + commands = commandSubSet, + visibleCommands = []; + + if (!commands) { + // Crawl the inner HTML for the commands. + commands = this.element.querySelectorAll(".win-command"); + } + + for (var i = 0, len = commands.length; i < len; i++) { + command = commands[i].winControl || commands[i]; + if (!command.hidden) { + visibleCommands.push(command); + } + } + + return visibleCommands; + }, + + // Once animation is complete, ensure that the commands are display:none + // and check if there's another animation to start. + _baseEndAnimateCommands: function _Overlay_baseEndAnimateCommands(hideCommands) { + if (this._disposed) { + return; + } + + // Update us + var count; + for (count = 0; count < hideCommands.length; count++) { + // Force us back into our appbar so that we can show again correctly + hideCommands[count].style.position = ""; + hideCommands[count].style.top = ""; + hideCommands[count].style.left = ""; + hideCommands[count].getBoundingClientRect(); + // Now make us really hidden + hideCommands[count].style.visibility = "hidden"; + hideCommands[count].style.display = "none"; + hideCommands[count].style.opacity = 1; + } + // Done animating + this._element.winAnimating = ""; + + this._endAnimateCommands(); + + // Might be something else to do + this._checkDoNext(); + }, + + _endAnimateCommands: function _Overlay_endAnimateCommands() { + // Nothing by default + }, + + // Resolves our commands + _resolveCommands: function _Overlay_resolveCommands(commands) { + // First make sure they're all DOM elements. + commands = _resolveElements(commands); + + // Now make sure they're all in this container + var result = {}; + result.commands = []; + result.others = []; + var allCommands = this.element.querySelectorAll(".win-command"); + var countAll, countIn; + for (countAll = 0; countAll < allCommands.length; countAll++) { + var found = false; + for (countIn = 0; countIn < commands.length; countIn++) { + if (commands[countIn] === allCommands[countAll]) { + result.commands.push(allCommands[countAll]); + commands.splice(countIn, 1); + found = true; + break; + } + } + if (!found) { + result.others.push(allCommands[countAll]); + } + } + return result; + }, + + // Find siblings, all DOM elements now. + // Returns all .win-commands in this Overlay that are NOT in the passed in 'commands' array. + _findSiblings: function _Overlay_findSiblings(commands) { + // Now make sure they're all in this container + var siblings = []; + var allCommands = this.element.querySelectorAll(".win-command"); + var countAll, countIn; + for (countAll = 0; countAll < allCommands.length; countAll++) { + var found = false; + for (countIn = 0; countIn < commands.length; countIn++) { + if (commands[countIn] === allCommands[countAll]) { + commands.splice(countIn, 1); + found = true; + break; + } + } + if (!found) { + siblings.push(allCommands[countAll]); + } + } + return siblings; + }, + + _baseResize: function _Overlay_baseResize(event) { + // Call specific resize + this._resize(event); + }, + + _hideOrDismiss: function _Overlay_hideOrDismiss() { + var element = this._element; + if (element && _ElementUtilities.hasClass(element, _Constants.settingsFlyoutClass)) { + this._dismiss(); + } else if (element && _ElementUtilities.hasClass(element, _Constants.appBarClass)) { + this.close(); + } else { + this.hide(); + } + }, + + _resize: function _Overlay_resize() { + // Nothing by default + }, + + _commandsUpdated: function _Overlay_commandsUpdated() { + // Nothing by default + }, + + _checkScrollPosition: function _Overlay_checkScrollPosition() { + // Nothing by default + }, + + _showingKeyboard: function _Overlay_showingKeyboard() { + // Nothing by default + }, + + _hidingKeyboard: function _Overlay_hidingKeyboard() { + // Nothing by default + }, + + // Verify that this HTML AppBar only has AppBar/MenuCommands. + _verifyCommandsOnly: function _Overlay_verifyCommandsOnly(element, type) { + var children = element.children; + var commands = new Array(children.length); + for (var i = 0; i < children.length; i++) { + // If constructed they have win-command class, otherwise they have data-win-control + if (!_ElementUtilities.hasClass(children[i], "win-command") && + children[i].getAttribute("data-win-control") !== type) { + // Wasn't tagged with class or AppBar/MenuCommand, not an AppBar/MenuCommand + throw new _ErrorFromName("WinJS.UI._Overlay.MustContainCommands", strings.mustContainCommands); + } else { + // Instantiate the commands. + ControlProcessor.processAll(children[i]); + commands[i] = children[i].winControl; + } + } + return commands; + }, + + // Sets focus on what we think is the last tab stop. If nothing is focusable will + // try to set focus on itself. + _focusOnLastFocusableElementOrThis: function _Overlay_focusOnLastFocusableElementOrThis() { + if (!this._focusOnLastFocusableElement()) { + // Nothing is focusable. Set focus to this. + _Overlay._trySetActive(this._element); + } + }, + + // Sets focus to what we think is the last tab stop. This element must have + // a firstDiv with tabIndex equal to the lowest tabIndex in the element + // and a finalDiv with tabIndex equal to the highest tabIndex in the element. + // Also the firstDiv must be its first child and finalDiv be its last child. + // Returns true if successful, false otherwise. + _focusOnLastFocusableElement: function _Overlay_focusOnLastFocusableElement() { + if (this._element.firstElementChild) { + var oldFirstTabIndex = this._element.firstElementChild.tabIndex; + var oldLastTabIndex = this._element.lastElementChild.tabIndex; + this._element.firstElementChild.tabIndex = -1; + this._element.lastElementChild.tabIndex = -1; + + var tabResult = _ElementUtilities._focusLastFocusableElement(this._element); + + if (tabResult) { + _Overlay._trySelect(_Global.document.activeElement); + } + + this._element.firstElementChild.tabIndex = oldFirstTabIndex; + this._element.lastElementChild.tabIndex = oldLastTabIndex; + + return tabResult; + } else { + return false; + } + }, + + + // Sets focus on what we think is the first tab stop. If nothing is focusable will + // try to set focus on itself. + _focusOnFirstFocusableElementOrThis: function _Overlay_focusOnFirstFocusableElementOrThis() { + if (!this._focusOnFirstFocusableElement()) { + // Nothing is focusable. Set focus to this. + _Overlay._trySetActive(this._element); + } + }, + + // Sets focus to what we think is the first tab stop. This element must have + // a firstDiv with tabIndex equal to the lowest tabIndex in the element + // and a finalDiv with tabIndex equal to the highest tabIndex in the element. + // Also the firstDiv must be its first child and finalDiv be its last child. + // Returns true if successful, false otherwise. + _focusOnFirstFocusableElement: function _Overlay__focusOnFirstFocusableElement(useSetActive, scroller) { + if (this._element.firstElementChild) { + var oldFirstTabIndex = this._element.firstElementChild.tabIndex; + var oldLastTabIndex = this._element.lastElementChild.tabIndex; + this._element.firstElementChild.tabIndex = -1; + this._element.lastElementChild.tabIndex = -1; + + var tabResult = _ElementUtilities._focusFirstFocusableElement(this._element, useSetActive, scroller); + + if (tabResult) { + _Overlay._trySelect(_Global.document.activeElement); + } + + this._element.firstElementChild.tabIndex = oldFirstTabIndex; + this._element.lastElementChild.tabIndex = oldLastTabIndex; + + return tabResult; + } else { + return false; + } + }, + + _writeProfilerMark: function _Overlay_writeProfilerMark(text) { + _WriteProfilerMark("WinJS.UI._Overlay:" + this._id + ":" + text); + } + }, + { + // Statics + + _isFlyoutVisible: function () { + var flyouts = _Global.document.querySelectorAll("." + _Constants.flyoutClass); + for (var i = 0; i < flyouts.length; i++) { + var flyoutControl = flyouts[i].winControl; + if (flyoutControl && !flyoutControl.hidden) { + return true; + } + } + + return false; + }, + + // Try to set us as active + _trySetActive: function (element, scroller) { + if (!element || !_Global.document.body || !_Global.document.body.contains(element)) { + return false; + } + if (!_ElementUtilities._setActive(element, scroller)) { + return false; + } + return (element === _Global.document.activeElement); + }, + + // Try to select the text so keyboard can be used. + _trySelect: function (element) { + try { + if (element && element.select) { + element.select(); + } + } catch (e) { } + }, + + _sizeOfDocument: function () { + return { + width: _Global.document.documentElement.offsetWidth, + height: _Global.document.documentElement.offsetHeight, + }; + }, + + _getParentControlUsingClassName: function (element, className) { + while (element && element !== _Global.document.body) { + if (_ElementUtilities.hasClass(element, className)) { + return element.winControl; + } + element = element.parentNode; + } + return null; + }, + + // Static controller for _Overlay global events registering/unregistering. + _globalEventListeners: new _GlobalListener(), + + // Show/Hide all bars + _hideAppBars: function _Overlay_hideAppBars(bars, keyboardInvoked) { + var allBarsAnimationPromises = bars.map(function (bar) { + bar.close(); + return bar._animationPromise; + }); + return Promise.join(allBarsAnimationPromises); + }, + + _showAppBars: function _Overlay_showAppBars(bars, keyboardInvoked) { + var allBarsAnimationPromises = bars.map(function (bar) { + bar._show(); + return bar._animationPromise; + }); + return Promise.join(allBarsAnimationPromises); + }, + + // WWA Soft Keyboard offsets + _keyboardInfo: _KeyboardInfo._KeyboardInfo, + + // Padding for IHM timer to allow for first scroll event + _scrollTimeout: _KeyboardInfo._KeyboardInfo._scrollTimeout, + + // Events + beforeShow: "beforeshow", + beforeHide: "beforehide", + afterShow: "aftershow", + afterHide: "afterhide", + + commonstrings: { + get cannotChangeCommandsWhenVisible() { return "Invalid argument: You must call hide() before changing {0} commands"; }, + get cannotChangeHiddenProperty() { return "Unable to set hidden property while parent {0} is visible."; } + }, + }); + + _Base.Class.mix(_Overlay, _Control.DOMEventMixin); + + return _Overlay; + }) + }); + +}); + + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// appbar,Flyout,Flyouts,Statics +define('WinJS/Controls/Flyout',[ + 'exports', + '../Core/_Global', + '../Core/_Base', + '../Core/_BaseUtils', + '../Core/_ErrorFromName', + '../Core/_Events', + '../Core/_Log', + '../Core/_Resources', + '../Core/_WriteProfilerMark', + '../Animations', + '../_Signal', + '../_LightDismissService', + '../Utilities/_Dispose', + '../Utilities/_ElementUtilities', + '../Utilities/_KeyboardBehavior', + '../Utilities/_Hoverable', + './_LegacyAppBar/_Constants', + './Flyout/_Overlay' +], function flyoutInit(exports, _Global, _Base, _BaseUtils, _ErrorFromName, _Events, _Log, _Resources, _WriteProfilerMark, Animations, _Signal, _LightDismissService, _Dispose, _ElementUtilities, _KeyboardBehavior, _Hoverable, _Constants, _Overlay) { + "use strict"; + + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + /// + /// + /// Displays lightweight UI that is either informational, or requires user interaction. + /// Unlike a dialog, a Flyout can be light dismissed by clicking or tapping off of it. + /// + /// + /// + /// Flyout + /// + /// + /// ]]> + /// Raised just before showing a flyout. + /// Raised immediately after a flyout is fully shown. + /// Raised just before hiding a flyout. + /// Raised immediately after a flyout is fully hidden. + /// The Flyout control itself. + /// + /// + Flyout: _Base.Namespace._lazy(function () { + var Key = _ElementUtilities.Key; + + function getDimension(element, property) { + return _ElementUtilities.convertToPixels(element, _Global.getComputedStyle(element, null)[property]); + } + + var strings = { + get ariaLabel() { return _Resources._getWinJSString("ui/flyoutAriaLabel").value; }, + get noAnchor() { return "Invalid argument: Flyout anchor element not found in DOM."; }, + get badPlacement() { return "Invalid argument: Flyout placement should be 'top' (default), 'bottom', 'left', 'right', 'auto', 'autohorizontal', or 'autovertical'."; }, + get badAlignment() { return "Invalid argument: Flyout alignment should be 'center' (default), 'left', or 'right'."; } + }; + + var createEvent = _Events._createEventProperty; + + // _LightDismissableLayer is an ILightDismissable which manages a set of ILightDismissables. + // It acts as a proxy between the LightDismissService and the light dismissables it manages. + // It enables multiple dismissables to be above the click eater at the same time. + var _LightDismissableLayer = _Base.Class.define(function _LightDismissableLayer_ctor(onLightDismiss) { + this._onLightDismiss = onLightDismiss; + this._currentlyFocusedClient = null; + this._clients = []; // Array of ILightDismissables + }, { + // Dismissables should call this as soon as they are ready to be shown. More specifically, they should call this: + // - After they are in the DOM and ready to receive focus (e.g. style.display cannot be "none") + // - Before their entrance animation is played + shown: function _LightDismissableLayer_shown(client /*: ILightDismissable */) { + client._focusable = true; + var index = this._clients.indexOf(client); + if (index === -1) { + this._clients.push(client); + client.onShow(this); + if (!_LightDismissService.isShown(this)) { + _LightDismissService.shown(this); + } else { + _LightDismissService.updated(this); + this._activateTopFocusableClientIfNeeded(); + } + } + }, + + // Dismissables should call this at the start of their exit animation. A "hiding", + // dismissable will still be rendered with the proper z-index but it will no + // longer be given focus. Also, focus is synchronously moved out of this dismissable. + hiding: function _LightDismissableLayer_hiding(client /*: ILightDismissable */) { + var index = this._clients.indexOf(client); + if (index !== -1) { + this._clients[index]._focusable = false; + this._activateTopFocusableClientIfNeeded(); + } + }, + + // Dismissables should call this when they are done being dismissed (i.e. after their exit animation has finished) + hidden: function _LightDismissableLayer_hidden(client /*: ILightDismissable */) { + var index = this._clients.indexOf(client); + if (index !== -1) { + this._clients.splice(index, 1); + client.setZIndex(""); + client.onHide(); + if (this._clients.length === 0) { + _LightDismissService.hidden(this); + } else { + _LightDismissService.updated(this); + this._activateTopFocusableClientIfNeeded(); + } + } + }, + + keyDown: function _LightDismissableLayer_keyDown(client /*: ILightDismissable */, eventObject) { + _LightDismissService.keyDown(this, eventObject); + }, + keyUp: function _LightDismissableLayer_keyUp(client /*: ILightDismissable */, eventObject) { + _LightDismissService.keyUp(this, eventObject); + }, + keyPress: function _LightDismissableLayer_keyPress(client /*: ILightDismissable */, eventObject) { + _LightDismissService.keyPress(this, eventObject); + }, + + // Used by tests. + clients: { + get: function _LightDismissableLayer_clients_get() { + return this._clients; + } + }, + + _clientForElement: function _LightDismissableLayer_clientForElement(element) { + for (var i = this._clients.length - 1; i >= 0; i--) { + if (this._clients[i].containsElement(element)) { + return this._clients[i]; + } + } + return null; + }, + + _focusableClientForElement: function _LightDismissableLayer_focusableClientForElement(element) { + for (var i = this._clients.length - 1; i >= 0; i--) { + if (this._clients[i]._focusable && this._clients[i].containsElement(element)) { + return this._clients[i]; + } + } + return null; + }, + + _getTopmostFocusableClient: function _LightDismissableLayer_getTopmostFocusableClient() { + for (var i = this._clients.length - 1; i >= 0; i--) { + var client = this._clients[i]; + if (client && client._focusable) { + return client; + } + } + return null; + }, + + _activateTopFocusableClientIfNeeded: function _LightDismissableLayer_activateTopFocusableClientIfNeeded() { + var topClient = this._getTopmostFocusableClient(); + if (topClient && _LightDismissService.isTopmost(this)) { + // If the last input type was keyboard, use focus() so a keyboard focus visual is drawn. + // Otherwise, use setActive() so no focus visual is drawn. + var useSetActive = !_KeyboardBehavior._keyboardSeenLast; + topClient.onTakeFocus(useSetActive); + } + }, + + // ILightDismissable + // + + setZIndex: function _LightDismissableLayer_setZIndex(zIndex) { + this._clients.forEach(function (client, index) { + client.setZIndex(zIndex + index); + }, this); + }, + getZIndexCount: function _LightDismissableLayer_getZIndexCount() { + return this._clients.length; + }, + containsElement: function _LightDismissableLayer_containsElement(element) { + return !!this._clientForElement(element); + }, + onTakeFocus: function _LightDismissableLayer_onTakeFocus(useSetActive) { + // Prefer the client that has focus + var client = this._focusableClientForElement(_Global.document.activeElement); + + if (!client && this._clients.indexOf(this._currentlyFocusedClient) !== -1 && this._currentlyFocusedClient._focusable) { + // Next try the client that had focus most recently + client = this._currentlyFocusedClient; + } + + if (!client) { + // Finally try the client at the top of the stack + client = this._getTopmostFocusableClient(); + } + + this._currentlyFocusedClient = client; + client && client.onTakeFocus(useSetActive); + }, + onFocus: function _LightDismissableLayer_onFocus(element) { + this._currentlyFocusedClient = this._clientForElement(element); + this._currentlyFocusedClient && this._currentlyFocusedClient.onFocus(element); + }, + onShow: function _LightDismissableLayer_onShow(service /*: ILightDismissService */) { }, + onHide: function _LightDismissableLayer_onHide() { + this._currentlyFocusedClient = null; + }, + onKeyInStack: function _LightDismissableLayer_onKeyInStack(info /*: IKeyboardInfo*/) { + // A keyboard event occurred in the light dismiss stack. Notify the flyouts to + // give them the opportunity to handle this evnet. + var index = this._clients.indexOf(this._currentlyFocusedClient); + if (index !== -1) { + var clients = this._clients.slice(0, index + 1); + for (var i = clients.length - 1; i >= 0 && !info.propagationStopped; i--) { + if (clients[i]._focusable) { + clients[i].onKeyInStack(info); + } + } + } + }, + onShouldLightDismiss: function _LightDismissableLayer_onShouldLightDismiss(info) { + return _LightDismissService.DismissalPolicies.light(info); + }, + onLightDismiss: function _LightDismissableLayer_onLightDismiss(info) { + this._onLightDismiss(info); + } + }); + + // Singleton class for managing cascading flyouts + var _CascadeManager = _Base.Class.define(function _CascadeManager_ctor() { + var that = this; + this._dismissableLayer = new _LightDismissableLayer(function _CascadeManager_onLightDismiss(info) { + if (info.reason === _LightDismissService.LightDismissalReasons.escape) { + that.collapseFlyout(that.getAt(that.length - 1)); + } else { + that.collapseAll(); + } + }); + this._cascadingStack = []; + this._handleKeyDownInCascade_bound = this._handleKeyDownInCascade.bind(this); + this._inputType = null; + }, + { + appendFlyout: function _CascadeManager_appendFlyout(flyoutToAdd) { + // PRECONDITION: flyoutToAdd must not already be in the cascade. + _Log.log && this.indexOf(flyoutToAdd) >= 0 && _Log.log('_CascadeManager is attempting to append a Flyout that is already in the cascade.', "winjs _CascadeManager", "error"); + // PRECONDITION: this.reentrancyLock must be false. appendFlyout should only be called from baseFlyoutShow() which is the function responsible for preventing reentrancy. + _Log.log && this.reentrancyLock && _Log.log('_CascadeManager is attempting to append a Flyout through reentrancy.', "winjs _CascadeManager", "error"); + + // IF the anchor element for flyoutToAdd is contained within another flyout, + // && that flyout is currently in the cascadingStack, consider that flyout to be the parent of flyoutToAdd: + // Remove from the cascadingStack, any subflyout descendants of the parent flyout. + // ELSE flyoutToAdd isn't anchored to any of the Flyouts in the existing cascade + // Collapse the entire cascadingStack to start a new cascade. + // FINALLY: + // add flyoutToAdd to the end of the cascading stack. Monitor it for events. + var indexOfParentFlyout = this.indexOfElement(flyoutToAdd._currentAnchor); + if (indexOfParentFlyout >= 0) { + this.collapseFlyout(this.getAt(indexOfParentFlyout + 1)); + } else { + this.collapseAll(); + } + + flyoutToAdd.element.addEventListener("keydown", this._handleKeyDownInCascade_bound, false); + this._cascadingStack.push(flyoutToAdd); + this._dismissableLayer.shown(flyoutToAdd._dismissable); + }, + collapseFlyout: function _CascadeManager_collapseFlyout(flyout) { + // Removes flyout param and its subflyout descendants from the _cascadingStack. + if (!this.reentrancyLock && flyout && this.indexOf(flyout) >= 0) { + this.reentrancyLock = true; + var signal = new _Signal(); + this.unlocked = signal.promise; + + var subFlyout; + while (this.length && flyout !== subFlyout) { + subFlyout = this._cascadingStack.pop(); + subFlyout.element.removeEventListener("keydown", this._handleKeyDownInCascade_bound, false); + subFlyout._hide(); // We use the reentrancyLock to prevent reentrancy here. + } + + if (this._cascadingStack.length === 0) { + // The cascade is empty so clear the input type. This gives us the opportunity + // to recalculate the input type when the next cascade starts. + this._inputType = null; + } + + this.reentrancyLock = false; + this.unlocked = null; + signal.complete(); + } + }, + flyoutHiding: function _CascadeManager_flyoutHiding(flyout) { + this._dismissableLayer.hiding(flyout._dismissable); + }, + flyoutHidden: function _CascadeManager_flyoutHidden(flyout) { + this._dismissableLayer.hidden(flyout._dismissable); + }, + collapseAll: function _CascadeManager_collapseAll() { + // Empties the _cascadingStack and hides all flyouts. + var headFlyout = this.getAt(0); + if (headFlyout) { + this.collapseFlyout(headFlyout); + } + }, + indexOf: function _CascadeManager_indexOf(flyout) { + return this._cascadingStack.indexOf(flyout); + }, + indexOfElement: function _CascadeManager_indexOfElement(el) { + // Returns an index cooresponding to the Flyout in the cascade whose element contains the element in question. + // Returns -1 if the element is not contained by any Flyouts in the cascade. + var indexOfAssociatedFlyout = -1; + for (var i = 0, len = this.length; i < len; i++) { + var currentFlyout = this.getAt(i); + if (currentFlyout.element.contains(el)) { + indexOfAssociatedFlyout = i; + break; + } + } + return indexOfAssociatedFlyout; + }, + length: { + get: function _CascadeManager_getLength() { + return this._cascadingStack.length; + } + }, + getAt: function _CascadeManager_getAt(index) { + return this._cascadingStack[index]; + }, + handleFocusIntoFlyout: function _CascadeManager_handleFocusIntoFlyout(event) { + // When a flyout in the cascade recieves focus, we close all subflyouts beneath it. + var index = this.indexOfElement(event.target); + if (index >= 0) { + var subFlyout = this.getAt(index + 1); + this.collapseFlyout(subFlyout); + } + }, + // Compute the input type that is associated with the cascading stack on demand. Allows + // each Flyout in the cascade to adjust its sizing based on the current input type + // and to do it in a way that is consistent with the rest of the Flyouts in the cascade. + inputType: { + get: function _CascadeManager_inputType_get() { + if (!this._inputType) { + this._inputType = _KeyboardBehavior._lastInputType; + } + return this._inputType; + } + }, + // Used by tests. + dismissableLayer: { + get: function _CascadeManager_dismissableLayer_get() { + return this._dismissableLayer; + } + }, + _handleKeyDownInCascade: function _CascadeManager_handleKeyDownInCascade(event) { + var rtl = _Global.getComputedStyle(event.target).direction === "rtl", + leftKey = rtl ? Key.rightArrow : Key.leftArrow, + target = event.target; + + if (event.keyCode === leftKey) { + // Left key press in a SubFlyout will close that subFlyout and any subFlyouts cascading from it. + var index = this.indexOfElement(target); + if (index >= 1) { + var subFlyout = this.getAt(index); + this.collapseFlyout(subFlyout); + // Prevent document scrolling + event.preventDefault(); + } + } else if (event.keyCode === Key.alt || event.keyCode === Key.F10) { + this.collapseAll(); + } + } + }); + + var AnimationOffsets = { + top: { top: "50px", left: "0px", keyframe: "WinJS-showFlyoutTop" }, + bottom: { top: "-50px", left: "0px", keyframe: "WinJS-showFlyoutBottom" }, + left: { top: "0px", left: "50px", keyframe: "WinJS-showFlyoutLeft" }, + right: { top: "0px", left: "-50px", keyframe: "WinJS-showFlyoutRight" }, + }; + + var Flyout = _Base.Class.derive(_Overlay._Overlay, function Flyout_ctor(element, options) { + /// + /// + /// Creates a new Flyout control. + /// + /// + /// The DOM element that hosts the control. + /// + /// + /// The set of properties and values to apply to the new Flyout. + /// + /// The new Flyout control. + /// + /// + + // Simplify checking later + options = options || {}; + + // Make sure there's an input element + this._element = element || _Global.document.createElement("div"); + this._id = this._element.id || _ElementUtilities._uniqueID(this._element); + this._writeProfilerMark("constructor,StartTM"); + + this._baseFlyoutConstructor(this._element, options); + + var _elms = this._element.getElementsByTagName("*"); + var firstDiv = this._addFirstDiv(); + firstDiv.tabIndex = _ElementUtilities._getLowestTabIndexInList(_elms); + var finalDiv = this._addFinalDiv(); + finalDiv.tabIndex = _ElementUtilities._getHighestTabIndexInList(_elms); + + // Handle "esc" & "tab" key presses + this._element.addEventListener("keydown", this._handleKeyDown, true); + + this._writeProfilerMark("constructor,StopTM"); + return this; + }, { + _lastMaxHeight: null, + + _baseFlyoutConstructor: function Flyout_baseFlyoutContstructor(element, options) { + // Flyout constructor + + // We have some options with defaults + this._placement = "auto"; + this._alignment = "center"; + + // Call the base overlay constructor helper + this._baseOverlayConstructor(element, options); + + // Start flyouts hidden + this._element.style.visibilty = "hidden"; + this._element.style.display = "none"; + + // Attach our css class + _ElementUtilities.addClass(this._element, _Constants.flyoutClass); + + var that = this; + // Each flyout has an ILightDismissable that is managed through the + // CascasdeManager rather than by the _LightDismissService directly. + this._dismissable = new _LightDismissService.LightDismissableElement({ + element: this._element, + tabIndex: this._element.hasAttribute("tabIndex") ? this._element.tabIndex : -1, + onLightDismiss: function () { + that.hide(); + }, + onTakeFocus: function (useSetActive) { + if (!that._dismissable.restoreFocus()) { + if (!_ElementUtilities.hasClass(that.element, _Constants.menuClass)) { + // Put focus on the first child in the Flyout + that._focusOnFirstFocusableElementOrThis(); + } else { + // Make sure the menu has focus, but don't show a focus rect + _Overlay._Overlay._trySetActive(that._element); + } + } + } + }); + + // Make sure we have an ARIA role + var role = this._element.getAttribute("role"); + if (role === null || role === "" || role === undefined) { + if (_ElementUtilities.hasClass(this._element, _Constants.menuClass)) { + this._element.setAttribute("role", "menu"); + } else { + this._element.setAttribute("role", "dialog"); + } + } + var label = this._element.getAttribute("aria-label"); + if (label === null || label === "" || label === undefined) { + this._element.setAttribute("aria-label", strings.ariaLabel); + } + + // Base animation is popIn, but our flyout has different arguments + this._currentAnimateIn = this._flyoutAnimateIn; + this._currentAnimateOut = this._flyoutAnimateOut; + + _ElementUtilities._addEventListener(this.element, "focusin", this._handleFocusIn.bind(this), false); + }, + + /// + /// Gets or sets the Flyout control's anchor. The anchor element is the HTML element which the Flyout originates from and is positioned relative to. + /// (This setting can be overridden when you call the show method.) + /// + /// + anchor: { + get: function () { + return this._anchor; + }, + set: function (value) { + this._anchor = value; + } + }, + + /// + /// Gets or sets the default placement of this Flyout. (This setting can be overridden when you call the show method.) + /// + /// + placement: { + get: function () { + return this._placement; + }, + set: function (value) { + if (value !== "top" && value !== "bottom" && value !== "left" && value !== "right" && value !== "auto" && value !== "autohorizontal" && value !== "autovertical") { + // Not a legal placement value + throw new _ErrorFromName("WinJS.UI.Flyout.BadPlacement", strings.badPlacement); + } + this._placement = value; + } + }, + + /// + /// Gets or sets the default alignment for this Flyout. (This setting can be overridden when you call the show method.) + /// + /// + alignment: { + get: function () { + return this._alignment; + }, + set: function (value) { + if (value !== "right" && value !== "left" && value !== "center") { + // Not a legal alignment value + throw new _ErrorFromName("WinJS.UI.Flyout.BadAlignment", strings.badAlignment); + } + this._alignment = value; + } + }, + + /// Disable a Flyout, setting or getting the HTML disabled attribute. When disabled the Flyout will no longer display with show(), and will hide if currently visible. + disabled: { + get: function () { + // Ensure it's a boolean because we're using the DOM element to keep in-sync + return !!this._element.disabled; + }, + set: function (value) { + // Force this check into a boolean because our current state could be a bit confused since we tie to the DOM element + value = !!value; + var oldValue = !!this._element.disabled; + if (oldValue !== value) { + this._element.disabled = value; + if (!this.hidden && this._element.disabled) { + this.hide(); + } + } + } + }, + + /// + /// Occurs immediately before the control is shown. + /// + onbeforeshow: createEvent(_Overlay._Overlay.beforeShow), + + /// + /// Occurs immediately after the control is shown. + /// + onaftershow: createEvent(_Overlay._Overlay.afterShow), + + /// + /// Occurs immediately before the control is hidden. + /// + onbeforehide: createEvent(_Overlay._Overlay.beforeHide), + + /// + /// Occurs immediately after the control is hidden. + /// + onafterhide: createEvent(_Overlay._Overlay.afterHide), + + _dispose: function Flyout_dispose() { + _Dispose.disposeSubTree(this.element); + this._hide(); + Flyout._cascadeManager.flyoutHidden(this); + this.anchor = null; + }, + + show: function (anchor, placement, alignment) { + /// + /// + /// Shows the Flyout, if hidden, regardless of other states. + /// + /// + /// The DOM element, or ID of a DOM element to anchor the Flyout, overriding the anchor property for this time only. + /// + /// + /// The placement of the Flyout to the anchor: 'auto' (default), 'top', 'bottom', 'left', or 'right'. This parameter overrides the placement property for this show only. + /// + /// + /// For 'top' or 'bottom' placement, the alignment of the Flyout to the anchor's edge: 'center' (default), 'left', or 'right'. + /// This parameter overrides the alignment property for this show only. + /// + /// + /// + this._writeProfilerMark("show,StartTM"); // The corresponding "stop" profiler mark is handled in _Overlay._baseEndShow(). + this._show(anchor, placement, alignment); + }, + + _show: function Flyout_show(anchor, placement, alignment) { + this._baseFlyoutShow(anchor, placement, alignment); + }, + + hide: function () { + /// + /// + /// Hides the Flyout, if visible, regardless of other states. + /// + /// + /// + // Just wrap the private one, turning off keyboard invoked flag + this._writeProfilerMark("hide,StartTM"); // The corresponding "stop" profiler mark is handled in _Overlay._baseEndHide(). + this._hide(); + }, + + _hide: function Flyout_hide() { + + // First close all subflyout descendants in the cascade. + // Any calls to collapseFlyout through reentrancy should nop. + Flyout._cascadeManager.collapseFlyout(this); + + if (this._baseHide()) { + Flyout._cascadeManager.flyoutHiding(this); + } + }, + + _beforeEndHide: function Flyout_beforeEndHide() { + Flyout._cascadeManager.flyoutHidden(this); + }, + + _baseFlyoutShow: function Flyout_baseFlyoutShow(anchor, placement, alignment) { + if (this.disabled || this._disposed) { + // Don't do anything. + return; + } + + // Pick up defaults + if (!anchor) { + anchor = this._anchor; + } + if (!placement) { + placement = this._placement; + } + if (!alignment) { + alignment = this._alignment; + } + + // Dereference the anchor if necessary + if (typeof anchor === "string") { + anchor = _Global.document.getElementById(anchor); + } else if (anchor && anchor.element) { + anchor = anchor.element; + } + + // We expect an anchor + if (!anchor) { + // If we have _nextLeft, etc., then we were continuing an old animation, so that's OK + if (!this._reuseCurrent) { + throw new _ErrorFromName("WinJS.UI.Flyout.NoAnchor", strings.noAnchor); + } + // Last call was incomplete, so reuse the previous _current values. + this._reuseCurrent = null; + } else { + // Remember the anchor so that if we lose focus we can go back + this._currentAnchor = anchor; + // Remember current values + this._currentPlacement = placement; + this._currentAlignment = alignment; + } + + // If we're animating (eg baseShow is going to fail), or the cascadeManager is in the middle of a updating the cascade, + // then don't mess up our current state. + if (this._element.winAnimating) { + this._reuseCurrent = true; + // Queue us up to wait for the current animation to finish. + // _checkDoNext() is always scheduled after the current animation completes. + this._doNext = "show"; + } else if (Flyout._cascadeManager.reentrancyLock) { + this._reuseCurrent = true; + // Queue us up to wait for the current animation to finish. + // Schedule a call to _checkDoNext() for when the cascadeManager unlocks. + this._doNext = "show"; + var that = this; + Flyout._cascadeManager.unlocked.then(function () { that._checkDoNext(); }); + } else { + // We call our base _baseShow to handle the actual animation + if (this._baseShow()) { + // (_baseShow shouldn't ever fail because we tested winAnimating above). + if (!_ElementUtilities.hasClass(this.element, "win-menu")) { + // Verify that the firstDiv is in the correct location. + // Move it to the correct location or add it if not. + var _elms = this._element.getElementsByTagName("*"); + var firstDiv = this.element.querySelectorAll(".win-first"); + if (this.element.children.length && !_ElementUtilities.hasClass(this.element.children[0], _Constants.firstDivClass)) { + if (firstDiv && firstDiv.length > 0) { + firstDiv.item(0).parentNode.removeChild(firstDiv.item(0)); + } + + firstDiv = this._addFirstDiv(); + } + firstDiv.tabIndex = _ElementUtilities._getLowestTabIndexInList(_elms); + + // Verify that the finalDiv is in the correct location. + // Move it to the correct location or add it if not. + var finalDiv = this.element.querySelectorAll(".win-final"); + if (!_ElementUtilities.hasClass(this.element.children[this.element.children.length - 1], _Constants.finalDivClass)) { + if (finalDiv && finalDiv.length > 0) { + finalDiv.item(0).parentNode.removeChild(finalDiv.item(0)); + } + + finalDiv = this._addFinalDiv(); + } + finalDiv.tabIndex = _ElementUtilities._getHighestTabIndexInList(_elms); + } + + Flyout._cascadeManager.appendFlyout(this); + } + } + }, + + _lightDismiss: function Flyout_lightDismiss() { + Flyout._cascadeManager.collapseAll(); + }, + + // Find our new flyout position. + _findPosition: function Flyout_findPosition() { + this._adjustedHeight = 0; + this._nextTop = 0; + this._nextLeft = 0; + this._keyboardMovedUs = false; + this._doesScroll = false; + + // Make sure menu commands display correctly + if (this._checkMenuCommands) { + this._checkMenuCommands(); + } + + // Remove old height restrictions and scrolling. + this._clearAdjustedStyles(); + + this._setAlignment(this._currentAlignment); + + // Set up the new position, and prep the offset for showPopup. + this._getTopLeft(); + + // Adjust position + if (this._nextTop < 0) { + // Overran bottom, attach to bottom. + this._element.style.bottom = _Overlay._Overlay._keyboardInfo._visibleDocBottomOffset + "px"; + this._element.style.top = "auto"; + } else { + // Normal, set top + this._element.style.top = this._nextTop + "px"; + this._element.style.bottom = "auto"; + } + if (this._nextLeft < 0) { + // Overran right, attach to right + this._element.style.right = "0px"; + this._element.style.left = "auto"; + } else { + // Normal, set left + this._element.style.left = this._nextLeft + "px"; + this._element.style.right = "auto"; + } + + // Adjust height/scrollbar + if (this._doesScroll) { + _ElementUtilities.addClass(this._element, _Constants.scrollsClass); + this._lastMaxHeight = this._element.style.maxHeight; + this._element.style.maxHeight = this._adjustedHeight + "px"; + } + + // May need to adjust if the IHM is showing. + if (_Overlay._Overlay._keyboardInfo._visible) { + // Use keyboard logic + this._checkKeyboardFit(); + + if (this._keyboardMovedUs) { + this._adjustForKeyboard(); + } + } + }, + + // This determines our positioning. We have 8 modes, the 1st four are explicit, the last 4 are automatic: + // * top - position explicitly on the top of the anchor, shrinking and adding scrollbar as needed. + // * bottom - position explicitly below the anchor, shrinking and adding scrollbar as needed. + // * left - position left of the anchor, shrinking and adding a vertical scrollbar as needed. + // * right - position right of the anchor, shrinking and adding a vertical scroolbar as needed. + // * auto - Automatic placement. + // * autohorizontal - Automatic placement (only left or right). + // * autovertical - Automatic placement (only top or bottom). + // * _cascasde - Private placement used by MenuCommand._activateFlyoutCommand + // Auto tests the height of the anchor and the flyout. For consistency in orientation, we imagine + // that the anchor is placed in the vertical center of the display. If the flyout would fit above + // that centered anchor, then we will place the flyout vertically in relation to the anchor, otherwise + // placement will be horizontal. + // Vertical auto or autovertical placement will be positioned on top of the anchor if room, otherwise below the anchor. + // - this is because touch users would be more likely to obscure flyouts below the anchor. + // Horizontal auto or autohorizontal placement will be positioned to the left of the anchor if room, otherwise to the right. + // - this is because right handed users would be more likely to obscure a flyout on the right of the anchor. + // All three auto placements will add a vertical scrollbar if necessary. + // + _getTopLeft: function Flyout_getTopLeft() { + + var that = this; + + function configureVerticalWithScroll(anchor) { + // Won't fit top or bottom. Pick the one with the most space and add a scrollbar. + if (topHasMoreRoom(anchor)) { + // Top + that._adjustedHeight = spaceAbove(anchor) - that._verticalMarginBorderPadding; + that._nextTop = _Overlay._Overlay._keyboardInfo._visibleDocTop; + that._nextAnimOffset = AnimationOffsets.top; + } else { + // Bottom + that._adjustedHeight = spaceBelow(anchor) - that._verticalMarginBorderPadding; + that._nextTop = _Constants.pinToBottomEdge; + that._nextAnimOffset = AnimationOffsets.bottom; + } + that._doesScroll = true; + } + + // If the anchor is centered vertically, would the flyout fit above it? + function fitsVerticallyWithCenteredAnchor(anchor, flyout) { + // Returns true if the flyout would always fit at least top + // or bottom of its anchor, regardless of the position of the anchor, + // as long as the anchor never changed its height, nor did the height of + // the visualViewport change. + return ((_Overlay._Overlay._keyboardInfo._visibleDocHeight - anchor.height) / 2) >= flyout.totalHeight; + } + + function spaceAbove(anchor) { + return anchor.top - _Overlay._Overlay._keyboardInfo._visibleDocTop; + } + + function spaceBelow(anchor) { + return _Overlay._Overlay._keyboardInfo._visibleDocBottom - anchor.bottom; + } + + function topHasMoreRoom(anchor) { + return spaceAbove(anchor) > spaceBelow(anchor); + } + + // See if we can fit in various places, fitting in the main view, + // ignoring viewport changes, like for the IHM. + function fitTop(bottomConstraint, flyout) { + that._nextTop = bottomConstraint - flyout.totalHeight; + that._nextAnimOffset = AnimationOffsets.top; + return (that._nextTop >= _Overlay._Overlay._keyboardInfo._visibleDocTop && + that._nextTop + flyout.totalHeight <= _Overlay._Overlay._keyboardInfo._visibleDocBottom); + } + + function fitBottom(topConstraint, flyout) { + that._nextTop = topConstraint; + that._nextAnimOffset = AnimationOffsets.bottom; + return (that._nextTop >= _Overlay._Overlay._keyboardInfo._visibleDocTop && + that._nextTop + flyout.totalHeight <= _Overlay._Overlay._keyboardInfo._visibleDocBottom); + } + + function fitLeft(leftConstraint, flyout) { + that._nextLeft = leftConstraint - flyout.totalWidth; + that._nextAnimOffset = AnimationOffsets.left; + return (that._nextLeft >= 0 && that._nextLeft + flyout.totalWidth <= _Overlay._Overlay._keyboardInfo._visualViewportWidth); + } + + function fitRight(rightConstraint, flyout) { + that._nextLeft = rightConstraint; + that._nextAnimOffset = AnimationOffsets.right; + return (that._nextLeft >= 0 && that._nextLeft + flyout.totalWidth <= _Overlay._Overlay._keyboardInfo._visualViewportWidth); + } + + function centerVertically(anchor, flyout) { + that._nextTop = anchor.top + anchor.height / 2 - flyout.totalHeight / 2; + if (that._nextTop < _Overlay._Overlay._keyboardInfo._visibleDocTop) { + that._nextTop = _Overlay._Overlay._keyboardInfo._visibleDocTop; + } else if (that._nextTop + flyout.totalHeight >= _Overlay._Overlay._keyboardInfo._visibleDocBottom) { + // Flag to pin to bottom edge of visual document. + that._nextTop = _Constants.pinToBottomEdge; + } + } + + function alignHorizontally(anchor, flyout, alignment) { + if (alignment === "center") { + that._nextLeft = anchor.left + anchor.width / 2 - flyout.totalWidth / 2; + } else if (alignment === "left") { + that._nextLeft = anchor.left; + } else if (alignment === "right") { + that._nextLeft = anchor.right - flyout.totalWidth; + } else { + throw new _ErrorFromName("WinJS.UI.Flyout.BadAlignment", strings.badAlignment); + } + if (that._nextLeft < 0) { + that._nextLeft = 0; + } else if (that._nextLeft + flyout.totalWidth >= _Overlay._Overlay._keyboardInfo._visualViewportWidth) { + // Flag to pin to right edge of visible document. + that._nextLeft = _Constants.pinToRightEdge; + } + } + + var anchorRawRectangle, + flyout = {}, + anchor = {}; + + try { + anchorRawRectangle = this._currentAnchor.getBoundingClientRect(); + } + catch (e) { + throw new _ErrorFromName("WinJS.UI.Flyout.NoAnchor", strings.noAnchor); + } + + // Adjust for the anchor's margins. + anchor.top = anchorRawRectangle.top; + anchor.bottom = anchorRawRectangle.bottom; + anchor.left = anchorRawRectangle.left; + anchor.right = anchorRawRectangle.right; + anchor.height = anchor.bottom - anchor.top; + anchor.width = anchor.right - anchor.left; + + // Get our flyout and margins, note that getDimension calls + // window.getComputedStyle, which ensures layout is updated. + flyout.marginTop = getDimension(this._element, "marginTop"); + flyout.marginBottom = getDimension(this._element, "marginBottom"); + flyout.marginLeft = getDimension(this._element, "marginLeft"); + flyout.marginRight = getDimension(this._element, "marginRight"); + flyout.totalWidth = _ElementUtilities.getTotalWidth(this._element); + flyout.totalHeight = _ElementUtilities.getTotalHeight(this._element); + flyout.contentWidth = _ElementUtilities.getContentWidth(this._element); + flyout.contentHeight = _ElementUtilities.getContentHeight(this._element); + this._verticalMarginBorderPadding = (flyout.totalHeight - flyout.contentHeight); + this._adjustedHeight = flyout.contentHeight; + + // Check fit for requested this._currentPlacement, doing fallback if necessary + switch (this._currentPlacement) { + case "top": + if (!fitTop(anchor.top, flyout)) { + // Didn't fit, needs scrollbar + this._nextTop = _Overlay._Overlay._keyboardInfo._visibleDocTop; + this._doesScroll = true; + this._adjustedHeight = spaceAbove(anchor) - this._verticalMarginBorderPadding; + } + alignHorizontally(anchor, flyout, this._currentAlignment); + break; + case "bottom": + if (!fitBottom(anchor.bottom, flyout)) { + // Didn't fit, needs scrollbar + this._nextTop = _Constants.pinToBottomEdge; + this._doesScroll = true; + this._adjustedHeight = spaceBelow(anchor) - this._verticalMarginBorderPadding; + } + alignHorizontally(anchor, flyout, this._currentAlignment); + break; + case "left": + if (!fitLeft(anchor.left, flyout)) { + // Didn't fit, just shove it to edge + this._nextLeft = 0; + } + centerVertically(anchor, flyout); + break; + case "right": + if (!fitRight(anchor.right, flyout)) { + // Didn't fit, just shove it to edge + this._nextLeft = _Constants.pinToRightEdge; + } + centerVertically(anchor, flyout); + break; + case "autovertical": + if (!fitTop(anchor.top, flyout)) { + // Didn't fit above (preferred), so go below. + if (!fitBottom(anchor.bottom, flyout)) { + // Didn't fit, needs scrollbar + configureVerticalWithScroll(anchor); + } + } + alignHorizontally(anchor, flyout, this._currentAlignment); + break; + case "autohorizontal": + if (!fitLeft(anchor.left, flyout)) { + // Didn't fit left (preferred), so go right. + if (!fitRight(anchor.right, flyout)) { + // Didn't fit,just shove it to edge + this._nextLeft = _Constants.pinToRightEdge; + } + } + centerVertically(anchor, flyout); + break; + case "auto": + // Auto, if the anchor was in the vertical center of the display would we fit above it? + if (fitsVerticallyWithCenteredAnchor(anchor, flyout)) { + // It will fit above or below the anchor + if (!fitTop(anchor.top, flyout)) { + // Didn't fit above (preferred), so go below. + fitBottom(anchor.bottom, flyout); + } + alignHorizontally(anchor, flyout, this._currentAlignment); + } else { + // Won't fit above or below, try a side + if (!fitLeft(anchor.left, flyout) && + !fitRight(anchor.right, flyout)) { + // Didn't fit left or right either + configureVerticalWithScroll(anchor); + alignHorizontally(anchor, flyout, this._currentAlignment); + } else { + centerVertically(anchor, flyout); + } + } + break; + case "_cascade": + // Align vertically + // PREFERRED: When there is enough room to align a subMenu to either the top or the bottom of its + // anchor element, the subMenu prefers to be top aligned. + // FALLBACK: When there is enough room to bottom align a subMenu but not enough room to top align it, + // then the subMenu will align to the bottom of its anchor element. + // LASTRESORT: When there is not enough room to top align or bottom align the subMenu to its anchor, + // then the subMenu will be center aligned to it's anchor's vertical midpoint. + if (!fitBottom(anchor.top - flyout.marginTop, flyout) && !fitTop(anchor.bottom + flyout.marginBottom, flyout)) { + centerVertically(anchor, flyout); + } + // Determine horizontal direction + // PREFERRED: When there is enough room to fit a subMenu on either side of the anchor, + // the subMenu prefers to go on the right hand side. + // FALLBACK: When there is only enough room to fit a subMenu on the left side of the anchor, + // the subMenu is placed to the left of the parent menu. + // LASTRESORT: When there is not enough room to fit a subMenu on either side of the anchor, + // the subMenu is pinned to the right edge of the window. + var rtl = _Global.getComputedStyle(this._element).direction === "rtl"; + + // Cascading Menus should overlap their ancestor menu by 4 pixels and we have a unit test to + // verify that behavior. Because we don't have access to the ancestor flyout we need to specify + // the overlap in terms of our anchor element. There is a 1px border around the menu that + // contains our anchor we need to overlap our anchor by 3px to ensure that we overlap the containing + // Menu by 4px. + var pixelsToOverlapAnchor = 3; + + var beginRight = anchor.right - flyout.marginLeft - pixelsToOverlapAnchor; + var beginLeft = anchor.left + flyout.marginRight + pixelsToOverlapAnchor; + + if (rtl) { + if (!fitLeft(beginLeft, flyout) && !fitRight(beginRight, flyout)) { + // Doesn't fit on either side, pin to the left edge. + that._nextLeft = 0; + that._nextAnimOffset = AnimationOffsets.left; + } + } else { + if (!fitRight(beginRight, flyout) && !fitLeft(beginLeft, flyout)) { + // Doesn't fit on either side, pin to the right edge of the visible document. + that._nextLeft = _Constants.pinToRightEdge; + that._nextAnimOffset = AnimationOffsets.right; + } + } + + break; + default: + // Not a legal this._currentPlacement value + throw new _ErrorFromName("WinJS.UI.Flyout.BadPlacement", strings.badPlacement); + } + }, + + _clearAdjustedStyles: function Flyout_clearAdjustedStyles() { + // Move to 0,0 in case it is off screen, so that it lays out at a reasonable size + this._element.style.top = "0px"; + this._element.style.bottom = "auto"; + this._element.style.left = "0px"; + this._element.style.right = "auto"; + + // Clear height restrictons and scrollbar class + _ElementUtilities.removeClass(this._element, _Constants.scrollsClass); + if (this._lastMaxHeight !== null) { + this._element.style.maxHeight = this._lastMaxHeight; + this._lastMaxHeight = null; + } + + // Clear Alignment + _ElementUtilities.removeClass(this._element, "win-rightalign"); + _ElementUtilities.removeClass(this._element, "win-leftalign"); + }, + + _setAlignment: function Flyout_setAlignment(alignment) { + // Alignment + switch (alignment) { + case "left": + _ElementUtilities.addClass(this._element, "win-leftalign"); + break; + case "right": + _ElementUtilities.addClass(this._element, "win-rightalign"); + break; + case "center": + case "none": + break; + } + }, + + _showingKeyboard: function Flyout_showingKeyboard(event) { + if (this.hidden) { + return; + } + + // The only way that we can be showing a keyboard when a flyout is up is because the input was + // in the flyout itself, in which case we'll be moving ourselves. There is no practical way + // for the application to override this as the focused element is in our flyout. + event.ensuredFocusedElementInView = true; + + // See if the keyboard is going to force us to move + this._checkKeyboardFit(); + + if (this._keyboardMovedUs) { + // Pop out immediately, then move to new spot + this._element.style.opacity = 0; + var that = this; + _Global.setTimeout(function () { that._adjustForKeyboard(); that._baseAnimateIn(); }, _Overlay._Overlay._keyboardInfo._animationShowLength); + } + }, + + _resize: function Flyout_resize() { + // If hidden and not busy animating, then nothing to do + if (!this.hidden || this._animating) { + + // This should only happen if the IHM is dismissing, + // the only other way is for viewstate changes, which + // would dismiss any flyout. + if (this._needToHandleHidingKeyboard) { + // Hiding keyboard, update our position, giving the anchor a chance to update first. + var that = this; + _BaseUtils._setImmediate(function () { + if (!that.hidden || that._animating) { + that._findPosition(); + } + }); + this._needToHandleHidingKeyboard = false; + } + } + }, + + // If you were not pinned to the bottom, you might have to be now. + _checkKeyboardFit: function Flyout_checkKeyboardFit() { + // Special Flyout positioning rules to determine if the Flyout needs to adjust its + // position because of the IHM. If the Flyout needs to adjust for the IHM, it will reposition + // itself to be pinned to either the top or bottom edge of the visual viewport. + // - Too Tall, above top, or below bottom. + + var keyboardMovedUs = false; + var viewportHeight = _Overlay._Overlay._keyboardInfo._visibleDocHeight; + var adjustedMarginBoxHeight = this._adjustedHeight + this._verticalMarginBorderPadding; + if (adjustedMarginBoxHeight > viewportHeight) { + // The Flyout is now too tall to fit in the viewport, pin to top and adjust height. + keyboardMovedUs = true; + this._nextTop = _Constants.pinToBottomEdge; + this._adjustedHeight = viewportHeight - this._verticalMarginBorderPadding; + this._doesScroll = true; + } else if (this._nextTop >= 0 && + this._nextTop + adjustedMarginBoxHeight > _Overlay._Overlay._keyboardInfo._visibleDocBottom) { + // Flyout clips the bottom of the viewport. Pin to bottom. + this._nextTop = _Constants.pinToBottomEdge; + keyboardMovedUs = true; + } else if (this._nextTop === _Constants.pinToBottomEdge) { + // We were already pinned to the bottom, so our position on screen will change + keyboardMovedUs = true; + } + + // Signals use of basic fadein animation + this._keyboardMovedUs = keyboardMovedUs; + }, + + _adjustForKeyboard: function Flyout_adjustForKeyboard() { + // Keyboard moved us, update our metrics as needed + if (this._doesScroll) { + // Add scrollbar if we didn't already have scrollsClass + if (!this._lastMaxHeight) { + _ElementUtilities.addClass(this._element, _Constants.scrollsClass); + this._lastMaxHeight = this._element.style.maxHeight; + } + // Adjust height + this._element.style.maxHeight = this._adjustedHeight + "px"; + } + + // Update top/bottom + this._checkScrollPosition(true); + }, + + _hidingKeyboard: function Flyout_hidingKeyboard() { + // If we aren't visible and not animating, or haven't been repositioned, then nothing to do + // We don't know if the keyboard moved the anchor, so _keyboardMovedUs doesn't help here + if (!this.hidden || this._animating) { + + // Snap to the final position + // We'll either just reveal the current space or resize the window + if (_Overlay._Overlay._keyboardInfo._isResized) { + // Flag resize that we'll need an updated position + this._needToHandleHidingKeyboard = true; + } else { + // Not resized, update our final position, giving the anchor a chance to update first. + var that = this; + _BaseUtils._setImmediate(function () { + if (!that.hidden || that._animating) { + that._findPosition(); + } + }); + } + } + }, + + _checkScrollPosition: function Flyout_checkScrollPosition(showing) { + if (this.hidden && !showing) { + return; + } + + // May need to adjust top by viewport offset + if (this._nextTop < 0) { + // Need to attach to bottom + this._element.style.bottom = _Overlay._Overlay._keyboardInfo._visibleDocBottomOffset + "px"; + this._element.style.top = "auto"; + } else { + // Normal, attach to top + this._element.style.top = this._nextTop + "px"; + this._element.style.bottom = "auto"; + } + }, + + // AppBar flyout animations + _flyoutAnimateIn: function Flyout_flyoutAnimateIn() { + if (this._keyboardMovedUs) { + return this._baseAnimateIn(); + } else { + this._element.style.opacity = 1; + this._element.style.visibility = "visible"; + return Animations.showPopup(this._element, this._nextAnimOffset); + } + }, + + _flyoutAnimateOut: function Flyout_flyoutAnimateOut() { + if (this._keyboardMovedUs) { + return this._baseAnimateOut(); + } else { + this._element.style.opacity = 0; + return Animations.hidePopup(this._element, this._nextAnimOffset); + } + }, + + // Hide all other flyouts besides this one + _hideAllOtherFlyouts: function Flyout_hideAllOtherFlyouts(thisFlyout) { + var flyouts = _Global.document.querySelectorAll("." + _Constants.flyoutClass); + for (var i = 0; i < flyouts.length; i++) { + var flyoutControl = flyouts[i].winControl; + if (flyoutControl && !flyoutControl.hidden && (flyoutControl !== thisFlyout)) { + flyoutControl.hide(); + } + } + }, + + _handleKeyDown: function Flyout_handleKeyDown(event) { + if ((event.keyCode === Key.space || event.keyCode === Key.enter) + && (this === _Global.document.activeElement)) { + event.preventDefault(); + event.stopPropagation(); + this.winControl.hide(); + } else if (event.shiftKey && event.keyCode === Key.tab + && this === _Global.document.activeElement + && !event.altKey && !event.ctrlKey && !event.metaKey) { + event.preventDefault(); + event.stopPropagation(); + this.winControl._focusOnLastFocusableElementOrThis(); + } + }, + + _handleFocusIn: function Flyout_handleFocusIn(event) { + if (!this.element.contains(event.relatedTarget)) { + Flyout._cascadeManager.handleFocusIntoFlyout(event); + } + // Else focus is only moving between elements in the flyout. + // Doesn't need to be handled by cascadeManager. + }, + + // Create and add a new first div as the first child + _addFirstDiv: function Flyout_addFirstDiv() { + var firstDiv = _Global.document.createElement("div"); + firstDiv.className = _Constants.firstDivClass; + firstDiv.style.display = "inline"; + firstDiv.setAttribute("role", "menuitem"); + firstDiv.setAttribute("aria-hidden", "true"); + + // add to beginning + if (this._element.children[0]) { + this._element.insertBefore(firstDiv, this._element.children[0]); + } else { + this._element.appendChild(firstDiv); + } + + var that = this; + _ElementUtilities._addEventListener(firstDiv, "focusin", function () { that._focusOnLastFocusableElementOrThis(); }, false); + + return firstDiv; + }, + + // Create and add a new final div as the last child + _addFinalDiv: function Flyout_addFinalDiv() { + var finalDiv = _Global.document.createElement("div"); + finalDiv.className = _Constants.finalDivClass; + finalDiv.style.display = "inline"; + finalDiv.setAttribute("role", "menuitem"); + finalDiv.setAttribute("aria-hidden", "true"); + + this._element.appendChild(finalDiv); + var that = this; + _ElementUtilities._addEventListener(finalDiv, "focusin", function () { that._focusOnFirstFocusableElementOrThis(); }, false); + + return finalDiv; + }, + + _writeProfilerMark: function Flyout_writeProfilerMark(text) { + _WriteProfilerMark("WinJS.UI.Flyout:" + this._id + ":" + text); + } + }, + { + _cascadeManager: new _CascadeManager(), + }); + return Flyout; + }) + }); + +}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('WinJS/Controls/CommandingSurface/_Constants',["require", "exports"], function (require, exports) { + // CommandingSurface class names + exports.ClassNames = { + controlCssClass: "win-commandingsurface", + disposableCssClass: "win-disposable", + actionAreaCssClass: "win-commandingsurface-actionarea", + actionAreaContainerCssClass: "win-commandingsurface-actionareacontainer", + overflowButtonCssClass: "win-commandingsurface-overflowbutton", + spacerCssClass: "win-commandingsurface-spacer", + ellipsisCssClass: "win-commandingsurface-ellipsis", + overflowAreaCssClass: "win-commandingsurface-overflowarea", + overflowAreaContainerCssClass: "win-commandingsurface-overflowareacontainer", + contentFlyoutCssClass: "win-commandingsurface-contentflyout", + emptyCommandingSurfaceCssClass: "win-commandingsurface-empty", + menuCssClass: "win-menu", + menuContainsToggleCommandClass: "win-menu-containstogglecommand", + openedClass: "win-commandingsurface-opened", + closingClass: "win-commandingsurface-closing", + closedClass: "win-commandingsurface-closed", + noneClass: "win-commandingsurface-closeddisplaynone", + minimalClass: "win-commandingsurface-closeddisplayminimal", + compactClass: "win-commandingsurface-closeddisplaycompact", + fullClass: "win-commandingsurface-closeddisplayfull", + overflowTopClass: "win-commandingsurface-overflowtop", + overflowBottomClass: "win-commandingsurface-overflowbottom", + }; + exports.EventNames = { + beforeOpen: "beforeopen", + afterOpen: "afteropen", + beforeClose: "beforeclose", + afterClose: "afterclose", + commandPropertyMutated: "_commandpropertymutated", + }; + exports.actionAreaCommandWidth = 68; + exports.actionAreaSeparatorWidth = 34; + exports.actionAreaOverflowButtonWidth = 32; + exports.overflowCommandHeight = 44; + exports.overflowSeparatorHeight = 12; + exports.controlMinWidth = exports.actionAreaOverflowButtonWidth; + exports.overflowAreaMaxWidth = 480; + exports.heightOfMinimal = 24; + exports.heightOfCompact = 48; + exports.contentMenuCommandDefaultLabel = "Custom content"; + exports.defaultClosedDisplayMode = "compact"; + exports.defaultOpened = false; + exports.defaultOverflowDirection = "bottom"; + // Constants for commands + exports.typeSeparator = "separator"; + exports.typeContent = "content"; + exports.typeButton = "button"; + exports.typeToggle = "toggle"; + exports.typeFlyout = "flyout"; + exports.commandSelector = ".win-command"; + exports.primaryCommandSection = "primary"; + exports.secondaryCommandSection = "secondary"; +}); + +define('WinJS/Controls/ToolBar/_Constants',["require", "exports", "../CommandingSurface/_Constants"], function (require, exports, _CommandingSurfaceConstants) { + // toolbar class names + exports.ClassNames = { + controlCssClass: "win-toolbar", + disposableCssClass: "win-disposable", + actionAreaCssClass: "win-toolbar-actionarea", + overflowButtonCssClass: "win-toolbar-overflowbutton", + spacerCssClass: "win-toolbar-spacer", + ellipsisCssClass: "win-toolbar-ellipsis", + overflowAreaCssClass: "win-toolbar-overflowarea", + contentFlyoutCssClass: "win-toolbar-contentflyout", + emptytoolbarCssClass: "win-toolbar-empty", + menuCssClass: "win-menu", + menuContainsToggleCommandClass: "win-menu-containstogglecommand", + openedClass: "win-toolbar-opened", + closedClass: "win-toolbar-closed", + compactClass: "win-toolbar-closeddisplaycompact", + fullClass: "win-toolbar-closeddisplayfull", + overflowTopClass: "win-toolbar-overflowtop", + overflowBottomClass: "win-toolbar-overflowbottom", + placeHolderCssClass: "win-toolbar-placeholder", + }; + exports.EventNames = { + beforeOpen: "beforeopen", + afterOpen: "afteropen", + beforeClose: "beforeclose", + afterClose: "afterclose" + }; + exports.OverflowDirection = { + top: "top", + bottom: "bottom", + }; + exports.overflowAreaMaxWidth = _CommandingSurfaceConstants.overflowAreaMaxWidth; + exports.controlMinWidth = _CommandingSurfaceConstants.controlMinWidth; + exports.defaultClosedDisplayMode = "compact"; + exports.defaultOpened = false; + // Constants for commands + exports.typeSeparator = "separator"; + exports.typeContent = "content"; + exports.typeButton = "button"; + exports.typeToggle = "toggle"; + exports.typeFlyout = "flyout"; + exports.commandSelector = ".win-command"; + exports.primaryCommandSection = "primary"; + exports.secondaryCommandSection = "secondary"; +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +// Glyph Enumeration +/// Segoe +define('WinJS/Controls/AppBar/_Icon',[ + 'exports', + '../../Core/_Base', + '../../Core/_Resources' + ], function appBarIconInit(exports, _Base, _Resources) { + "use strict"; + + var glyphs = ["previous", + "next", + "play", + "pause", + "edit", + "save", + "clear", + "delete", + "remove", + "add", + "cancel", + "accept", + "more", + "redo", + "undo", + "home", + "up", + "forward", + "right", + "back", + "left", + "favorite", + "camera", + "settings", + "video", + "sync", + "download", + "mail", + "find", + "help", + "upload", + "emoji", + "twopage", + "leavechat", + "mailforward", + "clock", + "send", + "crop", + "rotatecamera", + "people", + "closepane", + "openpane", + "world", + "flag", + "previewlink", + "globe", + "trim", + "attachcamera", + "zoomin", + "bookmarks", + "document", + "protecteddocument", + "page", + "bullets", + "comment", + "mail2", + "contactinfo", + "hangup", + "viewall", + "mappin", + "phone", + "videochat", + "switch", + "contact", + "rename", + "pin", + "musicinfo", + "go", + "keyboard", + "dockleft", + "dockright", + "dockbottom", + "remote", + "refresh", + "rotate", + "shuffle", + "list", + "shop", + "selectall", + "orientation", + "import", + "importall", + "browsephotos", + "webcam", + "pictures", + "savelocal", + "caption", + "stop", + "showresults", + "volume", + "repair", + "message", + "page2", + "calendarday", + "calendarweek", + "calendar", + "characters", + "mailreplyall", + "read", + "link", + "accounts", + "showbcc", + "hidebcc", + "cut", + "attach", + "paste", + "filter", + "copy", + "emoji2", + "important", + "mailreply", + "slideshow", + "sort", + "manage", + "allapps", + "disconnectdrive", + "mapdrive", + "newwindow", + "openwith", + "contactpresence", + "priority", + "uploadskydrive", + "gototoday", + "font", + "fontcolor", + "contact2", + "folder", + "audio", + "placeholder", + "view", + "setlockscreen", + "settile", + "cc", + "stopslideshow", + "permissions", + "highlight", + "disableupdates", + "unfavorite", + "unpin", + "openlocal", + "mute", + "italic", + "underline", + "bold", + "movetofolder", + "likedislike", + "dislike", + "like", + "alignright", + "aligncenter", + "alignleft", + "zoom", + "zoomout", + "openfile", + "otheruser", + "admin", + "street", + "map", + "clearselection", + "fontdecrease", + "fontincrease", + "fontsize", + "cellphone", + "reshare", + "tag", + "repeatone", + "repeatall", + "outlinestar", + "solidstar", + "calculator", + "directions", + "target", + "library", + "phonebook", + "memo", + "microphone", + "postupdate", + "backtowindow", + "fullscreen", + "newfolder", + "calendarreply", + "unsyncfolder", + "reporthacked", + "syncfolder", + "blockcontact", + "switchapps", + "addfriend", + "touchpointer", + "gotostart", + "zerobars", + "onebar", + "twobars", + "threebars", + "fourbars", + "scan", + "preview", + "hamburger"]; + + // Provide properties to grab resources for each of the icons + /// + /// The AppBarIcon enumeration provides a set of glyphs for use with the AppBarCommand icon property. + /// + var icons = glyphs.reduce(function (fixedIcons, item) { + fixedIcons[item] = { get: function () { return _Resources._getWinJSString("ui/appBarIcons/" + item).value; } }; + return fixedIcons; + }, {}); + + _Base.Namespace._moduleDefine(exports, "WinJS.UI.AppBarIcon", icons); +}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +// AppBarCommand +/// appbar,appbars,Flyout,Flyouts,onclick,Statics +define('WinJS/Controls/AppBar/_Command',[ + 'exports', + '../../Core/_Global', + '../../Core/_WinRT', + '../../Core/_Base', + "../../Core/_BaseUtils", + '../../Core/_ErrorFromName', + "../../Core/_Events", + '../../Core/_Resources', + '../../Utilities/_Control', + '../../Utilities/_Dispose', + '../../Utilities/_ElementUtilities', + '../Flyout/_Overlay', + '../Tooltip', + '../_LegacyAppBar/_Constants', + './_Icon' +], function appBarCommandInit(exports, _Global, _WinRT, _Base, _BaseUtils, _ErrorFromName, _Events, _Resources, _Control, _Dispose, _ElementUtilities, _Overlay, Tooltip, _Constants, _Icon) { + "use strict"; + + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + /// + /// + /// Represents a command to display in an AppBar. + /// + /// + /// + /// + /// ]]> + /// Raised after the hidden property has been programmatically changed. + /// The AppBarCommand control itself. + /// The AppBarCommand's icon box. + /// The AppBarCommand's icon's image formatting. + /// The AppBarCommand's label + /// + /// + AppBarCommand: _Base.Namespace._lazy(function () { + + function _handleClick(event) { + /*jshint validthis: true */ + var command = this.winControl; + if (command) { + if (command._type === _Constants.typeToggle) { + command.selected = !command.selected; + } else if (command._type === _Constants.typeFlyout && command._flyout) { + var flyout = command._flyout; + // Flyout may not have processAll'd, so this may be a DOM object + if (typeof flyout === "string") { + flyout = _Global.document.getElementById(flyout); + } + if (!flyout.show) { + flyout = flyout.winControl; + } + if (flyout && flyout.show) { + flyout.show(this, "autovertical"); + } + } + if (command.onclick) { + command.onclick(event); + } + } + } + + // Used by AppBarCommands to notify listeners that a property has changed. + var PropertyMutations = _Base.Class.define(function PropertyMutations_ctor() { + this._observer = _BaseUtils._merge({}, _Events.eventMixin); + }, { + bind: function (callback) { + this._observer.addEventListener(_Constants.commandPropertyMutated, callback); + }, + unbind: function (callback) { + this._observer.removeEventListener(_Constants.commandPropertyMutated, callback); + }, + dispatchEvent: function (type, detail) { + this._observer.dispatchEvent(type, detail); + }, + }); + + var strings = { + get ariaLabel() { return _Resources._getWinJSString("ui/appBarCommandAriaLabel").value; }, + get duplicateConstruction() { return "Invalid argument: Controls may only be instantiated one time for each DOM element"; }, + get badClick() { return "Invalid argument: The onclick property for an {0} must be a function"; }, + get badDivElement() { return "Invalid argument: For a content command, the element must be null or a div element"; }, + get badHrElement() { return "Invalid argument: For a separator, the element must be null or an hr element"; }, + get badButtonElement() { return "Invalid argument: For a button, toggle, or flyout command, the element must be null or a button element"; }, + get badPriority() { return "Invalid argument: the priority of an {0} must be a non-negative integer"; } + }; + + var AppBarCommand = _Base.Class.define(function AppBarCommand_ctor(element, options) { + /// + /// + /// Creates a new AppBarCommand control. + /// + /// + /// The DOM element that will host the control. AppBarCommand will create one if null. + /// + /// + /// The set of properties and values to apply to the new AppBarCommand. + /// + /// + /// The new AppBarCommand control. + /// + /// + + // Check to make sure we weren't duplicated + if (element && element.winControl) { + throw new _ErrorFromName("WinJS.UI.AppBarCommand.DuplicateConstruction", strings.duplicateConstruction); + } + + this._disposed = false; + + // Don't blow up if they didn't pass options + if (!options) { + options = {}; + } + + // Need a type before we can create our element + if (!options.type) { + this._type = _Constants.typeButton; + } + + options.section = options.section || _Constants.sectionPrimary; + + // Go ahead and create it, separator and content types look different than buttons + // Don't forget to use passed in element if one was provided. + this._element = element; + + if (options.type === _Constants.typeContent) { + this._createContent(); + } else if (options.type === _Constants.typeSeparator) { + this._createSeparator(); + } else { + // This will also set the icon & label + this._createButton(); + } + _ElementUtilities.addClass(this._element, "win-disposable"); + + // Remember ourselves + this._element.winControl = this; + + // Attach our css class + _ElementUtilities.addClass(this._element, _Constants.appBarCommandClass); + + if (options.onclick) { + this.onclick = options.onclick; + } + // We want to handle some clicks + options.onclick = _handleClick; + + _Control.setOptions(this, options); + + if (this._type === _Constants.typeToggle && !options.selected) { + this.selected = false; + } + + // Set up pointerdown handler and clean up ARIA if needed + if (this._type !== _Constants.typeSeparator) { + + // Make sure we have an ARIA role + var role = this._element.getAttribute("role"); + if (role === null || role === "" || role === undefined) { + if (this._type === _Constants.typeToggle) { + role = "menuitemcheckbox"; + } else if (this._type === _Constants.typeContent) { + role = "group"; + } else { + role = "menuitem"; + } + this._element.setAttribute("role", role); + if (this._type === _Constants.typeFlyout) { + this._element.setAttribute("aria-haspopup", true); + } + } + // Label should've been set by label, but if it was missed for some reason: + var label = this._element.getAttribute("aria-label"); + if (label === null || label === "" || label === undefined) { + this._element.setAttribute("aria-label", strings.ariaLabel); + } + } + + this._propertyMutations = new PropertyMutations(); + var that = this; + ObservablePropertyWhiteList.forEach(function (propertyName) { + makeObservable(that, propertyName); + }); + }, { + /// + /// Gets or sets the ID of the AppBarCommand. + /// + id: { + get: function () { + return this._element.id; + }, + + set: function (value) { + // we allow setting first time only. otherwise we ignore it. + if (value && !this._element.id) { + this._element.id = value; + } + } + }, + + /// + /// Gets or sets the type of the AppBarCommand. Possible values are "button", "toggle", "flyout", "content" or "separator". + /// + type: { + get: function () { + return this._type; + }, + set: function (value) { + // we allow setting first time only. otherwise we ignore it. + if (!this._type) { + if (value !== _Constants.typeContent && value !== _Constants.typeFlyout && value !== _Constants.typeToggle && value !== _Constants.typeSeparator) { + this._type = _Constants.typeButton; + } else { + this._type = value; + } + } + } + }, + + /// + /// Gets or sets the label of the AppBarCommand. + /// + label: { + get: function () { + return this._label; + }, + set: function (value) { + this._label = value; + if (this._labelSpan) { + this._labelSpan.textContent = this.label; + } + + // Ensure that we have a tooltip, by updating already-constructed tooltips. Separators won't have these: + if (!this.tooltip && this._tooltipControl) { + this._tooltip = this.label; + this._tooltipControl.innerHTML = this.label; + } + + // Update aria-label + this._element.setAttribute("aria-label", this.label); + + // Check if we need to suppress the tooltip + this._testIdenticalTooltip(); + } + }, + + /// + /// Gets or sets the icon of the AppBarCommand. + /// + icon: { + get: function () { + return this._icon; + }, + set: function (value) { + + this._icon = _Icon[value] || value; + + if (this._imageSpan) { + // If the icon's a single character, presume a glyph + if (this._icon && this._icon.length === 1) { + // Set the glyph + this._imageSpan.textContent = this._icon; + this._imageSpan.style.backgroundImage = ""; + this._imageSpan.style.msHighContrastAdjust = ""; + _ElementUtilities.addClass(this._imageSpan, "win-commandglyph"); + } else { + // Must be an image, set that + this._imageSpan.textContent = ""; + this._imageSpan.style.backgroundImage = this._icon; + this._imageSpan.style.msHighContrastAdjust = "none"; + _ElementUtilities.removeClass(this._imageSpan, "win-commandglyph"); + } + } + } + }, + + /// + /// Gets or sets the function to invoke when the command is clicked. + /// + onclick: { + get: function () { + return this._onclick; + }, + set: function (value) { + if (value && typeof value !== "function") { + throw new _ErrorFromName("WinJS.UI.AppBarCommand.BadClick", _Resources._formatString(strings.badClick, "AppBarCommand")); + } + this._onclick = value; + } + }, + + /// + /// Gets or sets the priority of the command + /// + priority: { + get: function () { + return this._priority; + }, + set: function (value) { + if (value === undefined || (typeof value === "number" && value >= 0)) { + this._priority = value; + } else { + throw new _ErrorFromName("WinJS.UI.AppBarCommand.BadPriority", _Resources._formatString(strings.badPriority, "AppBarCommand")); + } + + } + }, + + /// + /// For flyout-type AppBarCommands, this property returns the WinJS.UI.Flyout that this command invokes. + /// When setting this property, you may also use the String ID of the flyout to invoke, the DOM object + /// for the flyout, or the WinJS.UI.Flyout object itself. + /// If the value is set to the String ID of the flyout to invoke, or the DOM object for the flyout, but this + /// has not been processed yet, the getter will return the DOM object until it is processed, and + /// subsequently return a flyout. + /// + flyout: { + get: function () { + // Resolve it to the flyout + var flyout = this._flyout; + if (typeof flyout === "string") { + flyout = _Global.document.getElementById(flyout); + } + // If it doesn't have a .element, then we need to getControl on it + if (flyout && !flyout.element && flyout.winControl) { + flyout = flyout.winControl; + } + + return flyout; + }, + set: function (value) { + // Need to update aria-owns with the new ID. + var id = value; + if (id && typeof id !== "string") { + // Our controls have .element properties + if (id.element) { + id = id.element; + } + // Hope it's a DOM element, get ID from DOM element + if (id) { + if (id.id) { + id = id.id; + } else { + // No id, have to fake one + id.id = _ElementUtilities._uniqueID(id); + id = id.id; + } + } + } + if (typeof id === "string") { + this._element.setAttribute("aria-owns", id); + } + + // Remember it + this._flyout = value; + } + }, + + /// + /// Gets or sets the section that the AppBarCommand is in. Possible values are "secondary" and "primary". + /// + section: { + get: function () { + return this._section; + }, + set: function (value) { + // we allow settings section only one time + if (!this._section || _WinRT.Windows.ApplicationModel.DesignMode.designModeEnabled) { + this._setSection(value); + } + } + }, + + /// Gets or sets the tooltip text of the AppBarCommand. + tooltip: { + get: function () { + return this._tooltip; + }, + set: function (value) { + this._tooltip = value; + + // Update already-constructed tooltips. Separators and content commands won't have these: + if (this._tooltipControl) { + this._tooltipControl.innerHTML = this._tooltip; + } + + // Check if we need to suppress the tooltip + this._testIdenticalTooltip(); + } + }, + + /// Set or get the selected state of a toggle button. + selected: { + get: function () { + // Ensure it's a boolean because we're using the DOM element to keep in-sync + return this._element.getAttribute("aria-checked") === "true"; + }, + set: function (value) { + this._element.setAttribute("aria-checked", value); + } + }, + + /// + element: { + get: function () { + return this._element; + } + }, + + /// + /// Gets or sets a value that indicates whether the AppBarCommand is disabled. A value of true disables the AppBarCommand, and a value of false enables it. + /// + disabled: { + get: function () { + // Ensure it's a boolean because we're using the DOM element to keep in-sync + return !!this._element.disabled; + }, + set: function (value) { + this._element.disabled = value; + } + }, + + /// + hidden: { + get: function () { + // Ensure it's a boolean because we're using the DOM element to keep in-sync + return this._element.style.visibility === "hidden"; + }, + set: function (value) { + if (value === this.hidden) { + // No changes to make. + return; + } + + var style = this._element.style; + var originalVisibility = style.visibility; + var originalDisplay = style.display; + + if (value) { + style.visibility = "hidden"; + style.display = "none"; + } else { + style.visibility = ""; + style.display = "inline-block"; + } + + if (!this._sendEvent(_Constants.commandVisibilityChanged)) { + style.visibility = originalVisibility; + style.display = originalDisplay; + } + } + }, + + /// + /// Gets or sets the HTMLElement within a "content" type AppBarCommand that should receive focus whenever focus moves via Home or the arrow keys, + /// from the previous AppBarCommand to the this AppBarCommand. Returns the AppBarCommand object's host element by default. + /// + firstElementFocus: { + get: function () { + return this._firstElementFocus || this._lastElementFocus || this._element; + }, + set: function (element) { + // Arguments of null and this.element should treated the same to ensure that this.element is never a tabstop when either focus property has been set. + this._firstElementFocus = (element === this.element) ? null : element; + this._updateTabStop(); + } + }, + + /// + /// Gets or sets the HTMLElement within a "content" type AppBarCommand that should receive focus whenever focus would move, via End or arrow keys, + /// from the next AppBarCommand to this AppBarCommand. Returns this AppBarCommand object's host element by default. + /// + lastElementFocus: { + get: function () { + return this._lastElementFocus || this._firstElementFocus || this._element; + }, + set: function (element) { + // Arguments of null and this.element should treated the same to ensure that this.element is never a tabstop when either focus property has been set. + this._lastElementFocus = (element === this.element) ? null : element; + this._updateTabStop(); + } + }, + + dispose: function () { + /// + /// + /// Disposes this control. + /// + /// + if (this._disposed) { + return; + } + this._disposed = true; + + if (this._tooltipControl) { + this._tooltipControl.dispose(); + } + + if (this._type === _Constants.typeContent) { + _Dispose.disposeSubTree(this.element); + } + }, + + addEventListener: function (type, listener, useCapture) { + /// + /// + /// Registers an event handler for the specified event. + /// + /// + /// Required. The name of the event to register. + /// + /// Required. The event handler function to associate with this event. + /// + /// Optional. Set to true to register the event handler for the capturing phase; otherwise, set to false to register the event handler for the bubbling phase. + /// + /// + return this._element.addEventListener(type, listener, useCapture); + }, + + removeEventListener: function (type, listener, useCapture) { + /// + /// + /// Removes an event handler that the addEventListener method registered. + /// + /// Required. The name of the event to remove. + /// Required. The event handler function to remove. + /// + /// Optional. Set to true to remove the capturing phase event handler; otherwise, set to false to remove the bubbling phase event handler. + /// + /// + return this._element.removeEventListener(type, listener, useCapture); + }, + + /// Adds an extra CSS class during construction. + extraClass: { + get: function () { + return this._extraClass; + }, + set: function (value) { + if (this._extraClass) { + _ElementUtilities.removeClass(this._element, this._extraClass); + } + this._extraClass = value; + _ElementUtilities.addClass(this._element, this._extraClass); + } + }, + + // Private + _testIdenticalTooltip: function AppBarCommand_testIdenticalToolTip() { + this._hideIfFullSize = (this._label === this._tooltip); + }, + + _createContent: function AppBarCommand_createContent() { + // Make sure there's an element + if (!this._element) { + this._element = _Global.document.createElement("div"); + } else { + // Verify the element was a div + if (this._element.tagName !== "DIV") { + throw new _ErrorFromName("WinJS.UI.AppBarCommand.BadDivElement", strings.badDivElement); + } + } + + // If a tabIndex isnt set, default to 0; + if (parseInt(this._element.getAttribute("tabIndex"), 10) !== this._element.tabIndex) { + this._element.tabIndex = 0; + } + }, + + _createSeparator: function AppBarCommand_createSeparator() { + // Make sure there's an element + if (!this._element) { + this._element = _Global.document.createElement("hr"); + } else { + // Verify the element was an hr + if (this._element.tagName !== "HR") { + throw new _ErrorFromName("WinJS.UI.AppBarCommand.BadHrElement", strings.badHrElement); + } + } + }, + + _createButton: function AppBarCommand_createButton() { + // Make sure there's an element + if (!this._element) { + this._element = _Global.document.createElement("button"); + } else { + // Verify the element was a button + if (this._element.tagName !== "BUTTON") { + throw new _ErrorFromName("WinJS.UI.AppBarCommand.BadButtonElement", strings.badButtonElement); + } + // Make sure it has a type="button" + var type = this._element.getAttribute("type"); + if (type === null || type === "" || type === undefined) { + this._element.setAttribute("type", "button"); + } + this._element.innerHTML = ""; + } + + // AppBarCommand buttons need to look like this: + //// + this._element.type = "button"; + this._iconSpan = _Global.document.createElement("span"); + this._iconSpan.setAttribute("aria-hidden", "true"); + this._iconSpan.className = "win-commandicon"; + this._iconSpan.tabIndex = -1; + this._element.appendChild(this._iconSpan); + this._imageSpan = _Global.document.createElement("span"); + this._imageSpan.setAttribute("aria-hidden", "true"); + this._imageSpan.className = "win-commandimage"; + this._imageSpan.tabIndex = -1; + this._iconSpan.appendChild(this._imageSpan); + this._labelSpan = _Global.document.createElement("span"); + this._labelSpan.setAttribute("aria-hidden", "true"); + this._labelSpan.className = "win-label"; + this._labelSpan.tabIndex = -1; + this._element.appendChild(this._labelSpan); + // 'win-global' or 'win-selection' are added later by caller. + // Label and icon are added later by caller. + + // Attach a tooltip - Note: we're going to stomp on it's setControl so we don't have to make another DOM element to hang it off of. + // This private _tooltipControl attribute is used by other pieces, changing the name could break them. + this._tooltipControl = new Tooltip.Tooltip(this._element); + var that = this; + this._tooltipControl.addEventListener("beforeopen", function () { + if (that._hideIfFullSize && !_Overlay._Overlay._getParentControlUsingClassName(that._element.parentElement, _Constants.reducedClass)) { + that._tooltipControl.close(); + } + }, false); + }, + + _setSection: function AppBarCommand_setSection(section) { + if (!section) { + section = _Constants.sectionPrimary; + } + + // _Constants.sectionSelection and _Constants.sectionGlobal are deprecated, so we will continue + // adding/removing its corresponding CSS class for app compat. + // _Constants.sectionPrimary and _Constants.sectionSecondary no longer apply CSS classes to the + // commands. + + if (this._section) { + // Remove the old section class + if (this._section === _Constants.sectionGlobal) { + _ElementUtilities.removeClass(this._element, _Constants.appBarCommandGlobalClass); + } else if (this.section === _Constants.sectionSelection) { + _ElementUtilities.removeClass(this._element, _Constants.appBarCommandSelectionClass); + } + } + // Add the new section class + this._section = section; + if (section === _Constants.sectionGlobal) { + _ElementUtilities.addClass(this._element, _Constants.appBarCommandGlobalClass); + } else if (section === _Constants.sectionSelection) { + _ElementUtilities.addClass(this._element, _Constants.appBarCommandSelectionClass); + } + }, + + _updateTabStop: function AppBarCommand_updateTabStop() { + // Whenever the firstElementFocus or lastElementFocus properties are set for content type AppBarCommands, + // the containing command element is no longer a tabstop. + + if (this._firstElementFocus || this._lastElementFocus) { + this.element.tabIndex = -1; + } else { + this.element.tabIndex = 0; + } + }, + + _isFocusable: function AppBarCommand_isFocusable() { + return (!this.hidden && this._type !== _Constants.typeSeparator && !this.element.disabled && + (this.firstElementFocus.tabIndex >= 0 || this.lastElementFocus.tabIndex >= 0)); + }, + + _sendEvent: function AppBarCommand_sendEvent(eventName, detail) { + if (this._disposed) { + return; + } + var event = _Global.document.createEvent("CustomEvent"); + event.initCustomEvent(eventName, true, true, (detail || {})); + return this._element.dispatchEvent(event); + }, + }); + + + // The list of AppBarCommand properties that we care about firing an event + // for, whenever they are changed after initial construction. + var ObservablePropertyWhiteList = [ + "label", + "disabled", + "flyout", + "extraClass", + "selected", + "onclick", + "hidden", + ]; + + function makeObservable(command, propertyName) { + // Make a pre-existing AppBarCommand property observable by firing the "_commandpropertymutated" + // event whenever its value changes. + + // Preserve initial value in JS closure variable + var _value = command[propertyName]; + + // Preserve original getter/setter if they exist, else use inline proxy functions. + var proto = command.constructor.prototype; + var originalDesc = getPropertyDescriptor(proto, propertyName) || {}; + var getter = originalDesc.get.bind(command) || function getterProxy() { + return _value; + }; + var setter = originalDesc.set.bind(command) || function setterProxy(value) { + _value = value; + }; + + // Define new observable Get/Set for propertyName on the command instance + Object.defineProperty(command, propertyName, { + get: function observable_get() { + return getter(); + }, + set: function observable_set(value) { + + var oldValue = getter(); + + // Process value through the original setter & getter before deciding to send an event. + setter(value); + var newValue = getter(); + if (!this._disposed && oldValue !== value && oldValue !== newValue && !command._disposed) { + + command._propertyMutations.dispatchEvent( + _Constants.commandPropertyMutated, + { + command: command, + propertyName: propertyName, + oldValue: oldValue, + newValue: newValue, + }); + } + } + }); + } + + function getPropertyDescriptor(obj, propertyName) { + // Returns a matching property descriptor, or null, + // if no matching descriptor is found. + var desc = null; + while (obj && !desc) { + desc = Object.getOwnPropertyDescriptor(obj, propertyName); + obj = Object.getPrototypeOf(obj); + // Walk obj's prototype chain until we find a match. + } + return desc; + } + + return AppBarCommand; + }) + }); + + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + Command: _Base.Namespace._lazy(function () { return exports.AppBarCommand; }) + }); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +// Menu Command +/// appbar,appbars,Flyout,Flyouts,onclick,Statics +define('WinJS/Controls/Menu/_Command',[ + 'exports', + '../../Core/_Global', + '../../Core/_Base', + '../../Core/_ErrorFromName', + '../../Core/_Resources', + '../../Promise', + '../../Utilities/_Control', + '../../Utilities/_ElementUtilities', + '../_LegacyAppBar/_Constants', + '../Flyout/_Overlay' +], function menuCommandInit(exports, _Global, _Base, _ErrorFromName, _Resources, Promise, _Control, _ElementUtilities, _Constants, _Overlay) { + "use strict"; + + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + /// + /// + /// Represents a command to be displayed in a Menu. MenuCommand objects provide button, toggle button, flyout button, + /// or separator functionality for Menu controls. + /// + /// + /// + /// + /// + /// ]]> + /// The MenuCommand control itself + /// + /// + MenuCommand: _Base.Namespace._lazy(function () { + + var strings = { + get ariaLabel() { return _Resources._getWinJSString("ui/menuCommandAriaLabel").value; }, + get duplicateConstruction() { return "Invalid argument: Controls may only be instantiated one time for each DOM element"; }, + get badClick() { return "Invalid argument: The onclick property for an {0} must be a function"; }, + get badHrElement() { return "Invalid argument: For a separator, the element must be null or an hr element"; }, + get badButtonElement() { return "Invalid argument: For a button, toggle, or flyout command, the element must be null or a button element"; } + }; + + var MenuCommand = _Base.Class.define(function MenuCommand_ctor(element, options) { + /// + /// + /// Creates a new MenuCommand object. + /// + /// + /// The DOM element that will host the control. + /// + /// + /// The set of properties and values to apply to the new MenuCommand. + /// + /// + /// A MenuCommand control. + /// + /// + /// + + // Check to make sure we weren't duplicated + if (element && element.winControl) { + throw new _ErrorFromName("WinJS.UI.MenuCommand.DuplicateConstruction", strings.duplicateConstruction); + } + + this._disposed = false; + + // Don't blow up if they didn't pass options + if (!options) { + options = {}; + } + + // Need a type before we can create our element + if (!options.type) { + this._type = _Constants.typeButton; + } + + // Go ahead and create it, separator types look different than buttons + // Don't forget to use passed in element if one was provided. + this._element = element; + if (options.type === _Constants.typeSeparator) { + this._createSeparator(); + } else { + // This will also set the icon & label + this._createButton(); + } + _ElementUtilities.addClass(this._element, "win-disposable"); + + // Remember ourselves + this._element.winControl = this; + + // Attach our css class + _ElementUtilities.addClass(this._element, _Constants.menuCommandClass); + + if (!options.selected && options.type === _Constants.typeToggle) { + // Make sure toggle's have selected false for CSS + this.selected = false; + } + + if (options.onclick) { + this.onclick = options.onclick; + } + options.onclick = this._handleClick.bind(this); + + _Control.setOptions(this, options); + + // Set our options + if (this._type !== _Constants.typeSeparator) { + // Make sure we have an ARIA role + var role = this._element.getAttribute("role"); + if (role === null || role === "" || role === undefined) { + role = "menuitem"; + if (this._type === _Constants.typeToggle) { + role = "menuitemcheckbox"; + } + this._element.setAttribute("role", role); + if (this._type === _Constants.typeFlyout) { + this._element.setAttribute("aria-haspopup", true); + } + } + var label = this._element.getAttribute("aria-label"); + if (label === null || label === "" || label === undefined) { + this._element.setAttribute("aria-label", strings.ariaLabel); + } + } + + }, { + /// + /// Gets the ID of the MenuCommand. + /// + /// + id: { + get: function () { + return this._element.id; + }, + set: function (value) { + // we allow setting first time only. otherwise we ignore it. + if (!this._element.id) { + this._element.id = value; + } + } + }, + + /// + /// Gets the type of the MenuCommand. Possible values are "button", "toggle", "flyout", or "separator". + /// + /// + type: { + get: function () { + return this._type; + }, + set: function (value) { + // we allow setting first time only. otherwise we ignore it. + if (!this._type) { + if (value !== _Constants.typeButton && value !== _Constants.typeFlyout && value !== _Constants.typeToggle && value !== _Constants.typeSeparator) { + value = _Constants.typeButton; + } + + this._type = value; + + if (value === _Constants.typeButton) { + _ElementUtilities.addClass(this.element, _Constants.menuCommandButtonClass); + } else if (value === _Constants.typeFlyout) { + _ElementUtilities.addClass(this.element, _Constants.menuCommandFlyoutClass); + this.element.addEventListener("keydown", this._handleKeyDown.bind(this), false); + } else if (value === _Constants.typeSeparator) { + _ElementUtilities.addClass(this.element, _Constants.menuCommandSeparatorClass); + } else if (value === _Constants.typeToggle) { + _ElementUtilities.addClass(this.element, _Constants.menuCommandToggleClass); + } + } + } + }, + + /// + /// The label of the MenuCommand + /// + /// + label: { + get: function () { + return this._label; + }, + set: function (value) { + this._label = value || ""; + if (this._labelSpan) { + this._labelSpan.textContent = this.label; + } + + // Update aria-label + this._element.setAttribute("aria-label", this.label); + } + }, + + /// + /// Gets or sets the function to invoke when the command is clicked. + /// + /// + onclick: { + get: function () { + return this._onclick; + }, + set: function (value) { + if (value && typeof value !== "function") { + throw new _ErrorFromName("WinJS.UI.MenuCommand.BadClick", _Resources._formatString(strings.badClick, "MenuCommand")); + } + this._onclick = value; + } + }, + + /// + /// For flyout type MenuCommands, this property returns the WinJS.UI.Flyout that this command invokes. When setting this property, you can set + /// it to the string ID of the Flyout, the DOM object that hosts the Flyout, or the Flyout object itself. + /// + /// + flyout: { + get: function () { + // Resolve it to the flyout + var flyout = this._flyout; + if (typeof flyout === "string") { + flyout = _Global.document.getElementById(flyout); + } + // If it doesn't have a .element, then we need to getControl on it + if (flyout && !flyout.element) { + flyout = flyout.winControl; + } + + return flyout; + }, + set: function (value) { + + // Need to update aria-owns with the new ID. + var id = value; + if (id && typeof id !== "string") { + // Our controls have .element properties + if (id.element) { + id = id.element; + } + // Hope it's a DOM element, get ID from DOM element + if (id) { + if (id.id) { + id = id.id; + } else { + // No id, have to fake one + id.id = _ElementUtilities._uniqueID(id); + id = id.id; + } + } + } + if (typeof id === "string") { + this._element.setAttribute("aria-owns", id); + } + + if (this._flyout !== value) { + MenuCommand._deactivateFlyoutCommand(this); + } + + // Remember it + this._flyout = value; + } + }, + + /// + /// Gets or sets the selected state of a toggle button. This property is true if the toggle button is selected; otherwise, it's false. + /// + /// + selected: { + get: function () { + // Ensure it's a boolean because we're using the DOM element to keep in-sync + return this._element.getAttribute("aria-checked") === "true"; + }, + set: function (value) { + this._element.setAttribute("aria-checked", !!value); + } + }, + + /// + element: { + get: function () { + return this._element; + } + }, + + /// + /// Gets or sets a value that indicates whether the MenuCommand is disabled. This value is true if the MenuCommand is disabled; otherwise, false. + /// + /// + disabled: { + get: function () { + // Ensure it's a boolean because we're using the DOM element to keep in-sync + return !!this._element.disabled; + }, + set: function (value) { + value = !!value; + if (value && this.type === _Constants.typeFlyout) { + MenuCommand._deactivateFlyoutCommand(this); + } + this._element.disabled = value; + } + }, + + /// + hidden: { + get: function () { + // Ensure it's a boolean because we're using the DOM element to keep in-sync + return this._element.style.visibility === "hidden"; + }, + set: function (value) { + var menuControl = _Overlay._Overlay._getParentControlUsingClassName(this._element, _Constants.menuClass); + if (menuControl && !menuControl.hidden) { + throw new _ErrorFromName("WinJS.UI.MenuCommand.CannotChangeHiddenProperty", _Resources._formatString(_Overlay._Overlay.commonstrings.cannotChangeHiddenProperty, "Menu")); + } + + var style = this._element.style; + if (value) { + if (this.type === _Constants.typeFlyout) { + MenuCommand._deactivateFlyoutCommand(this); + } + style.visibility = "hidden"; + style.display = "none"; + } else { + style.visibility = ""; + style.display = "block"; + } + } + }, + + /// + /// Gets or sets the extra CSS class that is applied to the host DOM element. + /// + /// + extraClass: { + get: function () { + return this._extraClass; + }, + set: function (value) { + if (this._extraClass) { + _ElementUtilities.removeClass(this._element, this._extraClass); + } + this._extraClass = value; + _ElementUtilities.addClass(this._element, this._extraClass); + } + }, + + + dispose: function () { + /// + /// + /// Disposes this control. + /// + /// + /// + if (this._disposed) { + return; + } + this._disposed = true; + }, + + addEventListener: function (type, listener, useCapture) { + /// + /// + /// Registers an event handler for the specified event. + /// + /// The name of the event to register. + /// The function that handles the event. + /// + /// Set to true to register the event handler for the capturing phase; otherwise, set to false to register the event handler for the bubbling phase. + /// + /// + /// + return this._element.addEventListener(type, listener, useCapture); + }, + + removeEventListener: function (type, listener, useCapture) { + /// + /// + /// Removes the specified event handler that the addEventListener method registered. + /// + /// The name of the event to remove. + /// The event handler function to remove. + /// + /// Set to true to remove the capturing phase event handler; set to false to remove the bubbling phase event handler. + /// + /// + /// + return this._element.removeEventListener(type, listener, useCapture); + }, + + // Private properties + _createSeparator: function MenuCommand_createSeparator() { + // Make sure there's an input element + if (!this._element) { + this._element = _Global.document.createElement("hr"); + } else { + // Verify the input was an hr + if (this._element.tagName !== "HR") { + throw new _ErrorFromName("WinJS.UI.MenuCommand.BadHrElement", strings.badHrElement); + } + } + }, + + _createButton: function MenuCommand_createButton() { + // Make sure there's an element + if (!this._element) { + this._element = _Global.document.createElement("button"); + } else { + // Verify the input was a button + if (this._element.tagName !== "BUTTON") { + throw new _ErrorFromName("WinJS.UI.MenuCommand.BadButtonElement", strings.badButtonElement); + } + } + + // Create our inner HTML. We will set aria values on the button itself further down in the constructor. + this._element.innerHTML = + '
' + + '' + + '' + + '' + + '
'; + this._element.type = "button"; + + // The purpose of menuCommandLiner is to lay out the MenuCommand's children in a flexbox. Ideally, this flexbox would + // be on MenuCommand.element. However, firefox lays out buttons with display:flex differently. + // Firefox bug 1014285 (Button with display:inline-flex doesn't layout properly) + // https://bugzilla.mozilla.org/show_bug.cgi?id=1014285 + this._menuCommandLiner = this._element.firstElementChild; + this._toggleSpan = this._menuCommandLiner.firstElementChild; + this._labelSpan = this._toggleSpan.nextElementSibling; + this._flyoutSpan = this._labelSpan.nextElementSibling; + + }, + _sendEvent: function MenuCommand_sendEvent(eventName, detail) { + if (!this._disposed) { + var event = _Global.document.createEvent("CustomEvent"); + event.initCustomEvent(eventName, true, true, (detail || {})); + this._element.dispatchEvent(event); + } + }, + + _invoke: function MenuCommand_invoke(event) { + if (!this.hidden && !this.disabled && !this._disposed) { + if (this._type === _Constants.typeToggle) { + this.selected = !this.selected; + } else if (this._type === _Constants.typeFlyout) { + MenuCommand._activateFlyoutCommand(this); + } + + if (event && event.type === "click" && this.onclick) { + this.onclick(event); + } + + // Bubble private 'invoked' event to Menu + this._sendEvent(_Constants._menuCommandInvokedEvent, { command: this }); + } + }, + + _handleClick: function MenuCommand_handleClick(event) { + this._invoke(event); + }, + + _handleKeyDown: function MenuCommand_handleKeyDown(event) { + var Key = _ElementUtilities.Key, + rtl = _Global.getComputedStyle(this.element).direction === "rtl", + rightKey = rtl ? Key.leftArrow : Key.rightArrow; + + if (event.keyCode === rightKey && this.type === _Constants.typeFlyout) { + this._invoke(event); + + // Prevent the page from scrolling + event.preventDefault(); + } + }, + }, { + // Statics + _activateFlyoutCommand: function MenuCommand_activateFlyoutCommand(menuCommand) { + // Activates the associated Flyout command and returns a promise once complete. + // A command is considered to be activated once the proper CSS class has been applied and its associated flyout has finished showing. + return new Promise(function (c, e) { + menuCommand = menuCommand.winControl || menuCommand; + var subFlyout = menuCommand.flyout; + // Flyout may not have processAll'd, so this may be a DOM object + if (subFlyout && subFlyout.hidden && subFlyout.show) { + _ElementUtilities.addClass(menuCommand.element, _Constants.menuCommandFlyoutActivatedClass); + + // Remove activation class from the command if the flyout is ever hidden. + subFlyout.addEventListener("beforehide", function beforeHide() { + subFlyout.removeEventListener("beforehide", beforeHide, false); + _ElementUtilities.removeClass(menuCommand.element, _Constants.menuCommandFlyoutActivatedClass); + }, false); + + subFlyout.addEventListener("aftershow", function afterShow() { + subFlyout.removeEventListener("aftershow", afterShow, false); + // We are considered activated once we start showing the flyout. + c(); + }, false); + + subFlyout.show(menuCommand, "_cascade"); + } else { + // Could not change command to activated state. + e(); + } + }); + }, + + _deactivateFlyoutCommand: function MenuCommand_deactivateFlyoutCommand(menuCommand) { + // Deactivates the associated Flyout command and returns a promise once complete. + // A command is considered to be deactivated once the proper CSS class has been applied and its associated flyout has finished hiding. + return new Promise(function (c) { + menuCommand = menuCommand.winControl || menuCommand; + _ElementUtilities.removeClass(menuCommand.element, _Constants.menuCommandFlyoutActivatedClass); + + var subFlyout = menuCommand.flyout; + // Flyout may not have processAll'd, so this may be a DOM object + if (subFlyout && !subFlyout.hidden && subFlyout.hide) { + + subFlyout.addEventListener("afterhide", function afterHide() { + subFlyout.removeEventListener("afterhide", afterHide, false); + c(); + }, false); + + subFlyout.hide(); + } else { + // subFlyout does not need to be hidden. + c(); + } + }); + }, + }); + return MenuCommand; + }) + }); + +}); + + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +define('WinJS/Controls/CommandingSurface/_MenuCommand',["require", "exports", "../Menu/_Command"], function (require, exports, _MenuCommandBase) { + var _MenuCommand = (function (_super) { + __extends(_MenuCommand, _super); + function _MenuCommand(element, options) { + if (options && options.beforeInvoke) { + this._beforeInvoke = options.beforeInvoke; + } + _super.call(this, element, options); + } + _MenuCommand.prototype._invoke = function (event) { + this._beforeInvoke && this._beforeInvoke(event); + _super.prototype._invoke.call(this, event); + }; + return _MenuCommand; + })(_MenuCommandBase.MenuCommand); + exports._MenuCommand = _MenuCommand; +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// +define('WinJS/Utilities/_OpenCloseMachine',["require", "exports", '../Core/_Global', '../Promise', '../_Signal'], function (require, exports, _Global, Promise, _Signal) { + "use strict"; + // This module provides a state machine which is designed to be used by controls which need to + // open, close, and fire related events (e.g. beforeopen, afterclose). The state machine handles + // many edge cases. For example, what happens if: + // - open is called when we're already opened? + // - close is called while we're in the middle of opening? + // - dispose is called while we're in the middle of firing beforeopen? + // The state machine takes care of all of these edge cases so that the control doesn't have to. + // The control is responible for knowing how to play its open/close animations and update its DOM. + // The state machine is responsible for ensuring that these things happen at the appropriate times. + // This module is broken up into 3 major pieces: + // - OpenCloseMachine: Controls should instantiate one of these. The machine keeps track of the + // current state and has methods for forwarding calls to the current state. + // - IOpenCloseControl: Controls must provide an object which implements this interface. The + // interface gives the machine hooks for invoking the control's open and close animations. + // - States: The various states (e.g. Closed, Opened, Opening) that the machine can be in. Each + // implements IOpenCloseState. + // Example usage: + // class MyControl { + // element: HTMLElement; + // private _machine: OpenCloseMachine; + // + // constructor(element?: HTMLElement, options: any = {}) { + // this.element = element || document.createElement("div"); + // + // // Create the machine. + // this._machine = new OpenCloseMachine({ + // eventElement: this.element, + // onOpen: (): Promise => { + // // Do the work to render the contol in its opened state with an animation. + // // Return the animation promise. + // }, + // onClose: (): Promise => { + // // Do the work to render the contol in its closed state with an animation. + // // Return the animation promise. + // }, + // onUpdateDom() { + // // Do the work to render the internal state of the control to the DOM. If a + // // control restricts all its DOM modifications to onUpdateDom, the state machine + // // can guarantee that the control won't modify its DOM while it is animating. + // }, + // onUpdateDomWithIsOpened: (isOpened: boolean ) => { + // // Do the same work as onUpdateDom but ensure that the DOM is rendered with either + // // the opened or closed visual as dictacted by isOpened. The control should have some + // // internal state to track whether it is currently opened or closed. Treat this as a + // // cue to mutate that internal state to reflect the value of isOpened. + // }, + // }); + // + // // Initialize the control. During this time, the machine will not ask the control to + // // play any animations or update its DOM. + // this.opened = true; + // _Control.setOptions(this, options); + // + // // Tell the machine the control is initialized. After this, the machine will start asking + // // the control to play animations and update its DOM as appropriate. + // this._machine.exitInit(); + // } + // + // get opened() { + // return this._machine.opened; + // } + // set opened(value: boolean) { + // this._machine.opened = value; + // } + // open() { + // this._machine.open(); + // } + // close() { + // this._machine.close(); + // } + // forceLayout() { + // this._machine.updateDom(); + // } + // dispose() { + // this._machine.dispose(); + // } + // } + var EventNames = { + beforeOpen: "beforeopen", + afterOpen: "afteropen", + beforeClose: "beforeclose", + afterClose: "afterclose", + // Private events + // Indicates that the OpenCloseMachine has settled either into the Opened state + // or Closed state. This is more comprehensive than the "afteropen" and "afterclose" + // events because it fires even if the machine has reached the state due to: + // - Exiting the Init state + // - The beforeopen/beforeclose events being canceled + _openCloseStateSettled: "_openCloseStateSettled" + }; + // + // OpenCloseMachine + // + var OpenCloseMachine = (function () { + // + // Methods called by the control + // + // When the machine is created, it sits in the Init state. When in the Init state, calls to + // updateDom will be postponed until the machine exits the Init state. Consequently, while in + // this state, the control can feel free to call updateDom as many times as it wants without + // worrying about it being expensive due to updating the DOM many times. The control should call + // *exitInit* to move the machine out of the Init state. + function OpenCloseMachine(args) { + this._control = args; + this._initializedSignal = new _Signal(); + this._disposed = false; + this._setState(States.Init); + } + // Moves the machine out of the Init state and into the Opened or Closed state depending on whether + // open or close was called more recently. + OpenCloseMachine.prototype.exitInit = function () { + this._initializedSignal.complete(); + }; + // These method calls are forwarded to the current state. + OpenCloseMachine.prototype.updateDom = function () { + this._state.updateDom(); + }; + OpenCloseMachine.prototype.open = function () { + this._state.open(); + }; + OpenCloseMachine.prototype.close = function () { + this._state.close(); + }; + Object.defineProperty(OpenCloseMachine.prototype, "opened", { + get: function () { + return this._state.opened; + }, + set: function (value) { + if (value) { + this.open(); + } + else { + this.close(); + } + }, + enumerable: true, + configurable: true + }); + // Puts the machine into the Disposed state. + OpenCloseMachine.prototype.dispose = function () { + this._setState(States.Disposed); + this._disposed = true; + this._control = null; + }; + // + // Methods called by states + // + OpenCloseMachine.prototype._setState = function (NewState, arg0) { + if (!this._disposed) { + this._state && this._state.exit(); + this._state = new NewState(); + this._state.machine = this; + this._state.enter(arg0); + } + }; + // Triggers arbitrary app code + OpenCloseMachine.prototype._fireEvent = function (eventName, options) { + options = options || {}; + var detail = options.detail || null; + var cancelable = !!options.cancelable; + var eventObject = _Global.document.createEvent("CustomEvent"); + eventObject.initCustomEvent(eventName, true, cancelable, detail); + return this._control.eventElement.dispatchEvent(eventObject); + }; + // Triggers arbitrary app code + OpenCloseMachine.prototype._fireBeforeOpen = function () { + return this._fireEvent(EventNames.beforeOpen, { + cancelable: true + }); + }; + // Triggers arbitrary app code + OpenCloseMachine.prototype._fireBeforeClose = function () { + return this._fireEvent(EventNames.beforeClose, { + cancelable: true + }); + }; + return OpenCloseMachine; + })(); + exports.OpenCloseMachine = OpenCloseMachine; + // + // States (each implements IOpenCloseState) + // + // WinJS animation promises always complete successfully. This + // helper allows an animation promise to complete in the canceled state + // so that the success handler can be skipped when the animation is + // interrupted. + function cancelablePromise(animationPromise) { + return Promise._cancelBlocker(animationPromise, function () { + animationPromise.cancel(); + }); + } + // Noop function, used in the various states to indicate that they don't support a given + // message. Named with the somewhat cute name '_' because it reads really well in the states. + function _() { + } + // Implementing the control as a state machine helps us correctly handle: + // - re-entrancy while firing events + // - calls into the control during asynchronous operations (e.g. animations) + // + // Many of the states do their "enter" work within a promise chain. The idea is that if + // the state is interrupted and exits, the rest of its work can be skipped by canceling + // the promise chain. + // An interesting detail is that anytime the state may trigger app code (e.g. due to + // firing an event), the current promise must end and a new promise must be chained off of it. + // This is necessary because the app code may interact with the control and cause it to + // change states. If we didn't create a new promise, then the very next line of code that runs + // after triggering app code may not be valid because the state may have exited. Starting a + // new promise after each triggering of app code prevents us from having to worry about this + // problem. In this configuration, when a promise's success handler runs, it guarantees that + // the state hasn't exited. + // For similar reasons, each of the promise chains created in "enter" starts off with a _Signal + // which is completed at the end of the "enter" function (this boilerplate is abstracted away by + // the "interruptible" function). The reason is that we don't want any of the code in "enter" + // to run until the promise chain has been stored in a variable. If we didn't do this (e.g. instead, + // started the promise chain with Promise.wrap()), then the "enter" code could trigger the "exit" + // function (via app code) before the promise chain had been stored in a variable. Under these + // circumstances, the promise chain would be uncancelable and so the "enter" work would be + // unskippable. This wouldn't be good when we needed the state to exit early. + // These two functions manage interruptible work promises (one creates them the other cancels + // them). They communicate with each other thru the _interruptibleWorkPromises property which + // "interruptible" creates on your object. + function interruptible(object, workFn) { + object["_interruptibleWorkPromises"] = object["_interruptibleWorkPromises"] || []; + var workStoredSignal = new _Signal(); + object["_interruptibleWorkPromises"].push(workFn(workStoredSignal.promise)); + workStoredSignal.complete(); + } + function cancelInterruptibles() { + (this["_interruptibleWorkPromises"] || []).forEach(function (workPromise) { + workPromise.cancel(); + }); + } + // Transitions: + // When created, the state machine will take one of the following initialization + // transitions depending on how the machines's APIs have been used by the time + // exitInit() is called on it: + // Init -> Closed + // Init -> Opened + // Following that, the life of the machine will be dominated by the following + // sequences of transitions. In geneneral, these sequences are uninterruptible. + // Closed -> BeforeOpen -> Closed (when preventDefault is called on beforeopen event) + // Closed -> BeforeOpen -> Opening -> Opened + // Opened -> BeforeClose -> Opened (when preventDefault is called on beforeclose event) + // Opened -> BeforeClose -> Closing -> Closed + // However, any state can be interrupted to go to the Disposed state: + // * -> Disposed + var States; + (function (States) { + function updateDomImpl() { + this.machine._control.onUpdateDom(); + } + // Initial state. Gives the control the opportunity to initialize itself without + // triggering any animations or DOM modifications. When done, the control should + // call *exitInit* to move the machine to the next state. + var Init = (function () { + function Init() { + this.name = "Init"; + this.exit = cancelInterruptibles; + this.updateDom = _; // Postponed until immediately before we switch to another state + } + Init.prototype.enter = function () { + var _this = this; + interruptible(this, function (ready) { + return ready.then(function () { + return _this.machine._initializedSignal.promise; + }).then(function () { + _this.machine._control.onUpdateDomWithIsOpened(_this._opened); + _this.machine._setState(_this._opened ? Opened : Closed); + }); + }); + }; + Object.defineProperty(Init.prototype, "opened", { + get: function () { + return this._opened; + }, + enumerable: true, + configurable: true + }); + Init.prototype.open = function () { + this._opened = true; + }; + Init.prototype.close = function () { + this._opened = false; + }; + return Init; + })(); + States.Init = Init; + // A rest state. The control is closed and is waiting for the app to call open. + var Closed = (function () { + function Closed() { + this.name = "Closed"; + this.exit = _; + this.opened = false; + this.close = _; + this.updateDom = updateDomImpl; + } + Closed.prototype.enter = function (args) { + args = args || {}; + if (args.openIsPending) { + this.open(); + } + this.machine._fireEvent(EventNames._openCloseStateSettled); + }; + Closed.prototype.open = function () { + this.machine._setState(BeforeOpen); + }; + return Closed; + })(); + // An event state. The control fires the beforeopen event. + var BeforeOpen = (function () { + function BeforeOpen() { + this.name = "BeforeOpen"; + this.exit = cancelInterruptibles; + this.opened = false; + this.open = _; + this.close = _; + this.updateDom = updateDomImpl; + } + BeforeOpen.prototype.enter = function () { + var _this = this; + interruptible(this, function (ready) { + return ready.then(function () { + return _this.machine._fireBeforeOpen(); // Give opportunity for chain to be canceled when triggering app code + }).then(function (shouldOpen) { + if (shouldOpen) { + _this.machine._setState(Opening); + } + else { + _this.machine._setState(Closed); + } + }); + }); + }; + return BeforeOpen; + })(); + // An animation/event state. The control plays its open animation and fires afteropen. + var Opening = (function () { + function Opening() { + this.name = "Opening"; + this.exit = cancelInterruptibles; + this.updateDom = _; // Postponed until immediately before we switch to another state + } + Opening.prototype.enter = function () { + var _this = this; + interruptible(this, function (ready) { + return ready.then(function () { + _this._closeIsPending = false; + return cancelablePromise(_this.machine._control.onOpen()); + }).then(function () { + _this.machine._fireEvent(EventNames.afterOpen); // Give opportunity for chain to be canceled when triggering app code + }).then(function () { + _this.machine._control.onUpdateDom(); + _this.machine._setState(Opened, { closeIsPending: _this._closeIsPending }); + }); + }); + }; + Object.defineProperty(Opening.prototype, "opened", { + get: function () { + return !this._closeIsPending; + }, + enumerable: true, + configurable: true + }); + Opening.prototype.open = function () { + this._closeIsPending = false; + }; + Opening.prototype.close = function () { + this._closeIsPending = true; + }; + return Opening; + })(); + // A rest state. The control is opened and is waiting for the app to call close. + var Opened = (function () { + function Opened() { + this.name = "Opened"; + this.exit = _; + this.opened = true; + this.open = _; + this.updateDom = updateDomImpl; + } + Opened.prototype.enter = function (args) { + args = args || {}; + if (args.closeIsPending) { + this.close(); + } + this.machine._fireEvent(EventNames._openCloseStateSettled); + }; + Opened.prototype.close = function () { + this.machine._setState(BeforeClose); + }; + return Opened; + })(); + // An event state. The control fires the beforeclose event. + var BeforeClose = (function () { + function BeforeClose() { + this.name = "BeforeClose"; + this.exit = cancelInterruptibles; + this.opened = true; + this.open = _; + this.close = _; + this.updateDom = updateDomImpl; + } + BeforeClose.prototype.enter = function () { + var _this = this; + interruptible(this, function (ready) { + return ready.then(function () { + return _this.machine._fireBeforeClose(); // Give opportunity for chain to be canceled when triggering app code + }).then(function (shouldClose) { + if (shouldClose) { + _this.machine._setState(Closing); + } + else { + _this.machine._setState(Opened); + } + }); + }); + }; + return BeforeClose; + })(); + // An animation/event state. The control plays the close animation and fires the afterclose event. + var Closing = (function () { + function Closing() { + this.name = "Closing"; + this.exit = cancelInterruptibles; + this.updateDom = _; // Postponed until immediately before we switch to another state + } + Closing.prototype.enter = function () { + var _this = this; + interruptible(this, function (ready) { + return ready.then(function () { + _this._openIsPending = false; + return cancelablePromise(_this.machine._control.onClose()); + }).then(function () { + _this.machine._fireEvent(EventNames.afterClose); // Give opportunity for chain to be canceled when triggering app code + }).then(function () { + _this.machine._control.onUpdateDom(); + _this.machine._setState(Closed, { openIsPending: _this._openIsPending }); + }); + }); + }; + Object.defineProperty(Closing.prototype, "opened", { + get: function () { + return this._openIsPending; + }, + enumerable: true, + configurable: true + }); + Closing.prototype.open = function () { + this._openIsPending = true; + }; + Closing.prototype.close = function () { + this._openIsPending = false; + }; + return Closing; + })(); + var Disposed = (function () { + function Disposed() { + this.name = "Disposed"; + this.enter = _; + this.exit = _; + this.opened = false; + this.open = _; + this.close = _; + this.updateDom = _; + } + return Disposed; + })(); + States.Disposed = Disposed; + })(States || (States = {})); +}); + + +define('require-style!less/styles-commandingsurface',[],function(){}); + +define('require-style!less/colors-commandingsurface',[],function(){}); +define('WinJS/Controls/CommandingSurface/_CommandingSurface',["require", "exports", "../../Animations", "../../Core/_Base", "../../Core/_BaseUtils", "../../BindingList", "../../ControlProcessor", "../CommandingSurface/_Constants", "../AppBar/_Command", "../CommandingSurface/_MenuCommand", "../../Utilities/_Control", "../../Utilities/_Dispose", "../../Utilities/_ElementUtilities", "../../Core/_ErrorFromName", '../../Core/_Events', "../../Controls/Flyout", "../../Core/_Global", "../../Utilities/_Hoverable", "../../Utilities/_KeyboardBehavior", '../../Core/_Log', '../../Promise', "../../Core/_Resources", "../../Scheduler", '../../Utilities/_OpenCloseMachine', '../../_Signal', "../../Core/_WriteProfilerMark"], function (require, exports, Animations, _Base, _BaseUtils, BindingList, ControlProcessor, _Constants, _Command, _CommandingSurfaceMenuCommand, _Control, _Dispose, _ElementUtilities, _ErrorFromName, _Events, _Flyout, _Global, _Hoverable, _KeyboardBehavior, _Log, Promise, _Resources, Scheduler, _OpenCloseMachine, _Signal, _WriteProfilerMark) { + require(["require-style!less/styles-commandingsurface"]); + require(["require-style!less/colors-commandingsurface"]); + "use strict"; + var strings = { + get overflowButtonAriaLabel() { + return _Resources._getWinJSString("ui/commandingSurfaceOverflowButtonAriaLabel").value; + }, + get badData() { + return "Invalid argument: The data property must an instance of a WinJS.Binding.List"; + }, + get mustContainCommands() { + return "The commandingSurface can only contain WinJS.UI.Command or WinJS.UI.AppBarCommand controls"; + }, + get duplicateConstruction() { + return "Invalid argument: Controls may only be instantiated one time for each DOM element"; + } + }; + var CommandLayoutPipeline = { + newDataStage: 3, + measuringStage: 2, + layoutStage: 1, + idle: 0, + }; + var OverflowDirection = { + /// The _CommandingSurface expands towards the bottom of the screen when opened and the overflow area renders below the actionarea. + bottom: "bottom", + /// The _CommandingSurface expands towards the top of the screen when opened and the overflow area renders above the actionarea. + top: "top", + }; + var overflowDirectionClassMap = {}; + overflowDirectionClassMap[OverflowDirection.top] = _Constants.ClassNames.overflowTopClass; + overflowDirectionClassMap[OverflowDirection.bottom] = _Constants.ClassNames.overflowBottomClass; + var ClosedDisplayMode = { + /// When the _CommandingSurface is closed, the actionarea is not visible and doesn't take up any space. + none: "none", + /// When the _CommandingSurface is closed, the height of the actionarea is reduced to the minimal height required to display only the actionarea overflowbutton. All other content in the actionarea is not displayed. + minimal: "minimal", + /// When the _CommandingSurface is closed, the height of the actionarea is reduced such that button commands are still visible, but their labels are hidden. + compact: "compact", + /// When the _CommandingSurface is closed, the height of the actionarea is always sized to content and does not change between opened and closed states. + full: "full", + }; + var closedDisplayModeClassMap = {}; + closedDisplayModeClassMap[ClosedDisplayMode.none] = _Constants.ClassNames.noneClass; + closedDisplayModeClassMap[ClosedDisplayMode.minimal] = _Constants.ClassNames.minimalClass; + closedDisplayModeClassMap[ClosedDisplayMode.compact] = _Constants.ClassNames.compactClass; + closedDisplayModeClassMap[ClosedDisplayMode.full] = _Constants.ClassNames.fullClass; + // Versions of add/removeClass that are no ops when called with falsy class names. + function addClass(element, className) { + className && _ElementUtilities.addClass(element, className); + } + function removeClass(element, className) { + className && _ElementUtilities.removeClass(element, className); + } + function diffElements(lhs, rhs) { + // Subtract array rhs from array lhs. + // Returns a new Array containing the subset of elements in lhs that are not also in rhs. + return lhs.filter(function (commandElement) { + return rhs.indexOf(commandElement) < 0; + }); + } + /// Represents an apaptive surface for displaying commands. + var _CommandingSurface = (function () { + function _CommandingSurface(element, options) { + /// Creates a new CommandingSurface control. + /// @param element: The DOM element that will host the control. + /// @param options: The set of properties and values to apply to the new CommandingSurface control. + /// @return: The new CommandingSurface control. + var _this = this; + if (options === void 0) { options = {}; } + this._hoverable = _Hoverable.isHoverable; /* force dependency on hoverable module */ + this._dataChangedEvents = ["itemchanged", "iteminserted", "itemmoved", "itemremoved", "reload"]; + // State private to _updateDomImpl_renderDisplayMode. No other method should make use of it. + // + // Nothing has been rendered yet so these are all initialized to undefined. Because + // they are undefined, the first time _updateDomImpl is called, they will all be + // rendered. + this._updateDomImpl_renderedState = { + closedDisplayMode: undefined, + isOpenedMode: undefined, + overflowDirection: undefined, + overflowAlignmentOffset: undefined, + }; + this._writeProfilerMark("constructor,StartTM"); + // Check to make sure we weren't duplicated + if (element && element["winControl"]) { + throw new _ErrorFromName("WinJS.UI._CommandingSurface.DuplicateConstruction", strings.duplicateConstruction); + } + this._initializeDom(element || _Global.document.createElement("div")); + this._machine = options.openCloseMachine || new _OpenCloseMachine.OpenCloseMachine({ + eventElement: this._dom.root, + onOpen: function () { + _this.synchronousOpen(); + return Promise.wrap(); + }, + onClose: function () { + _this.synchronousClose(); + return Promise.wrap(); + }, + onUpdateDom: function () { + _this.updateDomImpl(); + }, + onUpdateDomWithIsOpened: function (isOpened) { + if (isOpened) { + _this.synchronousOpen(); + } + else { + _this.synchronousClose(); + } + } + }); + // Initialize private state. + this._disposed = false; + this._primaryCommands = []; + this._secondaryCommands = []; + this._refreshBound = this._refresh.bind(this); + this._resizeHandlerBound = this._resizeHandler.bind(this); + this._winKeyboard = new _KeyboardBehavior._WinKeyboard(this._dom.root); + this._refreshPending = false; + this._rtl = false; + this._initializedSignal = new _Signal(); + this._nextLayoutStage = CommandLayoutPipeline.idle; + this._isOpenedMode = _Constants.defaultOpened; + this._menuCommandProjections = []; + // Initialize public properties. + this.overflowDirection = _Constants.defaultOverflowDirection; + this.closedDisplayMode = _Constants.defaultClosedDisplayMode; + this.opened = this._isOpenedMode; + if (!options.data) { + // Shallow copy object so we can modify it. + options = _BaseUtils._shallowCopy(options); + // Set default data + options.data = options.data || this._getDataFromDOMElements(); + } + _Control.setOptions(this, options); + // Event handlers + _ElementUtilities._resizeNotifier.subscribe(this._dom.root, this._resizeHandlerBound); + this._dom.root.addEventListener('keydown', this._keyDownHandler.bind(this)); + // Exit the Init state. + _ElementUtilities._inDom(this._dom.root).then(function () { + _this._rtl = _Global.getComputedStyle(_this._dom.root).direction === 'rtl'; + if (!options.openCloseMachine) { + // We should only call exitInit on the machine when we own the machine. + _this._machine.exitInit(); + } + _this._initializedSignal.complete(); + _this._writeProfilerMark("constructor,StopTM"); + }); + } + Object.defineProperty(_CommandingSurface.prototype, "element", { + /// Gets the DOM element that hosts the CommandingSurface. + get: function () { + return this._dom.root; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(_CommandingSurface.prototype, "data", { + /// Gets or sets the Binding List of WinJS.UI.Command for the CommandingSurface. + get: function () { + return this._data; + }, + set: function (value) { + this._writeProfilerMark("set_data,info"); + if (value !== this.data) { + if (!(value instanceof BindingList.List)) { + throw new _ErrorFromName("WinJS.UI._CommandingSurface.BadData", strings.badData); + } + if (this._data) { + this._removeDataListeners(); + } + this._data = value; + this._addDataListeners(); + this._dataUpdated(); + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(_CommandingSurface.prototype, "closedDisplayMode", { + /// Gets or sets the closedDisplayMode for the CommandingSurface. Values are "none", "minimal", "compact", and "full". + get: function () { + return this._closedDisplayMode; + }, + set: function (value) { + this._writeProfilerMark("set_closedDisplayMode,info"); + var isChangingState = (value !== this._closedDisplayMode); + if (ClosedDisplayMode[value] && isChangingState) { + this._closedDisplayMode = value; + this._machine.updateDom(); + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(_CommandingSurface.prototype, "overflowDirection", { + /// Gets or sets which direction the commandingSurface overflows when opened. Values are "top" and "bottom" for. + get: function () { + return this._overflowDirection; + }, + set: function (value) { + var isChangingState = (value !== this._overflowDirection); + if (OverflowDirection[value] && isChangingState) { + this._overflowDirection = value; + this._machine.updateDom(); + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(_CommandingSurface.prototype, "opened", { + /// Gets or sets whether the _CommandingSurface is currently opened. + get: function () { + return this._machine.opened; + }, + set: function (value) { + this._machine.opened = value; + }, + enumerable: true, + configurable: true + }); + _CommandingSurface.prototype.open = function () { + /// Opens the _CommandingSurface's actionarea and overflowarea + this._machine.open(); + }; + _CommandingSurface.prototype.close = function () { + /// Closes the _CommandingSurface's actionarea and overflowarea + this._machine.close(); + }; + _CommandingSurface.prototype.dispose = function () { + /// Disposes this CommandingSurface. + if (this._disposed) { + return; + } + this._disposed = true; + this._machine.dispose(); + _ElementUtilities._resizeNotifier.unsubscribe(this._dom.root, this._resizeHandlerBound); + if (this._contentFlyout) { + this._contentFlyout.dispose(); + this._contentFlyout.element.parentNode.removeChild(this._contentFlyout.element); + } + _Dispose.disposeSubTree(this._dom.root); + }; + _CommandingSurface.prototype.forceLayout = function () { + /// Forces the CommandingSurface to update its layout. Use this function when the window did not change + /// size, but the container of the CommandingSurface changed size. + this._meaurementsDirty(); + this._machine.updateDom(); + }; + _CommandingSurface.prototype.getBoundingRects = function () { + return { + commandingSurface: this._dom.root.getBoundingClientRect(), + overflowArea: this._dom.overflowArea.getBoundingClientRect(), + }; + }; + _CommandingSurface.prototype.getCommandById = function (id) { + if (this._data) { + for (var i = 0, len = this._data.length; i < len; i++) { + var command = this._data.getAt(i); + if (command.id === id) { + return command; + } + } + } + return null; + }; + _CommandingSurface.prototype.showOnlyCommands = function (commands) { + if (this._data) { + for (var i = 0, len = this._data.length; i < len; i++) { + this._data.getAt(i).hidden = true; + } + for (var i = 0, len = commands.length; i < len; i++) { + // The array passed to showOnlyCommands can contain either command ids, or the commands themselves. + var command = (typeof commands[i] === "string" ? this.getCommandById(commands[i]) : commands[i]); + if (command) { + command.hidden = false; + } + } + } + }; + _CommandingSurface.prototype.deferredDomUpate = function () { + // Notify the machine that an update has been requested. + this._machine.updateDom(); + }; + _CommandingSurface.prototype.createOpenAnimation = function (closedHeight) { + // createOpenAnimation should only be called when the commanding surface is in a closed state. The control using the commanding surface is expected + // to call createOpenAnimation() before it opens the surface, then open the commanding surface, then call .execute() to start the animation. + // This function is overridden by our unit tests. + if (_Log.log) { + this._updateDomImpl_renderedState.isOpenedMode && _Log.log("The CommandingSurface should only attempt to create an open animation when it's not already opened"); + } + var that = this; + return { + execute: function () { + var boundingRects = that.getBoundingRects(); + // The overflowAreaContainer has no size by default. Measure the overflowArea's size and apply it to the overflowAreaContainer before animating + that._dom.overflowAreaContainer.style.width = boundingRects.overflowArea.width + "px"; + that._dom.overflowAreaContainer.style.height = boundingRects.overflowArea.height + "px"; + return Animations._commandingSurfaceOpenAnimation({ + actionAreaClipper: that._dom.actionAreaContainer, + actionArea: that._dom.actionArea, + overflowAreaClipper: that._dom.overflowAreaContainer, + overflowArea: that._dom.overflowArea, + oldHeight: closedHeight, + newHeight: boundingRects.commandingSurface.height, + overflowAreaHeight: boundingRects.overflowArea.height, + menuPositionedAbove: (that.overflowDirection === OverflowDirection.top), + }).then(function () { + that._clearAnimation(); + }); + } + }; + }; + _CommandingSurface.prototype.createCloseAnimation = function (closedHeight) { + // createCloseAnimation should only be called when the commanding surface is in an opened state. The control using the commanding surface is expected + // to call createCloseAnimation() before it closes the surface, then call execute() to let the animation run. Once the animation finishes, the control + // should close the commanding surface. + // This function is overridden by our unit tests. + if (_Log.log) { + !this._updateDomImpl_renderedState.isOpenedMode && _Log.log("The CommandingSurface should only attempt to create an closed animation when it's not already closed"); + } + var openedHeight = this.getBoundingRects().commandingSurface.height, overflowAreaOpenedHeight = this._dom.overflowArea.offsetHeight, oldOverflowTop = this._dom.overflowArea.offsetTop, that = this; + return { + execute: function () { + _ElementUtilities.addClass(that.element, _Constants.ClassNames.closingClass); + return Animations._commandingSurfaceCloseAnimation({ + actionAreaClipper: that._dom.actionAreaContainer, + actionArea: that._dom.actionArea, + overflowAreaClipper: that._dom.overflowAreaContainer, + overflowArea: that._dom.overflowArea, + oldHeight: openedHeight, + newHeight: closedHeight, + overflowAreaHeight: overflowAreaOpenedHeight, + menuPositionedAbove: (that.overflowDirection === OverflowDirection.top), + }).then(function () { + _ElementUtilities.removeClass(that.element, _Constants.ClassNames.closingClass); + that._clearAnimation(); + }); + } + }; + }; + Object.defineProperty(_CommandingSurface.prototype, "initialized", { + get: function () { + return this._initializedSignal.promise; + }, + enumerable: true, + configurable: true + }); + _CommandingSurface.prototype._writeProfilerMark = function (text) { + _WriteProfilerMark("WinJS.UI._CommandingSurface:" + this._id + ":" + text); + }; + _CommandingSurface.prototype._initializeDom = function (root) { + var _this = this; + this._writeProfilerMark("_intializeDom,info"); + // Attaching JS control to DOM element + root["winControl"] = this; + this._id = root.id || _ElementUtilities._uniqueID(root); + if (!root.hasAttribute("tabIndex")) { + root.tabIndex = -1; + } + _ElementUtilities.addClass(root, _Constants.ClassNames.controlCssClass); + _ElementUtilities.addClass(root, _Constants.ClassNames.disposableCssClass); + var actionArea = _Global.document.createElement("div"); + _ElementUtilities.addClass(actionArea, _Constants.ClassNames.actionAreaCssClass); + _ElementUtilities._reparentChildren(root, actionArea); + var actionAreaContainer = _Global.document.createElement("div"); + _ElementUtilities.addClass(actionAreaContainer, _Constants.ClassNames.actionAreaContainerCssClass); + actionAreaContainer.appendChild(actionArea); + root.appendChild(actionAreaContainer); + var spacer = _Global.document.createElement("div"); + _ElementUtilities.addClass(spacer, _Constants.ClassNames.spacerCssClass); + actionArea.appendChild(spacer); + var overflowButton = _Global.document.createElement("button"); + overflowButton.tabIndex = 0; + overflowButton.innerHTML = ""; + _ElementUtilities.addClass(overflowButton, _Constants.ClassNames.overflowButtonCssClass); + actionArea.appendChild(overflowButton); + overflowButton.addEventListener("click", function () { + _this.opened = !_this.opened; + }); + var overflowArea = _Global.document.createElement("div"); + _ElementUtilities.addClass(overflowArea, _Constants.ClassNames.overflowAreaCssClass); + _ElementUtilities.addClass(overflowArea, _Constants.ClassNames.menuCssClass); + var overflowAreaContainer = _Global.document.createElement("div"); + _ElementUtilities.addClass(overflowAreaContainer, _Constants.ClassNames.overflowAreaContainerCssClass); + overflowAreaContainer.appendChild(overflowArea); + root.appendChild(overflowAreaContainer); + this._dom = { + root: root, + actionArea: actionArea, + actionAreaContainer: actionAreaContainer, + spacer: spacer, + overflowButton: overflowButton, + overflowArea: overflowArea, + overflowAreaContainer: overflowAreaContainer + }; + }; + _CommandingSurface.prototype._getFocusableElementsInfo = function () { + var _this = this; + var focusableCommandsInfo = { + elements: [], + focusedIndex: -1 + }; + var elementsInReach = Array.prototype.slice.call(this._dom.actionArea.children); + var elementsInReach = Array.prototype.slice.call(this._dom.actionArea.children); + if (this._dom.overflowArea.style.display !== "none") { + elementsInReach = elementsInReach.concat(Array.prototype.slice.call(this._dom.overflowArea.children)); + } + elementsInReach.forEach(function (element) { + if (_this._isElementFocusable(element)) { + focusableCommandsInfo.elements.push(element); + if (element.contains(_Global.document.activeElement)) { + focusableCommandsInfo.focusedIndex = focusableCommandsInfo.elements.length - 1; + } + } + }); + return focusableCommandsInfo; + }; + _CommandingSurface.prototype._dataUpdated = function () { + var _this = this; + this._primaryCommands = []; + this._secondaryCommands = []; + if (this.data.length > 0) { + this.data.forEach(function (command) { + if (command.section === "secondary") { + _this._secondaryCommands.push(command); + } + else { + _this._primaryCommands.push(command); + } + }); + } + this._dataDirty(); + this._machine.updateDom(); + }; + _CommandingSurface.prototype._refresh = function () { + var _this = this; + if (!this._refreshPending) { + this._refreshPending = true; + // Batch calls to _dataUpdated + Scheduler.schedule(function () { + if (_this._refreshPending && !_this._disposed) { + _this._refreshPending = false; + _this._dataUpdated(); + } + }, Scheduler.Priority.high, null, "WinJS.UI._CommandingSurface._refresh"); + } + }; + _CommandingSurface.prototype._addDataListeners = function () { + var _this = this; + this._dataChangedEvents.forEach(function (eventName) { + _this._data.addEventListener(eventName, _this._refreshBound, false); + }); + }; + _CommandingSurface.prototype._removeDataListeners = function () { + var _this = this; + this._dataChangedEvents.forEach(function (eventName) { + _this._data.removeEventListener(eventName, _this._refreshBound, false); + }); + }; + _CommandingSurface.prototype._isElementFocusable = function (element) { + var focusable = false; + if (element) { + var command = element["winControl"]; + if (command) { + focusable = command.element.style.display !== "none" && command.type !== _Constants.typeSeparator && !command.hidden && !command.disabled && (!command.firstElementFocus || command.firstElementFocus.tabIndex >= 0 || command.lastElementFocus.tabIndex >= 0); + } + else { + // e.g. the overflow button + focusable = element.style.display !== "none" && getComputedStyle(element).visibility !== "hidden" && element.tabIndex >= 0; + } + } + return focusable; + }; + _CommandingSurface.prototype._isCommandInActionArea = function (element) { + // Returns true if the element is a command in the actionarea, false otherwise + return element && element["winControl"] && element.parentElement === this._dom.actionArea; + }; + _CommandingSurface.prototype._getLastElementFocus = function (element) { + if (this._isCommandInActionArea(element)) { + // Only commands in the actionarea support lastElementFocus + return element["winControl"].lastElementFocus; + } + else { + return element; + } + }; + _CommandingSurface.prototype._getFirstElementFocus = function (element) { + if (this._isCommandInActionArea(element)) { + // Only commands in the actionarea support firstElementFocus + return element["winControl"].firstElementFocus; + } + else { + return element; + } + }; + _CommandingSurface.prototype._keyDownHandler = function (ev) { + if (!ev.altKey) { + if (_ElementUtilities._matchesSelector(ev.target, ".win-interactive, .win-interactive *")) { + return; + } + var Key = _ElementUtilities.Key; + var focusableElementsInfo = this._getFocusableElementsInfo(); + var targetCommand; + if (focusableElementsInfo.elements.length) { + switch (ev.keyCode) { + case (this._rtl ? Key.rightArrow : Key.leftArrow): + case Key.upArrow: + var index = Math.max(0, focusableElementsInfo.focusedIndex - 1); + targetCommand = this._getLastElementFocus(focusableElementsInfo.elements[index % focusableElementsInfo.elements.length]); + break; + case (this._rtl ? Key.leftArrow : Key.rightArrow): + case Key.downArrow: + var index = Math.min(focusableElementsInfo.focusedIndex + 1, focusableElementsInfo.elements.length - 1); + targetCommand = this._getFirstElementFocus(focusableElementsInfo.elements[index]); + break; + case Key.home: + var index = 0; + targetCommand = this._getFirstElementFocus(focusableElementsInfo.elements[index]); + break; + case Key.end: + var index = focusableElementsInfo.elements.length - 1; + targetCommand = this._getLastElementFocus(focusableElementsInfo.elements[index]); + break; + } + } + if (targetCommand && targetCommand !== _Global.document.activeElement) { + targetCommand.focus(); + ev.preventDefault(); + } + } + }; + _CommandingSurface.prototype._getDataFromDOMElements = function () { + this._writeProfilerMark("_getDataFromDOMElements,info"); + ControlProcessor.processAll(this._dom.actionArea, true); + var commands = []; + var childrenLength = this._dom.actionArea.children.length; + var child; + for (var i = 0; i < childrenLength; i++) { + child = this._dom.actionArea.children[i]; + if (child["winControl"] && child["winControl"] instanceof _Command.AppBarCommand) { + commands.push(child["winControl"]); + } + else if (child !== this._dom.overflowButton && child !== this._dom.spacer) { + throw new _ErrorFromName("WinJS.UI._CommandingSurface.MustContainCommands", strings.mustContainCommands); + } + } + return new BindingList.List(commands); + }; + _CommandingSurface.prototype._resizeHandler = function () { + if (this._dom.root.offsetWidth) { + var currentActionAreaWidth = _ElementUtilities._getPreciseContentWidth(this._dom.actionArea); + if (this._cachedMeasurements && this._cachedMeasurements.actionAreaContentBoxWidth !== currentActionAreaWidth) { + this._cachedMeasurements.actionAreaContentBoxWidth = currentActionAreaWidth; + this._layoutDirty(); + this._machine.updateDom(); + } + } + }; + _CommandingSurface.prototype._dataDirty = function () { + this._nextLayoutStage = Math.max(CommandLayoutPipeline.newDataStage, this._nextLayoutStage); + }; + _CommandingSurface.prototype._meaurementsDirty = function () { + this._nextLayoutStage = Math.max(CommandLayoutPipeline.measuringStage, this._nextLayoutStage); + }; + _CommandingSurface.prototype._layoutDirty = function () { + this._nextLayoutStage = Math.max(CommandLayoutPipeline.layoutStage, this._nextLayoutStage); + }; + _CommandingSurface.prototype.synchronousOpen = function () { + this._overflowAlignmentOffset = 0; + this._isOpenedMode = true; + this.updateDomImpl(); + this._overflowAlignmentOffset = this._computeAdjustedOverflowAreaOffset(); + this.updateDomImpl(); + }; + _CommandingSurface.prototype._computeAdjustedOverflowAreaOffset = function () { + // Returns any negative offset needed to prevent the shown overflowarea from clipping outside of the viewport. + // This function should only be called when CommandingSurface has been rendered in the opened state with + // an overflowAlignmentOffset of 0. + if (_Log.log) { + !this._updateDomImpl_renderedState.isOpenedMode && _Log.log("The CommandingSurface should only attempt to compute adjusted overflowArea offset " + " when it has been rendered opened"); + this._updateDomImpl_renderedState.overflowAlignmentOffset !== 0 && _Log.log("The CommandingSurface should only attempt to compute adjusted overflowArea offset " + " when it has been rendered with an overflowAlignementOffset of 0"); + } + var overflowArea = this._dom.overflowArea, boundingClientRects = this.getBoundingRects(), adjustedOffset = 0; + if (this._rtl) { + // In RTL the left edge of overflowarea prefers to align to the LEFT edge of the commandingSurface. + // Make sure we avoid clipping through the RIGHT edge of the viewport + var viewportRight = window.innerWidth, rightOffsetFromViewport = boundingClientRects.overflowArea.right; + adjustedOffset = Math.min(viewportRight - rightOffsetFromViewport, 0); + } + else { + // In LTR the right edge of overflowarea prefers to align to the RIGHT edge of the commandingSurface. + // Make sure we avoid clipping through the LEFT edge of the viewport. + var leftOffsetFromViewport = boundingClientRects.overflowArea.left; + adjustedOffset = Math.min(0, leftOffsetFromViewport); + } + return adjustedOffset; + }; + _CommandingSurface.prototype.synchronousClose = function () { + this._isOpenedMode = false; + this.updateDomImpl(); + }; + _CommandingSurface.prototype.updateDomImpl = function () { + this._updateDomImpl_renderDisplayMode(); + this._updateDomImpl_updateCommands(); + }; + _CommandingSurface.prototype._updateDomImpl_renderDisplayMode = function () { + var rendered = this._updateDomImpl_renderedState; + if (rendered.isOpenedMode !== this._isOpenedMode) { + if (this._isOpenedMode) { + // Render opened + removeClass(this._dom.root, _Constants.ClassNames.closedClass); + addClass(this._dom.root, _Constants.ClassNames.openedClass); + } + else { + // Render closed + removeClass(this._dom.root, _Constants.ClassNames.openedClass); + addClass(this._dom.root, _Constants.ClassNames.closedClass); + } + rendered.isOpenedMode = this._isOpenedMode; + } + if (rendered.closedDisplayMode !== this.closedDisplayMode) { + removeClass(this._dom.root, closedDisplayModeClassMap[rendered.closedDisplayMode]); + addClass(this._dom.root, closedDisplayModeClassMap[this.closedDisplayMode]); + rendered.closedDisplayMode = this.closedDisplayMode; + } + if (rendered.overflowDirection !== this.overflowDirection) { + removeClass(this._dom.root, overflowDirectionClassMap[rendered.overflowDirection]); + addClass(this._dom.root, overflowDirectionClassMap[this.overflowDirection]); + rendered.overflowDirection = this.overflowDirection; + } + if (this._overflowAlignmentOffset !== rendered.overflowAlignmentOffset) { + var offsetProperty = (this._rtl ? "left" : "right"); + var offsetTextValue = this._overflowAlignmentOffset + "px"; + this._dom.overflowAreaContainer.style[offsetProperty] = offsetTextValue; + } + }; + _CommandingSurface.prototype._updateDomImpl_updateCommands = function () { + this._writeProfilerMark("_updateDomImpl_updateCommands,info"); + var nextStage = this._nextLayoutStage; + while (nextStage !== CommandLayoutPipeline.idle) { + var currentStage = nextStage; + var okToProceed = false; + switch (currentStage) { + case CommandLayoutPipeline.newDataStage: + nextStage = CommandLayoutPipeline.measuringStage; + okToProceed = this._processNewData(); + break; + case CommandLayoutPipeline.measuringStage: + nextStage = CommandLayoutPipeline.layoutStage; + okToProceed = this._measure(); + break; + case CommandLayoutPipeline.layoutStage: + nextStage = CommandLayoutPipeline.idle; + okToProceed = this._layoutCommands(); + break; + } + if (!okToProceed) { + // If a stage fails, exit the loop and track that stage + // to be restarted the next time _updateCommands is run. + nextStage = currentStage; + break; + } + } + this._nextLayoutStage = nextStage; + if (nextStage === CommandLayoutPipeline.idle) { + // Callback for unit tests. + this._layoutCompleteCallback && this._layoutCompleteCallback(); + } + }; + _CommandingSurface.prototype._getDataChangeInfo = function () { + var i = 0, len = 0; + var added = []; + var deleted = []; + var affected = []; + var currentShown = []; + var currentElements = []; + var newShown = []; + var newHidden = []; + var newElements = []; + Array.prototype.forEach.call(this._dom.actionArea.querySelectorAll(_Constants.commandSelector), function (commandElement) { + if (commandElement.style.display !== "none") { + currentShown.push(commandElement); + } + currentElements.push(commandElement); + }); + this.data.forEach(function (command) { + if (command.element.style.display !== "none") { + newShown.push(command.element); + } + else { + newHidden.push(command.element); + } + newElements.push(command.element); + }); + deleted = diffElements(currentShown, newShown); + affected = diffElements(currentShown, deleted); + // "added" must also include the elements from "newHidden" to ensure that we continue + // to animate any command elements that have underflowed back into the actionarea + // as a part of this data change. + added = diffElements(newShown, currentShown).concat(newHidden); + return { + newElements: newElements, + currentElements: currentElements, + added: added, + deleted: deleted, + affected: affected, + }; + }; + _CommandingSurface.prototype._processNewData = function () { + var _this = this; + this._writeProfilerMark("_processNewData,info"); + var changeInfo = this._getDataChangeInfo(); + // Take a snapshot of the current state + var updateCommandAnimation = Animations._createUpdateListAnimation(changeInfo.added, changeInfo.deleted, changeInfo.affected); + // Unbind property mutation event listener from deleted IObservableCommands + changeInfo.deleted.forEach(function (deletedElement) { + var command = (deletedElement['winControl']); + if (command && command['_propertyMutations']) { + command._propertyMutations.unbind(_this._refreshBound); + } + }); + // Bind property mutation event listener to added IObservable commands. + changeInfo.added.forEach(function (deletedElement) { + var command = (deletedElement['winControl']); + if (command && command['_propertyMutations']) { + command._propertyMutations.bind(_this._refreshBound); + } + }); + // Remove current ICommand elements + changeInfo.currentElements.forEach(function (element) { + if (element.parentElement) { + element.parentElement.removeChild(element); + } + }); + // Add new ICommand elements in the right order. + changeInfo.newElements.forEach(function (element) { + _this._dom.actionArea.appendChild(element); + }); + // Ensure that the overflow button is always the last element in the actionarea + this._dom.actionArea.appendChild(this._dom.overflowButton); + if (this.data.length > 0) { + _ElementUtilities.removeClass(this._dom.root, _Constants.ClassNames.emptyCommandingSurfaceCssClass); + } + else { + _ElementUtilities.addClass(this._dom.root, _Constants.ClassNames.emptyCommandingSurfaceCssClass); + } + // Execute the animation. + updateCommandAnimation.execute(); + // Indicate processing was successful. + return true; + }; + _CommandingSurface.prototype._measure = function () { + var _this = this; + this._writeProfilerMark("_measure,info"); + var canMeasure = (_Global.document.body.contains(this._dom.root) && this._dom.actionArea.offsetWidth > 0); + if (canMeasure) { + var overflowButtonWidth = _ElementUtilities._getPreciseTotalWidth(this._dom.overflowButton), actionAreaContentBoxWidth = _ElementUtilities._getPreciseContentWidth(this._dom.actionArea), separatorWidth = 0, standardCommandWidth = 0, contentCommandWidths = {}; + this._primaryCommands.forEach(function (command) { + // Ensure that the element we are measuring does not have display: none (e.g. it was just added, and it + // will be animated in) + var originalDisplayStyle = command.element.style.display; + command.element.style.display = ""; + if (command.type === _Constants.typeContent) { + // Measure each 'content' command type that we find + contentCommandWidths[_this._commandUniqueId(command)] = _ElementUtilities._getPreciseTotalWidth(command.element); + } + else if (command.type === _Constants.typeSeparator) { + // Measure the first 'separator' command type we find. + if (!separatorWidth) { + separatorWidth = _ElementUtilities._getPreciseTotalWidth(command.element); + } + } + else { + // Button, toggle, 'flyout' command types have the same width. Measure the first one we find. + if (!standardCommandWidth) { + standardCommandWidth = _ElementUtilities._getPreciseTotalWidth(command.element); + } + } + // Restore the original display style + command.element.style.display = originalDisplayStyle; + }); + this._cachedMeasurements = { + contentCommandWidths: contentCommandWidths, + separatorWidth: separatorWidth, + standardCommandWidth: standardCommandWidth, + overflowButtonWidth: overflowButtonWidth, + actionAreaContentBoxWidth: actionAreaContentBoxWidth, + }; + // Indicate measure was successful + return true; + } + else { + // Indicate measure was unsuccessful + return false; + } + }; + _CommandingSurface.prototype._layoutCommands = function () { + var _this = this; + this._writeProfilerMark("_layoutCommands,StartTM"); + // + // Filter commands that will not be visible in the actionarea + // + this._primaryCommands.forEach(function (command) { + command.element.style.display = (command.hidden ? "none" : ""); + }); + var primaryCommandsLocation = this._getVisiblePrimaryCommandsLocation(); + this._hideSeparatorsIfNeeded(primaryCommandsLocation.actionArea); + // Primary commands that will be mirrored in the overflow area should be hidden so + // that they are not visible in the actionarea. + primaryCommandsLocation.overflowArea.forEach(function (command) { + command.element.style.display = "none"; + }); + // The secondary commands in the actionarea should be hidden since they are always + // mirrored as new elements in the overflow area. + this._secondaryCommands.forEach(function (command) { + command.element.style.display = "none"; + }); + var overflowCommands = primaryCommandsLocation.overflowArea; + var showOverflowButton = (overflowCommands.length > 0 || this._secondaryCommands.length > 0); + this._dom.overflowButton.style.display = showOverflowButton ? "" : "none"; + // Set up a custom content flyout if there will be "content" typed commands in the overflowarea. + var isCustomContent = function (command) { + return command.type === _Constants.typeContent; + }; + var hasCustomContent = overflowCommands.some(isCustomContent) || this._secondaryCommands.some(isCustomContent); + if (hasCustomContent && !this._contentFlyout) { + this._contentFlyoutInterior = _Global.document.createElement("div"); + _ElementUtilities.addClass(this._contentFlyoutInterior, _Constants.ClassNames.contentFlyoutCssClass); + this._contentFlyout = new _Flyout.Flyout(); + this._contentFlyout.element.appendChild(this._contentFlyoutInterior); + _Global.document.body.appendChild(this._contentFlyout.element); + this._contentFlyout.onbeforeshow = function () { + _ElementUtilities.empty(_this._contentFlyoutInterior); + _ElementUtilities._reparentChildren(_this._chosenCommand.element, _this._contentFlyoutInterior); + }; + this._contentFlyout.onafterhide = function () { + _ElementUtilities._reparentChildren(_this._contentFlyoutInterior, _this._chosenCommand.element); + }; + } + // + // Project overflowing and secondary commands into the overflowArea as MenuCommands + // + // Clean up previous MenuCommand projections + _ElementUtilities.empty(this._dom.overflowArea); + this._menuCommandProjections.map(function (menuCommand) { + if (_this._contentFlyout && menuCommand.flyout === _this._contentFlyout) { + // Prevent our _contentFlyout from being disposed with the MenuCommand. + menuCommand.flyout = null; + } + menuCommand.dispose(); + }); + var hasToggleCommands = false, menuCommandProjections = []; + // Add primary commands that have overflowed. + overflowCommands.forEach(function (command) { + if (command.type === _Constants.typeToggle) { + hasToggleCommands = true; + } + menuCommandProjections.push(_this._projectAsMenuCommand(command)); + }); + // Add separator between primary and secondary command if applicable + var secondaryCommandsLength = this._secondaryCommands.length; + if (overflowCommands.length > 0 && secondaryCommandsLength > 0) { + var separator = new _CommandingSurfaceMenuCommand._MenuCommand(null, { + type: _Constants.typeSeparator + }); + menuCommandProjections.push(separator); + } + // Add secondary commands + this._secondaryCommands.forEach(function (command) { + if (!command.hidden) { + if (command.type === _Constants.typeToggle) { + hasToggleCommands = true; + } + menuCommandProjections.push(_this._projectAsMenuCommand(command)); + } + }); + this._hideSeparatorsIfNeeded(menuCommandProjections); + menuCommandProjections.forEach(function (command) { + _this._dom.overflowArea.appendChild(command.element); + }); + this._menuCommandProjections = menuCommandProjections; + _ElementUtilities[hasToggleCommands ? "addClass" : "removeClass"](this._dom.overflowArea, _Constants.ClassNames.menuContainsToggleCommandClass); + this._writeProfilerMark("_layoutCommands,StopTM"); + // Indicate layout was successful. + return true; + }; + _CommandingSurface.prototype._commandUniqueId = function (command) { + return _ElementUtilities._uniqueID(command.element); + }; + _CommandingSurface.prototype._getVisiblePrimaryCommandsInfo = function () { + var width = 0; + var commands = []; + var priority = 0; + var currentAssignedPriority = 0; + for (var i = this._primaryCommands.length - 1; i >= 0; i--) { + var command = this._primaryCommands[i]; + if (!command.hidden) { + if (command.priority === undefined) { + priority = currentAssignedPriority--; + } + else { + priority = command.priority; + } + width = (command.element.style.display === "none" ? 0 : this._getCommandWidth(command)); + commands.unshift({ + command: command, + width: width, + priority: priority + }); + } + } + return commands; + }; + _CommandingSurface.prototype._getVisiblePrimaryCommandsLocation = function () { + this._writeProfilerMark("_getVisiblePrimaryCommandsLocation,info"); + var actionAreaCommands = []; + var overflowAreaCommands = []; + var overflowButtonSpace = 0; + var hasSecondaryCommands = this._secondaryCommands.length > 0; + var commandsInfo = this._getVisiblePrimaryCommandsInfo(); + var sortedCommandsInfo = commandsInfo.slice(0).sort(function (commandInfo1, commandInfo2) { + return commandInfo1.priority - commandInfo2.priority; + }); + var maxPriority = Number.MAX_VALUE; + var availableWidth = this._cachedMeasurements.actionAreaContentBoxWidth; + for (var i = 0, len = sortedCommandsInfo.length; i < len; i++) { + availableWidth -= sortedCommandsInfo[i].width; + // The overflow button needs space if there are secondary commands, or we are not evaluating the last command. + overflowButtonSpace = (hasSecondaryCommands || (i < len - 1) ? this._cachedMeasurements.overflowButtonWidth : 0); + if (availableWidth - overflowButtonSpace < 0) { + maxPriority = sortedCommandsInfo[i].priority - 1; + break; + } + } + commandsInfo.forEach(function (commandInfo) { + if (commandInfo.priority <= maxPriority) { + actionAreaCommands.push(commandInfo.command); + } + else { + overflowAreaCommands.push(commandInfo.command); + } + }); + return { + actionArea: actionAreaCommands, + overflowArea: overflowAreaCommands + }; + }; + _CommandingSurface.prototype._getCommandWidth = function (command) { + if (command.type === _Constants.typeContent) { + return this._cachedMeasurements.contentCommandWidths[this._commandUniqueId(command)]; + } + else if (command.type === _Constants.typeSeparator) { + return this._cachedMeasurements.separatorWidth; + } + else { + return this._cachedMeasurements.standardCommandWidth; + } + }; + _CommandingSurface.prototype._projectAsMenuCommand = function (originalCommand) { + var _this = this; + var menuCommand = new _CommandingSurfaceMenuCommand._MenuCommand(null, { + label: originalCommand.label, + type: (originalCommand.type === _Constants.typeContent ? _Constants.typeFlyout : originalCommand.type) || _Constants.typeButton, + disabled: originalCommand.disabled, + flyout: originalCommand.flyout, + beforeInvoke: function () { + // Save the command that was selected + _this._chosenCommand = (menuCommand["_originalICommand"]); + // If this WinJS.UI.MenuCommand has type: toggle, we should also toggle the value of the original WinJS.UI.Command + if (_this._chosenCommand.type === _Constants.typeToggle) { + _this._chosenCommand.selected = !_this._chosenCommand.selected; + } + } + }); + if (originalCommand.selected) { + menuCommand.selected = true; + } + if (originalCommand.extraClass) { + menuCommand.extraClass = originalCommand.extraClass; + } + if (originalCommand.type === _Constants.typeContent) { + if (!menuCommand.label) { + menuCommand.label = _Constants.contentMenuCommandDefaultLabel; + } + menuCommand.flyout = this._contentFlyout; + } + else { + menuCommand.onclick = originalCommand.onclick; + } + menuCommand["_originalICommand"] = originalCommand; + return menuCommand; + }; + _CommandingSurface.prototype._hideSeparatorsIfNeeded = function (commands) { + var prevType = _Constants.typeSeparator; + var command; + // Hide all leading or consecutive separators + var commandsLength = commands.length; + commands.forEach(function (command) { + if (command.type === _Constants.typeSeparator && prevType === _Constants.typeSeparator) { + command.element.style.display = "none"; + } + prevType = command.type; + }); + for (var i = commandsLength - 1; i >= 0; i--) { + command = commands[i]; + if (command.type === _Constants.typeSeparator) { + command.element.style.display = "none"; + } + else { + break; + } + } + }; + _CommandingSurface.prototype._clearAnimation = function () { + var transformScriptName = _BaseUtils._browserStyleEquivalents["transform"].scriptName; + this._dom.actionAreaContainer.style[transformScriptName] = ""; + this._dom.actionArea.style[transformScriptName] = ""; + this._dom.overflowAreaContainer.style[transformScriptName] = ""; + this._dom.overflowArea.style[transformScriptName] = ""; + }; + /// Display options for the actionarea when the _CommandingSurface is closed. + _CommandingSurface.ClosedDisplayMode = ClosedDisplayMode; + /// Display options used by the _Commandingsurface to determine which direction it should expand when opening. + _CommandingSurface.OverflowDirection = OverflowDirection; + _CommandingSurface.supportedForProcessing = true; + return _CommandingSurface; + })(); + exports._CommandingSurface = _CommandingSurface; + _Base.Class.mix(_CommandingSurface, _Events.createEventProperties(_Constants.EventNames.beforeOpen, _Constants.EventNames.afterOpen, _Constants.EventNames.beforeClose, _Constants.EventNames.afterClose)); + // addEventListener, removeEventListener, dispatchEvent + _Base.Class.mix(_CommandingSurface, _Control.DOMEventMixin); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// +define('WinJS/Controls/CommandingSurface',["require", "exports"], function (require, exports) { + var module = null; + function getModule() { + if (!module) { + require(["./CommandingSurface/_CommandingSurface"], function (m) { + module = m; + }); + } + return module._CommandingSurface; + } + var publicMembers = Object.create({}, { + _CommandingSurface: { + get: function () { + return getModule(); + } + } + }); + return publicMembers; +}); + + +define('require-style!less/styles-toolbar',[],function(){}); +define('WinJS/Controls/ToolBar/_ToolBar',["require", "exports", "../../Core/_Base", "../ToolBar/_Constants", "../CommandingSurface", "../../Utilities/_Control", "../../Utilities/_Dispose", "../../Utilities/_ElementUtilities", "../../Core/_ErrorFromName", '../../Core/_Events', "../../Core/_Global", '../../_LightDismissService', "../../Core/_Resources", '../../Utilities/_OpenCloseMachine', "../../Core/_WriteProfilerMark"], function (require, exports, _Base, _Constants, _CommandingSurface, _Control, _Dispose, _ElementUtilities, _ErrorFromName, _Events, _Global, _LightDismissService, _Resources, _OpenCloseMachine, _WriteProfilerMark) { + require(["require-style!less/styles-toolbar"]); + "use strict"; + var strings = { + get ariaLabel() { + return _Resources._getWinJSString("ui/toolbarAriaLabel").value; + }, + get overflowButtonAriaLabel() { + return _Resources._getWinJSString("ui/toolbarOverflowButtonAriaLabel").value; + }, + get mustContainCommands() { + return "The toolbar can only contain WinJS.UI.Command or WinJS.UI.AppBarCommand controls"; + }, + get duplicateConstruction() { + return "Invalid argument: Controls may only be instantiated one time for each DOM element"; + } + }; + var ClosedDisplayMode = { + /// + /// When the ToolBar is closed, the height of the ToolBar is reduced such that button commands are still visible, but their labels are hidden. + /// + compact: "compact", + /// + /// When the ToolBar is closed, the height of the ToolBar is always sized to content. + /// + full: "full", + }; + var closedDisplayModeClassMap = {}; + closedDisplayModeClassMap[ClosedDisplayMode.compact] = _Constants.ClassNames.compactClass; + closedDisplayModeClassMap[ClosedDisplayMode.full] = _Constants.ClassNames.fullClass; + // Versions of add/removeClass that are no ops when called with falsy class names. + function addClass(element, className) { + className && _ElementUtilities.addClass(element, className); + } + function removeClass(element, className) { + className && _ElementUtilities.removeClass(element, className); + } + /// + /// + /// Displays ICommands within the flow of the app. Use the ToolBar around other statically positioned app content. + /// + /// + /// + /// + /// + /// + /// ]]> + /// The entire ToolBar control. + /// The toolbar overflow button. + /// The container for toolbar commands that overflow. + /// + /// + var ToolBar = (function () { + function ToolBar(element, options) { + /// + /// + /// Creates a new ToolBar control. + /// + /// + /// The DOM element that will host the control. + /// + /// + /// The set of properties and values to apply to the new ToolBar control. + /// + /// + /// The new ToolBar control. + /// + /// + var _this = this; + if (options === void 0) { options = {}; } + // State private to the _updateDomImpl family of method. No other methods should make use of it. + // + // Nothing has been rendered yet so these are all initialized to undefined. Because + // they are undefined, the first time _updateDomImpl is called, they will all be + // rendered. + this._updateDomImpl_renderedState = { + isOpenedMode: undefined, + closedDisplayMode: undefined, + prevInlineWidth: undefined, + }; + this._writeProfilerMark("constructor,StartTM"); + // Check to make sure we weren't duplicated + if (element && element["winControl"]) { + throw new _ErrorFromName("WinJS.UI.ToolBar.DuplicateConstruction", strings.duplicateConstruction); + } + this._initializeDom(element || _Global.document.createElement("div")); + var stateMachine = new _OpenCloseMachine.OpenCloseMachine({ + eventElement: this.element, + onOpen: function () { + var openAnimation = _this._commandingSurface.createOpenAnimation(_this._getClosedHeight()); + _this._synchronousOpen(); + return openAnimation.execute(); + }, + onClose: function () { + var closeAnimation = _this._commandingSurface.createCloseAnimation(_this._getClosedHeight()); + return closeAnimation.execute().then(function () { + _this._synchronousClose(); + }); + }, + onUpdateDom: function () { + _this._updateDomImpl(); + }, + onUpdateDomWithIsOpened: function (isOpened) { + _this._isOpenedMode = isOpened; + _this._updateDomImpl(); + } + }); + // Events + this._handleShowingKeyboardBound = this._handleShowingKeyboard.bind(this); + _ElementUtilities._inputPaneListener.addEventListener(this._dom.root, "showing", this._handleShowingKeyboardBound); + // Initialize private state. + this._disposed = false; + this._cachedClosedHeight = null; + this._commandingSurface = new _CommandingSurface._CommandingSurface(this._dom.commandingSurfaceEl, { openCloseMachine: stateMachine }); + addClass(this._dom.commandingSurfaceEl.querySelector(".win-commandingsurface-actionarea"), _Constants.ClassNames.actionAreaCssClass); + addClass(this._dom.commandingSurfaceEl.querySelector(".win-commandingsurface-overflowarea"), _Constants.ClassNames.overflowAreaCssClass); + addClass(this._dom.commandingSurfaceEl.querySelector(".win-commandingsurface-overflowbutton"), _Constants.ClassNames.overflowButtonCssClass); + addClass(this._dom.commandingSurfaceEl.querySelector(".win-commandingsurface-ellipsis"), _Constants.ClassNames.ellipsisCssClass); + this._isOpenedMode = _Constants.defaultOpened; + this._dismissable = new _LightDismissService.LightDismissableElement({ + element: this._dom.root, + tabIndex: this._dom.root.hasAttribute("tabIndex") ? this._dom.root.tabIndex : -1, + onLightDismiss: function () { + _this.close(); + } + }); + // Initialize public properties. + this.closedDisplayMode = _Constants.defaultClosedDisplayMode; + this.opened = this._isOpenedMode; + _Control.setOptions(this, options); + // Exit the Init state. + _ElementUtilities._inDom(this.element).then(function () { + return _this._commandingSurface.initialized; + }).then(function () { + stateMachine.exitInit(); + _this._writeProfilerMark("constructor,StopTM"); + }); + } + Object.defineProperty(ToolBar.prototype, "element", { + /// + get: function () { + return this._dom.root; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ToolBar.prototype, "data", { + /// + /// Gets or sets the Binding List of WinJS.UI.Command for the ToolBar. + /// + get: function () { + return this._commandingSurface.data; + }, + set: function (value) { + this._commandingSurface.data = value; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ToolBar.prototype, "closedDisplayMode", { + /// + /// Gets or sets the closedDisplayMode for the ToolBar. Values are "compact" and "full". + /// + get: function () { + return this._commandingSurface.closedDisplayMode; + }, + set: function (value) { + if (ClosedDisplayMode[value]) { + this._commandingSurface.closedDisplayMode = value; + this._cachedClosedHeight = null; + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(ToolBar.prototype, "opened", { + /// + get: function () { + return this._commandingSurface.opened; + }, + set: function (value) { + this._commandingSurface.opened = value; + }, + enumerable: true, + configurable: true + }); + ToolBar.prototype.open = function () { + /// + /// + /// Opens the ToolBar + /// + /// + this._commandingSurface.open(); + }; + ToolBar.prototype.close = function () { + /// + /// + /// Closes the ToolBar + /// + /// + this._commandingSurface.close(); + }; + ToolBar.prototype.dispose = function () { + /// + /// + /// Disposes this ToolBar. + /// + /// + if (this._disposed) { + return; + } + this._disposed = true; + _LightDismissService.hidden(this._dismissable); + // Disposing the _commandingSurface will trigger dispose on its OpenCloseMachine and synchronously complete any animations that might have been running. + this._commandingSurface.dispose(); + // If page navigation is happening, we don't want the ToolBar left behind in the body. + // Synchronoulsy close the ToolBar to force it out of the body and back into its parent element. + this._synchronousClose(); + _ElementUtilities._inputPaneListener.removeEventListener(this._dom.root, "showing", this._handleShowingKeyboardBound); + _Dispose.disposeSubTree(this.element); + }; + ToolBar.prototype.forceLayout = function () { + /// + /// + /// Forces the ToolBar to update its layout. Use this function when the window did not change size, but the container of the ToolBar changed size. + /// + /// + this._commandingSurface.forceLayout(); + }; + ToolBar.prototype.getCommandById = function (id) { + /// + /// + /// Retrieves the command with the specified ID from this ToolBar. + /// If more than one command is found, this method returns the first command found. + /// + /// Id of the command to return. + /// + /// The command found, or null if no command is found. + /// + /// + return this._commandingSurface.getCommandById(id); + }; + ToolBar.prototype.showOnlyCommands = function (commands) { + /// + /// + /// Show the specified commands, hiding all of the others in the ToolBar. + /// + /// + /// An array of the commands to show. The array elements may be Command objects, or the string identifiers (IDs) of commands. + /// + /// + return this._commandingSurface.showOnlyCommands(commands); + }; + ToolBar.prototype._writeProfilerMark = function (text) { + _WriteProfilerMark("WinJS.UI.ToolBar:" + this._id + ":" + text); + }; + ToolBar.prototype._initializeDom = function (root) { + this._writeProfilerMark("_intializeDom,info"); + // Attaching JS control to DOM element + root["winControl"] = this; + this._id = root.id || _ElementUtilities._uniqueID(root); + _ElementUtilities.addClass(root, _Constants.ClassNames.controlCssClass); + _ElementUtilities.addClass(root, _Constants.ClassNames.disposableCssClass); + // Make sure we have an ARIA role + var role = root.getAttribute("role"); + if (!role) { + root.setAttribute("role", "menubar"); + } + var label = root.getAttribute("aria-label"); + if (!label) { + root.setAttribute("aria-label", strings.ariaLabel); + } + // Create element for commandingSurface and reparent any declarative Commands. + // The CommandingSurface constructor will parse child elements as AppBarCommands. + var commandingSurfaceEl = document.createElement("DIV"); + _ElementUtilities._reparentChildren(root, commandingSurfaceEl); + root.appendChild(commandingSurfaceEl); + // While the ToolBar is open, it will place itself in the so it can become a light dismissible + // overlay. It leaves the placeHolder element behind as stand in at the ToolBar's original DOM location + // to avoid reflowing surrounding app content and create the illusion that the ToolBar hasn't moved along + // the x or y planes. + var placeHolder = _Global.document.createElement("DIV"); + _ElementUtilities.addClass(placeHolder, _Constants.ClassNames.placeHolderCssClass); + // If the ToolBar's original HTML parent node is disposed while the ToolBar is open and repositioned as + // a temporary child of the , make sure that calling dispose on the placeHolder element will trigger + // dispose on the ToolBar as well. + _Dispose.markDisposable(placeHolder, this.dispose.bind(this)); + this._dom = { + root: root, + commandingSurfaceEl: commandingSurfaceEl, + placeHolder: placeHolder, + }; + }; + ToolBar.prototype._handleShowingKeyboard = function (event) { + // Because the ToolBar takes up layout space and is not an overlay, it doesn't have the same expectation + // to move itself to get out of the way of a showing IHM. Instsead we just close the ToolBar to avoid + // scenarios where the ToolBar is occluded, but the click-eating-div is still present since it may seem + // strange to end users that an occluded ToolBar (out of sight, out of mind) is still eating their first + // click. + // Mitigation: + // Because (1) custom content in a ToolBar can only be included as a 'content' type command, because (2) + // the ToolBar only supports closedDisplayModes 'compact' and 'full', and because (3) 'content' type + // commands in the overflowarea use a separate contentflyout to display their contents: + // Interactable custom content contained within the ToolBar actionarea or overflowarea, will remain + // visible and interactable even when showing the IHM closes the ToolBar. + this.close(); + }; + ToolBar.prototype._synchronousOpen = function () { + this._isOpenedMode = true; + this._updateDomImpl(); + }; + ToolBar.prototype._synchronousClose = function () { + this._isOpenedMode = false; + this._updateDomImpl(); + }; + ToolBar.prototype._updateDomImpl = function () { + var rendered = this._updateDomImpl_renderedState; + if (rendered.isOpenedMode !== this._isOpenedMode) { + if (this._isOpenedMode) { + this._updateDomImpl_renderOpened(); + } + else { + this._updateDomImpl_renderClosed(); + } + rendered.isOpenedMode = this._isOpenedMode; + } + if (rendered.closedDisplayMode !== this.closedDisplayMode) { + removeClass(this._dom.root, closedDisplayModeClassMap[rendered.closedDisplayMode]); + addClass(this._dom.root, closedDisplayModeClassMap[this.closedDisplayMode]); + rendered.closedDisplayMode = this.closedDisplayMode; + } + this._commandingSurface.updateDomImpl(); + }; + ToolBar.prototype._getClosedHeight = function () { + if (this._cachedClosedHeight === null) { + var wasOpen = this._isOpenedMode; + if (this._isOpenedMode) { + this._synchronousClose(); + } + this._cachedClosedHeight = this._commandingSurface.getBoundingRects().commandingSurface.height; + if (wasOpen) { + this._synchronousOpen(); + } + } + return this._cachedClosedHeight; + }; + ToolBar.prototype._updateDomImpl_renderOpened = function () { + var _this = this; + // Measure closed state. + this._updateDomImpl_renderedState.prevInlineWidth = this._dom.root.style.width; + var closedBorderBox = this._dom.root.getBoundingClientRect(); + var closedContentWidth = _ElementUtilities._getPreciseContentWidth(this._dom.root); + var closedContentHeight = _ElementUtilities._getPreciseContentHeight(this._dom.root); + var closedStyle = getComputedStyle(this._dom.root); + var closedPaddingTop = _ElementUtilities._convertToPrecisePixels(closedStyle.paddingTop); + var closedBorderTop = _ElementUtilities._convertToPrecisePixels(closedStyle.borderTopWidth); + var closedMargins = _ElementUtilities._getPreciseMargins(this._dom.root); + var closedContentBoxTop = closedBorderBox.top + closedBorderTop + closedPaddingTop; + var closedContentBoxBottom = closedContentBoxTop + closedContentHeight; + // Size our placeHolder. Set height and width to match borderbox of the closed ToolBar. + // Copy ToolBar margins to the placeholder. + var placeHolder = this._dom.placeHolder; + var placeHolderStyle = placeHolder.style; + placeHolderStyle.width = closedBorderBox.width + "px"; + placeHolderStyle.height = closedBorderBox.height + "px"; + placeHolderStyle.marginTop = closedMargins.top + "px"; + placeHolderStyle.marginRight = closedMargins.right + "px"; + placeHolderStyle.marginBottom = closedMargins.bottom + "px"; + placeHolderStyle.marginLeft = closedMargins.left + "px"; + _ElementUtilities._maintainFocus(function () { + // Move ToolBar element to the body in preparation of becoming a light dismissible. Leave an equal sized placeHolder element + // at our original DOM location to avoid reflowing surrounding app content. + _this._dom.root.parentElement.insertBefore(placeHolder, _this._dom.root); + _Global.document.body.appendChild(_this._dom.root); + // Position the ToolBar to completely cover the same region as the placeholder element. + _this._dom.root.style.width = closedContentWidth + "px"; + _this._dom.root.style.left = closedBorderBox.left - closedMargins.left + "px"; + // Determine which direction to expand the CommandingSurface elements when opened. The overflow area will be rendered at the corresponding edge of + // the ToolBar's content box, so we choose the direction that offers the most space between that edge and the corresponding edge of the viewport. + // This is to reduce the chance that the overflow area might clip through the edge of the viewport. + var topOfViewport = 0; + var bottomOfViewport = _Global.innerHeight; + var distanceFromTop = closedContentBoxTop - topOfViewport; + var distanceFromBottom = bottomOfViewport - closedContentBoxBottom; + if (distanceFromTop > distanceFromBottom) { + // CommandingSurface is going to expand updwards. + _this._commandingSurface.overflowDirection = _Constants.OverflowDirection.top; + // Position the bottom edge of the ToolBar marginbox over the bottom edge of the placeholder marginbox. + _this._dom.root.style.bottom = (bottomOfViewport - closedBorderBox.bottom) - closedMargins.bottom + "px"; + } + else { + // CommandingSurface is going to expand downwards. + _this._commandingSurface.overflowDirection = _Constants.OverflowDirection.bottom; + // Position the top edge of the ToolBar marginbox over the top edge of the placeholder marginbox. + _this._dom.root.style.top = (topOfViewport + closedBorderBox.top) - closedMargins.top + "px"; + } + // Render opened state + _ElementUtilities.addClass(_this._dom.root, _Constants.ClassNames.openedClass); + _ElementUtilities.removeClass(_this._dom.root, _Constants.ClassNames.closedClass); + }); + this._commandingSurface.synchronousOpen(); + _LightDismissService.shown(this._dismissable); // Call at the start of the open animation + }; + ToolBar.prototype._updateDomImpl_renderClosed = function () { + var _this = this; + _ElementUtilities._maintainFocus(function () { + if (_this._dom.placeHolder.parentElement) { + // Restore our placement in the DOM + var placeHolder = _this._dom.placeHolder; + placeHolder.parentElement.insertBefore(_this._dom.root, placeHolder); + placeHolder.parentElement.removeChild(placeHolder); + } + // Render Closed + _this._dom.root.style.top = ""; + _this._dom.root.style.right = ""; + _this._dom.root.style.bottom = ""; + _this._dom.root.style.left = ""; + _this._dom.root.style.width = _this._updateDomImpl_renderedState.prevInlineWidth; + _ElementUtilities.addClass(_this._dom.root, _Constants.ClassNames.closedClass); + _ElementUtilities.removeClass(_this._dom.root, _Constants.ClassNames.openedClass); + }); + this._commandingSurface.synchronousClose(); + _LightDismissService.hidden(this._dismissable); // Call after the close animation + }; + /// + /// Display options for the actionarea when the ToolBar is closed. + /// + ToolBar.ClosedDisplayMode = ClosedDisplayMode; + ToolBar.supportedForProcessing = true; + return ToolBar; + })(); + exports.ToolBar = ToolBar; + _Base.Class.mix(ToolBar, _Events.createEventProperties(_Constants.EventNames.beforeOpen, _Constants.EventNames.afterOpen, _Constants.EventNames.beforeClose, _Constants.EventNames.afterClose)); + // addEventListener, removeEventListener, dispatchEvent + _Base.Class.mix(ToolBar, _Control.DOMEventMixin); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// +define('WinJS/Controls/ToolBar',["require", "exports", '../Core/_Base'], function (require, exports, _Base) { + var module = null; + _Base.Namespace.define("WinJS.UI", { + ToolBar: { + get: function () { + if (!module) { + require(["./ToolBar/_ToolBar"], function (m) { + module = m; + }); + } + return module.ToolBar; + } + } + }); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('WinJS/Controls/_LegacyAppBar/_Layouts',[ + 'exports', + '../../Animations/_TransitionAnimation', + '../../BindingList', + '../../Core/_BaseUtils', + '../../Core/_Global', + '../../Core/_Base', + '../../Core/_ErrorFromName', + '../../Core/_Resources', + '../../Core/_WriteProfilerMark', + '../../Controls/ToolBar', + '../../Controls/ToolBar/_Constants', + '../../Promise', + '../../Scheduler', + '../../Utilities/_Control', + '../../Utilities/_Dispose', + '../../Utilities/_ElementUtilities', + '../AppBar/_Command', + './_Constants' +], function appBarLayoutsInit(exports, _TransitionAnimation, BindingList, _BaseUtils, _Global, _Base, _ErrorFromName, _Resources, _WriteProfilerMark, ToolBar, _ToolBarConstants, Promise, Scheduler, _Control, _Dispose, _ElementUtilities, _Command, _Constants) { + "use strict"; + + // AppBar will use this when AppBar.layout property is set to "custom" + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + _AppBarBaseLayout: _Base.Namespace._lazy(function () { + var baseType = _Constants.appBarLayoutCustom; + + var strings = { + get nullCommand() { return "Invalid argument: command must not be null"; } + }; + + var _AppBarBaseLayout = _Base.Class.define(function _AppBarBaseLayout_ctor(appBarEl, options) { + this._disposed = false; + + options = options || {}; + _Control.setOptions(this, options); + + if (appBarEl) { + this.connect(appBarEl); + } + }, { + // Members + className: { + get: function _AppBarBaseLayout_get_className() { + return this._className; + }, + }, + type: { + get: function _AppBarBaseLayout_get_className() { + return this._type || baseType; + }, + }, + commandsInOrder: { + get: function _AppBarBaseLayout_get_commandsInOrder() { + // Get a DOM ordered collection of the AppBarCommand elements in the AppBar. + var commandElements = this.appBarEl.querySelectorAll("." + _Constants.appBarCommandClass); + + // Return an array of AppBarCommand objects. + return Array.prototype.map.call(commandElements, function (commandElement) { + return commandElement.winControl; + }); + } + }, + connect: function _AppBarBaseLayout_connect(appBarEl) { + if (this.className) { + _ElementUtilities.addClass(appBarEl, this.className); + } + this.appBarEl = appBarEl; + }, + disconnect: function _AppBarBaseLayout_disconnect() { + if (this.className) { + _ElementUtilities.removeClass(this.appBarEl, this.className); + } + this.appBarEl = null; + this.dispose(); + }, + layout: function _AppBarBaseLayout_layout(commands) { + // Append commands to the DOM. + var len = commands.length; + for (var i = 0; i < len; i++) { + var command = this.sanitizeCommand(commands[i]); + this.appBarEl.appendChild(command._element); + } + }, + showCommands: function _AppBarBaseLayout_showCommands(commands) { + // Use the default overlay showCommands implementation + this.appBarEl.winControl._showCommands(commands); + }, + showOnlyCommands: function _AppBarBaseLayout_showOnlyCommands(commands) { + // Use the default overlay _showOnlyCommands implementation + this.appBarEl.winControl._showOnlyCommands(commands); + }, + hideCommands: function _AppBarBaseLayout_hideCommands(commands) { + // Use the default overlay _hideCommands implementation + this.appBarEl.winControl._hideCommands(commands); + }, + sanitizeCommand: function _AppBarBaseLayout_sanitizeCommand(command) { + if (!command) { + throw new _ErrorFromName("WinJS.UI.AppBar.NullCommand", strings.nullCommand); + } + // See if it's a command already + command = command.winControl || command; + if (!command._element) { + // Not a command, so assume it is options for the command's constructor. + command = new _Command.AppBarCommand(null, command); + } + // If we were attached somewhere else, detach us + if (command._element.parentElement) { + command._element.parentElement.removeChild(command._element); + } + + return command; + }, + dispose: function _AppBarBaseLayout_dispose() { + this._disposed = true; + }, + disposeChildren: function _AppBarBaseLayout_disposeChildren() { + var appBarFirstDiv = this.appBarEl.querySelectorAll("." + _Constants.firstDivClass); + appBarFirstDiv = appBarFirstDiv.length >= 1 ? appBarFirstDiv[0] : null; + var appBarFinalDiv = this.appBarEl.querySelectorAll("." + _Constants.finalDivClass); + appBarFinalDiv = appBarFinalDiv.length >= 1 ? appBarFinalDiv[0] : null; + + var children = this.appBarEl.children; + var length = children.length; + for (var i = 0; i < length; i++) { + var element = children[i]; + if (element === appBarFirstDiv || element === appBarFinalDiv) { + continue; + } else { + _Dispose.disposeSubTree(element); + } + } + }, + handleKeyDown: function _AppBarBaseLayout_handleKeyDown() { + // NOP + }, + commandsUpdated: function _AppBarBaseLayout_commandsUpdated() { + // NOP + }, + beginAnimateCommands: function _AppBarBaseLayout_beginAnimateCommands() { + // The parameters are 3 mutually exclusive arrays of win-command elements contained in this Overlay. + // 1) showCommands[]: All of the HIDDEN win-command elements that ARE scheduled to show. + // 2) hideCommands[]: All of the VISIBLE win-command elements that ARE scheduled to hide. + // 3) otherVisibleCommands[]: All VISIBLE win-command elements that ARE NOT scheduled to hide. + + // NOP + }, + endAnimateCommands: function _AppBarBaseLayout_endAnimateCommands() { + // NOP + }, + scale: function _AppBarBaseLayout_scale() { + // NOP + }, + resize: function _AppBarBaseLayout_resize() { + // NOP + }, + positionChanging: function _AppBarBaseLayout_positionChanging(fromPosition, toPosition) { + // NOP + return Promise.wrap(); + }, + setFocusOnShow: function _AppBarBaseLayout_setFocusOnShow() { + this.appBarEl.winControl._setFocusToAppBar(); + } + }); + return _AppBarBaseLayout; + }), + }); + + // AppBar will use this when AppBar.layout property is set to "commands" + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + _AppBarCommandsLayout: _Base.Namespace._lazy(function () { + var layoutClassName = _Constants.commandLayoutClass; + var layoutType = _Constants.appBarLayoutCommands; + + var _AppBarCommandsLayout = _Base.Class.derive(exports._AppBarBaseLayout, function _AppBarCommandsLayout_ctor(appBarEl) { + exports._AppBarBaseLayout.call(this, appBarEl, { _className: layoutClassName, _type: layoutType }); + this._commandLayoutsInit(appBarEl); + }, { + commandsInOrder: { + get: function _AppBarCommandsLayout_get_commandsInOrder() { + return this._originalCommands.filter(function (command) { + // Make sure the element is still in the AppBar. + return this.appBarEl.contains(command.element); + }, this); + } + }, + layout: function _AppBarCommandsLayout_layout(commands) { + // Insert commands and other layout specific DOM into the AppBar element. + + // Empty our tree. + _ElementUtilities.empty(this._primaryCommands); + _ElementUtilities.empty(this._secondaryCommands); + + // Keep track of the order we receive the commands in. + this._originalCommands = []; + + // Layout commands + for (var i = 0, len = commands.length; i < len; i++) { + var command = this.sanitizeCommand(commands[i]); + + this._originalCommands.push(command); + + if ("primary" === command.section || "global" === command.section) { + this._primaryCommands.appendChild(command._element); + } else { + this._secondaryCommands.appendChild(command._element); + } + } + + // Append layout containers to AppBar element. + // Secondary Commands should come first in Tab Order. + this.appBarEl.appendChild(this._secondaryCommands); + this.appBarEl.appendChild(this._primaryCommands); + + + // Need to measure all content commands after they have been added to the AppBar to make sure we allow + // user defined CSS rules based on the ancestor of the content command to take affect. + this._needToMeasureNewCommands = true; + + // In case this is called from the constructor before the AppBar element has been appended to the DOM, + // we schedule the initial scaling of commands, with the expectation that the element will be added + // synchronously, in the same block of code that called the constructor. + Scheduler.schedule(function () { + if (this._needToMeasureNewCommands && !this._disposed) { + this.scale(); + } + }.bind(this), Scheduler.Priority.idle, this, "WinJS._commandLayoutsMixin._scaleNewCommands"); + + }, + disposeChildren: function _AppBarCommandsLayout_disposeChildren() { + _Dispose.disposeSubTree(this._primaryCommands); + _Dispose.disposeSubTree(this._secondaryCommands); + }, + handleKeyDown: function _AppBarCommandsLayout_handleKeyDown(event) { + var Key = _ElementUtilities.Key; + + if (_ElementUtilities._matchesSelector(event.target, ".win-interactive, .win-interactive *")) { + return; // Ignore left, right, home & end keys if focused element has win-interactive class. + } + var rtl = _Global.getComputedStyle(this.appBarEl).direction === "rtl"; + var leftKey = rtl ? Key.rightArrow : Key.leftArrow; + var rightKey = rtl ? Key.leftArrow : Key.rightArrow; + + if (event.keyCode === leftKey || event.keyCode === rightKey || event.keyCode === Key.home || event.keyCode === Key.end) { + + var globalCommandHasFocus = this._primaryCommands.contains(_Global.document.activeElement); + var focusableCommands = this._getFocusableCommandsInLogicalOrder(globalCommandHasFocus); + var targetCommand; + + if (focusableCommands.length) { + switch (event.keyCode) { + case leftKey: + // Arrowing past the last command wraps back around to the first command. + var index = Math.max(-1, focusableCommands.focusedIndex - 1) + focusableCommands.length; + targetCommand = focusableCommands[index % focusableCommands.length].winControl.lastElementFocus; + break; + + case rightKey: + // Arrowing previous to the first command wraps back around to the last command. + var index = focusableCommands.focusedIndex + 1 + focusableCommands.length; + targetCommand = focusableCommands[index % focusableCommands.length].winControl.firstElementFocus; + break; + + case Key.home: + var index = 0; + targetCommand = focusableCommands[index].winControl.firstElementFocus; + break; + + case Key.end: + var index = focusableCommands.length - 1; + targetCommand = focusableCommands[index].winControl.lastElementFocus; + break; + } + } + + if (targetCommand && targetCommand !== _Global.document.activeElement) { + targetCommand.focus(); + // Prevent default so that the browser doesn't also evaluate the keydown event on the newly focused element. + event.preventDefault(); + } + } + }, + commandsUpdated: function _AppBarCommandsLayout_commandsUpdated(newSetOfVisibleCommands) { + // Whenever new commands are set or existing commands are hiding/showing in the AppBar, this + // function is called to update the cached width measurement of all visible AppBarCommands. + + var visibleCommands = (newSetOfVisibleCommands) ? newSetOfVisibleCommands : this.commandsInOrder.filter(function (command) { + return !command.hidden; + }); + this._fullSizeWidthOfLastKnownVisibleCommands = this._getWidthOfFullSizeCommands(visibleCommands); + }, + beginAnimateCommands: function _AppBarCommandsLayout_beginAnimateCommands(showCommands, hideCommands, otherVisibleCommands) { + // The parameters are 3 mutually exclusive arrays of win-command elements contained in this Overlay. + // 1) showCommands[]: All of the HIDDEN win-command elements that ARE scheduled to show. + // 2) hideCommands[]: All of the VISIBLE win-command elements that ARE scheduled to hide. + // 3) otherVisibleCommands[]: All VISIBLE win-command elements that ARE NOT scheduled to hide. + + this._scaleAfterAnimations = false; + + // Determine if the overall width of visible commands in the primary row will be increasing OR decreasing. + var changeInWidth = this._getWidthOfFullSizeCommands(showCommands) - this._getWidthOfFullSizeCommands(hideCommands); + if (changeInWidth > 0) { + // Width of contents is going to increase, update our command counts now, to what they will be after we complete the animations. + var visibleCommandsAfterAnimations = otherVisibleCommands.concat(showCommands); + this.commandsUpdated(visibleCommandsAfterAnimations); + // Make sure we will have enough room to fit everything on a single row. + this.scale(); + } else if (changeInWidth < 0) { + // Width of contents is going to decrease. Once animations are complete, check if + // there is enough available space to make the remaining commands full size. + this._scaleAfterAnimations = true; + } + }, + endAnimateCommands: function _AppBarCommandsLayout_endAnimateCommands() { + if (this._scaleAfterAnimations) { + this.commandsUpdated(); + this.scale(); + } + }, + resize: function _AppBarCommandsLayout_resize() { + if (!this._disposed) { + // Check for horizontal window resizes. + this._appBarTotalKnownWidth = null; + if (this.appBarEl.winControl.opened) { + this.scale(); + } + } + }, + disconnect: function _AppBarCommandsLayout_disconnect() { + exports._AppBarBaseLayout.prototype.disconnect.call(this); + }, + _getWidthOfFullSizeCommands: function _AppBarCommandsLayout_getWidthOfFullSizeCommands(commands) { + // Commands layout puts primary commands and secondary commands into the primary row. + // Return the total width of all visible primary and secondary commands as if they were full-size. + + // Perform any pending measurements on "content" type AppBarCommands. + if (this._needToMeasureNewCommands) { + this._measureContentCommands(); + } + var accumulatedWidth = 0; + var separatorsCount = 0; + var buttonsCount = 0; + + if (!commands) { + // Return the cached full size width of the last known visible commands in the AppBar. + return this._fullSizeWidthOfLastKnownVisibleCommands; + } else { + // Return the width of the specified commands. + var command; + for (var i = 0, len = commands.length; i < len; i++) { + command = commands[i].winControl || commands[i]; + if (command._type === _Constants.typeSeparator) { + separatorsCount++; + } else if (command._type !== _Constants.typeContent) { + // button, toggle, and flyout types all have the same width. + buttonsCount++; + } else { + accumulatedWidth += command._fullSizeWidth; + } + } + } + return accumulatedWidth += (separatorsCount * _Constants.separatorWidth) + (buttonsCount * _Constants.buttonWidth); + }, + _getFocusableCommandsInLogicalOrder: function _AppBarCommandsLayout_getCommandsInLogicalOrder() { + // Function returns an array of all the contained AppBarCommands which are reachable by left/right arrows. + + var secondaryCommands = this._secondaryCommands.children, + primaryCommands = this._primaryCommands.children, + focusedIndex = -1; + + var getFocusableCommandsHelper = function (commandsInReach) { + var focusableCommands = []; + for (var i = 0, len = commandsInReach.length; i < len; i++) { + var element = commandsInReach[i]; + if (_ElementUtilities.hasClass(element, _Constants.appBarCommandClass) && element.winControl) { + var containsFocus = element.contains(_Global.document.activeElement); + // With the inclusion of content type commands, it may be possible to tab to elements in AppBarCommands that are not reachable by arrow keys. + // Regardless, when an AppBarCommand contains the element with focus, we just include the whole command so that we can determine which + // commands are adjacent to it when looking for the next focus destination. + if (element.winControl._isFocusable() || containsFocus) { + focusableCommands.push(element); + if (containsFocus) { + focusedIndex = focusableCommands.length - 1; + } + } + } + } + return focusableCommands; + }; + + // Determines which set of commands the user could potentially reach through Home, End, and arrow keys. + // All commands in the commands layout AppBar, from left to right are in reach. Secondary (previously known as Selection) + // then Primary (previously known as Global). + var commandsInReach = Array.prototype.slice.call(secondaryCommands).concat(Array.prototype.slice.call(primaryCommands)); + + var focusableCommands = getFocusableCommandsHelper(commandsInReach); + focusableCommands.focusedIndex = focusedIndex; + return focusableCommands; + }, + _commandLayoutsInit: function _AppBarCommandsLayout_commandLayoutsInit() { + // Create layout infrastructure + this._primaryCommands = _Global.document.createElement("DIV"); + this._secondaryCommands = _Global.document.createElement("DIV"); + _ElementUtilities.addClass(this._primaryCommands, _Constants.primaryCommandsClass); + _ElementUtilities.addClass(this._secondaryCommands, _Constants.secondaryCommandsClass); + }, + _scaleHelper: function _AppBarCommandsLayout_scaleHelper() { + // This exists as a single line function so that unit tests can + // overwrite it since they can't resize the WWA window. + + // It is expected that AppBar is an immediate child of the and will have 100% width. + // We measure the clientWidth of the documentElement so that we can scale the AppBar lazily + // even while its element is display: 'none' + var extraPadding = this.appBarEl.winControl.closedDisplayMode === "minimal" ? _Constants.appBarInvokeButtonWidth : 0; + return _Global.document.documentElement.clientWidth - extraPadding; + }, + _measureContentCommands: function _AppBarCommandsLayout_measureContentCommands() { + // AppBar measures the width of content commands when they are first added + // and then caches that value to avoid additional layouts in the future. + + // Can't measure unless We're in the document body + if (_Global.document.body.contains(this.appBarEl)) { + this._needToMeasureNewCommands = false; + + var hadHiddenClass = _ElementUtilities.hasClass(this.appBarEl, "win-navbar-closed"); + _ElementUtilities.removeClass(this.appBarEl, "win-navbar-closed"); + + // Make sure AppBar and children have width dimensions. + var prevAppBarDisplay = this.appBarEl.style.display; + this.appBarEl.style.display = ""; + var prevCommandDisplay; + + var contentElements = this.appBarEl.querySelectorAll("div." + _Constants.appBarCommandClass); + var element; + for (var i = 0, len = contentElements.length; i < len; i++) { + element = contentElements[i]; + if (element.winControl && element.winControl._type === _Constants.typeContent) { + // Make sure command has width dimensions before we measure. + prevCommandDisplay = element.style.display; + element.style.display = ""; + element.winControl._fullSizeWidth = _ElementUtilities.getTotalWidth(element) || 0; + element.style.display = prevCommandDisplay; + } + } + + // Restore state to AppBar. + this.appBarEl.style.display = prevAppBarDisplay; + if (hadHiddenClass) { + _ElementUtilities.addClass(this.appBarEl, "win-navbar-closed"); + } + + this.commandsUpdated(); + } + }, + }); + return _AppBarCommandsLayout; + }), + }); + + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + _AppBarMenuLayout: _Base.Namespace._lazy(function () { + var layoutClassName = _Constants.menuLayoutClass; + var layoutType = _Constants.appBarLayoutMenu; + + // + // Resize animation + // The resize animation requires 2 animations to run simultaneously in sync with each other. It's implemented + // without PVL because PVL doesn't provide a way to guarantee that 2 animations will start at the same time. + // + var transformNames = _BaseUtils._browserStyleEquivalents["transform"]; + function transformWithTransition(element, transition) { + // transition's properties: + // - duration: Number representing the duration of the animation in milliseconds. + // - timing: String representing the CSS timing function that controls the progress of the animation. + // - to: The value of *element*'s transform property after the animation. + var duration = transition.duration * _TransitionAnimation._animationFactor; + var transitionProperty = _BaseUtils._browserStyleEquivalents["transition"].scriptName; + element.style[transitionProperty] = duration + "ms " + transformNames.cssName + " " + transition.timing; + element.style[transformNames.scriptName] = transition.to; + + var finish; + return new Promise(function (c) { + var onTransitionEnd = function (eventObject) { + if (eventObject.target === element && eventObject.propertyName === transformNames.cssName) { + finish(); + } + }; + + var didFinish = false; + finish = function () { + if (!didFinish) { + _Global.clearTimeout(timeoutId); + element.removeEventListener(_BaseUtils._browserEventEquivalents["transitionEnd"], onTransitionEnd); + element.style[transitionProperty] = ""; + didFinish = true; + } + c(); + }; + + // Watch dog timeout + var timeoutId = _Global.setTimeout(function () { + timeoutId = _Global.setTimeout(finish, duration); + }, 50); + + element.addEventListener(_BaseUtils._browserEventEquivalents["transitionEnd"], onTransitionEnd); + }, function () { + finish(); // On cancelation, complete the promise successfully to match PVL + }); + } + // See resizeTransition's comment for documentation on *args*. + function growTransition(elementClipper, element, args) { + var diff = args.anchorTrailingEdge ? args.to.total - args.from.total : args.from.total - args.to.total; + var translate = args.dimension === "width" ? "translateX" : "translateY"; + var size = args.dimension; + var duration = args.duration || 367; + var timing = args.timing || "cubic-bezier(0.1, 0.9, 0.2, 1)"; + + // Set up + elementClipper.style[size] = args.to.total + "px"; + elementClipper.style[transformNames.scriptName] = translate + "(" + diff + "px)"; + element.style[size] = args.to.content + "px"; + element.style[transformNames.scriptName] = translate + "(" + -diff + "px)"; + + // Resolve styles + _Global.getComputedStyle(elementClipper).opacity; + _Global.getComputedStyle(element).opacity; + + // Animate + var transition = { + duration: duration, + timing: timing, + to: "" + }; + return Promise.join([ + transformWithTransition(elementClipper, transition), + transformWithTransition(element, transition) + ]); + } + // See resizeTransition's comment for documentation on *args*. + function shrinkTransition(elementClipper, element, args) { + var diff = args.anchorTrailingEdge ? args.from.total - args.to.total : args.to.total - args.from.total; + var translate = args.dimension === "width" ? "translateX" : "translateY"; + var duration = args.duration || 367; + var timing = args.timing || "cubic-bezier(0.1, 0.9, 0.2, 1)"; + + // Set up + elementClipper.style[transformNames.scriptName] = ""; + element.style[transformNames.scriptName] = ""; + + // Resolve styles + _Global.getComputedStyle(elementClipper).opacity; + _Global.getComputedStyle(element).opacity; + + // Animate + var transition = { + duration: duration, + timing: timing + }; + var clipperTransition = _BaseUtils._merge(transition, { to: translate + "(" + diff + "px)" }); + var elementTransition = _BaseUtils._merge(transition, { to: translate + "(" + -diff + "px)" }); + return Promise.join([ + transformWithTransition(elementClipper, clipperTransition), + transformWithTransition(element, elementTransition) + ]); + } + // Plays an animation which makes an element look like it is resizing in 1 dimension. Arguments: + // - elementClipper: The parent of *element*. It shouldn't have any margin, border, or padding and its + // size should match element's size. Its purpose is to clip *element* during the animation to give + // it the illusion that it is resizing. + // - element: The element that should look like it's resizing. + // - args: An object with the following required properties: + // - from: An object representing the old width/height of the element. + // - to: An object representing the new width/height of the element. + // from/to are objects of the form { content: number; total: number; }. "content" is the + // width/height of *element*'s content box (e.g. getContentWidth). "total" is the width/height + // of *element*'s margin box (e.g. getTotalWidth). + // - duration: The CSS transition duration property. + // - timing: The CSS transition timing property. + // - dimension: The dimension on which *element* is resizing. Either "width" or "height". + // - anchorTrailingEdge: During the resize animation, one edge will move and the other edge will + // remain where it is. This flag specifies which edge is anchored (i.e. won't move). + // + function resizeTransition(elementClipper, element, args) { + if (args.to.total > args.from.total) { + return growTransition(elementClipper, element, args); + } else if (args.to.total < args.from.total) { + return shrinkTransition(elementClipper, element, args); + } else { + return Promise.as(); + } + } + + var _AppBarMenuLayout = _Base.Class.derive(exports._AppBarBaseLayout, function _AppBarMenuLayout_ctor(appBarEl) { + exports._AppBarBaseLayout.call(this, appBarEl, { _className: layoutClassName, _type: layoutType }); + this._tranformNames = _BaseUtils._browserStyleEquivalents["transform"]; + this._animationCompleteBound = this._animationComplete.bind(this); + this._positionToolBarBound = this._positionToolBar.bind(this); + }, { + commandsInOrder: { + get: function _AppBarMenuLayout_get_commandsInOrder() { + return this._originalCommands; + } + }, + layout: function _AppBarMenuLayout_layout(commands) { + this._writeProfilerMark("layout,info"); + + commands = commands || []; + this._originalCommands = []; + + var that = this; + commands.forEach(function (command) { + that._originalCommands.push(that.sanitizeCommand(command)); + }); + this._displayedCommands = this._originalCommands.slice(0); + + if (this._menu) { + _ElementUtilities.empty(this._menu); + } else { + this._menu = _Global.document.createElement("div"); + _ElementUtilities.addClass(this._menu, _Constants.menuContainerClass); + } + this.appBarEl.appendChild(this._menu); + + this._toolbarEl = _Global.document.createElement("div"); + this._menu.appendChild(this._toolbarEl); + + this._createToolBar(commands); + }, + + showCommands: function _AppBarMenuLayout_showCommands(commands) { + var elements = this._getCommandsElements(commands); + var data = []; + var newDisplayedCommands = []; + var that = this; + this._originalCommands.forEach(function (command) { + if (elements.indexOf(command.element) >= 0 || that._displayedCommands.indexOf(command) >= 0) { + newDisplayedCommands.push(command); + data.push(command); + } + }); + this._displayedCommands = newDisplayedCommands; + this._updateData(data); + }, + + showOnlyCommands: function _AppBarMenuLayout_showOnlyCommands(commands) { + this._displayedCommands = []; + this.showCommands(commands); + }, + + hideCommands: function _AppBarMenuLayout_hideCommands(commands) { + var elements = this._getCommandsElements(commands); + var data = []; + var newDisplayedCommands = []; + var that = this; + this._originalCommands.forEach(function (command) { + if (elements.indexOf(command.element) === -1 && that._displayedCommands.indexOf(command) >= 0) { + newDisplayedCommands.push(command); + data.push(command); + } + }); + this._displayedCommands = newDisplayedCommands; + this._updateData(data); + }, + + connect: function _AppBarMenuLayout_connect(appBarEl) { + this._writeProfilerMark("connect,info"); + + exports._AppBarBaseLayout.prototype.connect.call(this, appBarEl); + this._id = _ElementUtilities._uniqueID(appBarEl); + }, + + resize: function _AppBarMenuLayout_resize() { + this._writeProfilerMark("resize,info"); + + if (this._initialized) { + this._forceLayoutPending = true; + } + }, + + positionChanging: function _AppBarMenuLayout_positionChanging(fromPosition, toPosition) { + this._writeProfilerMark("positionChanging from:" + fromPosition + " to: " + toPosition + ",info"); + + this._animationPromise = this._animationPromise || Promise.wrap(); + + if (this._animating) { + this._animationPromise.cancel(); + } + + this._animating = true; + if (toPosition === "shown" || (fromPosition !== "shown" && toPosition === "compact")) { + this._positionToolBar(); + this._animationPromise = this._animateToolBarEntrance(); + } else { + if (fromPosition === "minimal" || fromPosition === "compact" || fromPosition === "hidden") { + this._animationPromise = Promise.wrap(); + } else { + this._animationPromise = this._animateToolBarExit(); + } + } + this._animationPromise.then(this._animationCompleteBound, this._animationCompleteBound); + return this._animationPromise; + }, + + disposeChildren: function _AppBarMenuLayout_disposeChildren() { + this._writeProfilerMark("disposeChildren,info"); + + if (this._toolbar) { + _Dispose.disposeSubTree(this._toolbarEl); + } + this._originalCommands = []; + this._displayedCommands = []; + }, + + setFocusOnShow: function _AppBarMenuLayout_setFocusOnShow() { + // Make sure the menu (used for clipping during the resize animation) + // doesn't scroll when we give focus to the AppBar. + this.appBarEl.winControl._setFocusToAppBar(true, this._menu); + }, + + _updateData: function _AppBarMenuLayout_updateData(data) { + var hadHiddenClass = _ElementUtilities.hasClass(this.appBarEl, "win-navbar-closed"); + var hadShownClass = _ElementUtilities.hasClass(this.appBarEl, "win-navbar-opened"); + _ElementUtilities.removeClass(this.appBarEl, "win-navbar-closed"); + + // Make sure AppBar and children have width dimensions. + var prevAppBarDisplay = this.appBarEl.style.display; + this.appBarEl.style.display = ""; + + + this._toolbar.data = new BindingList.List(data); + if (hadHiddenClass) { + this._positionToolBar(); + } + + // Restore state to AppBar. + this.appBarEl.style.display = prevAppBarDisplay; + if (hadHiddenClass) { + _ElementUtilities.addClass(this.appBarEl, "win-navbar-closed"); + } + + if (hadShownClass) { + this._positionToolBar(); + this._animateToolBarEntrance(); + } + }, + + _getCommandsElements: function _AppBarMenuLayout_getCommandsElements(commands) { + if (!commands) { + return []; + } + + if (typeof commands === "string" || !commands || !commands.length) { + commands = [commands]; + } + + var elements = []; + for (var i = 0, len = commands.length; i < len; i++) { + if (commands[i]) { + if (typeof commands[i] === "string") { + var element = _Global.document.getElementById(commands[i]); + if (element) { + elements.push(element); + } else { + // Check in the list we are tracking, since it might not be in the DOM yet + for (var j = 0, len2 = this._originalCommands.length; j < len2; j++) { + var element = this._originalCommands[j].element; + if (element.id === commands[i]) { + elements.push(element); + } + } + } + } else if (commands[i].element) { + elements.push(commands[i].element); + } else { + elements.push(commands[i]); + } + } + } + + return elements; + }, + + _animationComplete: function _AppBarMenuLayout_animationComplete() { + if (!this._disposed) { + this._animating = false; + } + }, + + _createToolBar: function _AppBarMenuLayout_createToolBar(commands) { + this._writeProfilerMark("_createToolBar,info"); + + var hadHiddenClass = _ElementUtilities.hasClass(this.appBarEl, "win-navbar-closed"); + _ElementUtilities.removeClass(this.appBarEl, "win-navbar-closed"); + + // Make sure AppBar and children have width dimensions. + var prevAppBarDisplay = this.appBarEl.style.display; + this.appBarEl.style.display = ""; + + this._toolbar = new ToolBar.ToolBar(this._toolbarEl, { + data: new BindingList.List(this._originalCommands), + shownDisplayMode: 'full', + }); + + var that = this; + this._appbarInvokeButton = this.appBarEl.querySelector("." + _Constants.invokeButtonClass); + this._overflowButton = this._toolbarEl.querySelector("." + _ToolBarConstants.overflowButtonCssClass); + this._overflowButton.addEventListener("click", function () { + that._appbarInvokeButton.click(); + }); + + this._positionToolBar(); + + // Restore state to AppBar. + this.appBarEl.style.display = prevAppBarDisplay; + if (hadHiddenClass) { + _ElementUtilities.addClass(this.appBarEl, "win-navbar-closed"); + } + }, + + _positionToolBar: function _AppBarMenuLayout_positionToolBar() { + if (!this._disposed) { + this._writeProfilerMark("_positionToolBar,info"); + this._initialized = true; + } + }, + + _animateToolBarEntrance: function _AppBarMenuLayout_animateToolBarEntrance() { + this._writeProfilerMark("_animateToolBarEntrance,info"); + + if (this._forceLayoutPending) { + this._forceLayoutPending = false; + this._toolbar.forceLayout(); + this._positionToolBar(); + } + var heightVisible = this._isMinimal() ? 0 : this.appBarEl.offsetHeight; + if (this._isBottom()) { + // Bottom AppBar Animation + var offsetTop = this._menu.offsetHeight - heightVisible; + return this._executeTranslate(this._menu, "translateY(" + -offsetTop + "px)"); + } else { + // Top AppBar Animation + return resizeTransition(this._menu, this._toolbarEl, { + from: { content: heightVisible, total: heightVisible }, + to: { content: this._menu.offsetHeight, total: this._menu.offsetHeight }, + dimension: "height", + duration: 400, + timing: "ease-in", + }); + } + }, + + _animateToolBarExit: function _AppBarMenuLayout_animateToolBarExit() { + this._writeProfilerMark("_animateToolBarExit,info"); + + var heightVisible = this._isMinimal() ? 0 : this.appBarEl.offsetHeight; + if (this._isBottom()) { + return this._executeTranslate(this._menu, "none"); + } else { + // Top AppBar Animation + return resizeTransition(this._menu, this._toolbarEl, { + from: { content: this._menu.offsetHeight, total: this._menu.offsetHeight }, + to: { content: heightVisible, total: heightVisible }, + dimension: "height", + duration: 400, + timing: "ease-in", + }); + } + }, + + _executeTranslate: function _AppBarMenuLayout_executeTranslate(element, value) { + return _TransitionAnimation.executeTransition(element, + { + property: this._tranformNames.cssName, + delay: 0, + duration: 400, + timing: "ease-in", + to: value + }); + }, + + _isMinimal: function _AppBarMenuLayout_isMinimal() { + return this.appBarEl.winControl.closedDisplayMode === "minimal"; + }, + + _isBottom: function _AppBarMenuLayout_isBottom() { + return this.appBarEl.winControl.placement === "bottom"; + }, + + _writeProfilerMark: function _AppBarMenuLayout_writeProfilerMark(text) { + _WriteProfilerMark("WinJS.UI._AppBarMenuLayout:" + this._id + ":" + text); + } + }); + + return _AppBarMenuLayout; + }), + }); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +// _LegacyAppBar +/// appbar,appBars,Flyout,Flyouts,iframe,Statics,unfocus,WinJS +define('WinJS/Controls/_LegacyAppBar',[ + 'exports', + '../Core/_Global', + '../Core/_WinRT', + '../Core/_Base', + '../Core/_BaseUtils', + '../Core/_ErrorFromName', + '../Core/_Events', + '../Core/_Resources', + '../Core/_WriteProfilerMark', + '../Animations', + '../Promise', + '../Scheduler', + '../_LightDismissService', + '../Utilities/_Control', + '../Utilities/_Dispose', + '../Utilities/_ElementUtilities', + '../Utilities/_Hoverable', + '../Utilities/_KeyboardBehavior', + './_LegacyAppBar/_Constants', + './_LegacyAppBar/_Layouts', + './AppBar/_Command', + './AppBar/_Icon', + './Flyout/_Overlay', + '../Application' +], function appBarInit(exports, _Global, _WinRT, _Base, _BaseUtils, _ErrorFromName, _Events, _Resources, _WriteProfilerMark, Animations, Promise, Scheduler, _LightDismissService, _Control, _Dispose, _ElementUtilities, _Hoverable, _KeyboardBehavior, _Constants, _Layouts, _Command, _Icon, _Overlay, Application) { + "use strict"; + + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + /// + /// + /// Represents an application toolbar for display commands. + /// + /// + /// + /// + /// + /// + /// ]]> + /// Raised just before showing the _LegacyAppBar. + /// Raised immediately after the _LegacyAppBar is fully shown. + /// Raised just before hiding the _LegacyAppBar. + /// Raised immediately after the _LegacyAppBar is fully hidden. + /// The _LegacyAppBar control itself. + /// Style for a custom layout _LegacyAppBar. + /// + /// + _LegacyAppBar: _Base.Namespace._lazy(function () { + var EVENTS = { + beforeOpen: "beforeopen", + afterOpen: "afteropen", + beforeClose: "beforeclose", + afterClose: "afterclose", + }; + + var createEvent = _Events._createEventProperty; + + // Enum of known constant pixel values for display modes. + var knownVisibleHeights = { + none: 0, + hidden: 0, + minimal: 25, + compact: 48 + }; + + // Maps each notion of a display modes to the corresponding visible position + var displayModeVisiblePositions = { + none: "hidden", + hidden: "hidden", + minimal: "minimal", + shown: "shown", + compact: "compact" + }; + + // Enum of closedDisplayMode constants + var closedDisplayModes = { + none: "none", + minimal: "minimal", + compact: "compact" + }; + + // Constants shown/hidden states + var appbarShownState = "shown", + appbarHiddenState = "hidden"; + + // Hook into event + var globalEventsInitialized = false; + + function _allManipulationChanged(event) { + var elements = _Global.document.querySelectorAll("." + _Constants.appBarClass); + if (elements) { + var len = elements.length; + for (var i = 0; i < len; i++) { + var element = elements[i]; + var appbar = element.winControl; + if (appbar && !element.disabled) { + appbar._manipulationChanged(event); + } + } + } + } + + var strings = { + get ariaLabel() { return _Resources._getWinJSString("ui/appBarAriaLabel").value; }, + get requiresCommands() { return "Invalid argument: commands must not be empty"; }, + get cannotChangePlacementWhenVisible() { return "Invalid argument: The placement property cannot be set when the AppBar is visible, call hide() first"; }, + get cannotChangeLayoutWhenVisible() { return "Invalid argument: The layout property cannot be set when the AppBar is visible, call hide() first"; } + }; + + var _LegacyAppBar = _Base.Class.derive(_Overlay._Overlay, function _LegacyAppBar_ctor(element, options) { + /// + /// + /// Creates a new _LegacyAppBar control. + /// + /// + /// The DOM element that will host the control. + /// + /// + /// The set of properties and values to apply to the new _LegacyAppBar control. + /// + /// + /// The new _LegacyAppBar control. + /// + /// + + this._initializing = true; + + // Simplify checking later + options = options || {}; + + // Make sure there's an element + this._element = element || _Global.document.createElement("div"); + this._id = this._element.id || _ElementUtilities._uniqueID(this._element); + this._writeProfilerMark("constructor,StartTM"); + + // Attach our css class. + _ElementUtilities.addClass(this._element, _Constants.appBarClass); + + var that = this; + this._dismissable = new _LightDismissService.LightDismissableElement({ + element: this._element, + tabIndex: this._element.hasAttribute("tabIndex") ? this._element.tabIndex : -1, + onLightDismiss: function () { + that.close(); + }, + onTakeFocus: function (useSetActive) { + if (!that._dismissable.restoreFocus()) { + that._layoutImpl.setFocusOnShow(); + } + }, + }); + + // Make sure we have an ARIA role + var role = this._element.getAttribute("role"); + if (!role) { + this._element.setAttribute("role", "menubar"); + } + var label = this._element.getAttribute("aria-label"); + if (!label) { + this._element.setAttribute("aria-label", strings.ariaLabel); + } + + // Call the _Overlay constructor helper to finish setting up our element. + // Don't pass constructor options, _LegacyAppBar needs to set those itself specific order. + this._baseOverlayConstructor(this._element); + + // Start off hidden + this._lastPositionVisited = displayModeVisiblePositions.none; + _ElementUtilities.addClass(this._element, _Constants.hiddenClass); + + // Add Invoke button. + this._invokeButton = _Global.document.createElement("button"); + this._invokeButton.tabIndex = 0; + this._invokeButton.setAttribute("type", "button"); + this._invokeButton.innerHTML = ""; + _ElementUtilities.addClass(this._invokeButton, _Constants.invokeButtonClass); + this._element.appendChild(this._invokeButton); + this._invokeButton.addEventListener("click", function () { + if (that.opened) { + that._hide(); + } else { + that._show(); + } + }, false); + + // Run layout setter immediately. We need to know our layout in order to correctly + // position any commands that may be getting set through the constructor. + this._layout = _Constants.appBarLayoutCustom; + delete options._layout; + + // Need to set placement before closedDisplayMode, closedDisplayMode sets our starting position, which is dependant on placement. + this.placement = options.placement || _Constants.appBarPlacementBottom; + this.closedDisplayMode = options.closedDisplayMode || closedDisplayModes.compact; + + _Control.setOptions(this, options); + + var commandsUpdatedBound = this._commandsUpdated.bind(this); + this._element.addEventListener(_Constants.commandVisibilityChanged, function (ev) { + if (that._disposed) { + return; + } + if (that.opened) { + ev.preventDefault(); + } + commandsUpdatedBound(); + }); + + this._initializing = false; + + this._setFocusToAppBarBound = this._setFocusToAppBar.bind(this); + + // Handle key down (left & right) + this._element.addEventListener("keydown", this._handleKeyDown.bind(this), false); + + // Attach global event handlers + if (!globalEventsInitialized) { + // Need to know if the IHM is done scrolling + _Global.document.addEventListener("MSManipulationStateChanged", _allManipulationChanged, false); + + globalEventsInitialized = true; + } + + if (this.closedDisplayMode === closedDisplayModes.none && this.layout === _Constants.appBarLayoutCommands) { + // Remove the commands layout _LegacyAppBar from the layout tree at this point so we don't cause unnecessary layout costs whenever + // the window resizes or when CSS changes are applied to the commands layout _LegacyAppBar's parent element. + this._element.style.display = "none"; + } + + this._winKeyboard = new _KeyboardBehavior._WinKeyboard(this._element); + + this._writeProfilerMark("constructor,StopTM"); + + return this; + }, { + // Public Properties + + /// The placement of the _LegacyAppBar on the display. Values are "top" or "bottom". + placement: { + get: function _LegacyAppBar_get_placement() { + return this._placement; + }, + set: function _LegacyAppBar_set_placement(value) { + // In designer we may have to move it + var wasShown = false; + if (_WinRT.Windows.ApplicationModel.DesignMode.designModeEnabled) { + this._hide(); + wasShown = true; + } + + if (this.opened) { + throw new _ErrorFromName("WinJS.UI._LegacyAppBar.CannotChangePlacementWhenVisible", strings.cannotChangePlacementWhenVisible); + } + + // Set placement, coerce invalid values to 'bottom' + this._placement = (value === _Constants.appBarPlacementTop) ? _Constants.appBarPlacementTop : _Constants.appBarPlacementBottom; + + // Clean up win-top, win-bottom styles + if (this._placement === _Constants.appBarPlacementTop) { + _ElementUtilities.addClass(this._element, _Constants.topClass); + _ElementUtilities.removeClass(this._element, _Constants.bottomClass); + } else if (this._placement === _Constants.appBarPlacementBottom) { + _ElementUtilities.removeClass(this._element, _Constants.topClass); + _ElementUtilities.addClass(this._element, _Constants.bottomClass); + } + + // Update our position on screen. + this._ensurePosition(); + if (wasShown) { + // Show again if we hid ourselves for the designer + this._show(); + } + } + }, + + _layout: { + get: function _LegacyAppBar_get_layout() { + return this._layoutImpl.type; + }, + set: function (layout) { + if (layout !== _Constants.appBarLayoutCommands && + layout !== _Constants.appBarLayoutCustom && + layout !== _Constants.appBarLayoutMenu) { + } + + // In designer we may have to redraw it + var wasShown = false; + if (_WinRT.Windows.ApplicationModel.DesignMode.designModeEnabled) { + this._hide(); + wasShown = true; + } + + if (this.opened) { + throw new _ErrorFromName("WinJS.UI._LegacyAppBar.CannotChangeLayoutWhenVisible", strings.cannotChangeLayoutWhenVisible); + } + + var commands; + if (!this._initializing) { + // Gather commands in preparation for hand off to new layout. + // We expect prev layout to return commands in the order they were set in, + // not necessarily the current DOM order the layout is using. + commands = this._layoutImpl.commandsInOrder; + this._layoutImpl.disconnect(); + } + + // Set layout + if (layout === _Constants.appBarLayoutCommands) { + this._layoutImpl = new _Layouts._AppBarCommandsLayout(); + } else if (layout === _Constants.appBarLayoutMenu) { + this._layoutImpl = new _Layouts._AppBarMenuLayout(); + } else { + // Custom layout uses Base _LegacyAppBar Layout class. + this._layoutImpl = new _Layouts._AppBarBaseLayout(); + } + this._layoutImpl.connect(this._element); + + if (commands && commands.length) { + // Reset _LegacyAppBar since layout changed. + this._layoutCommands(commands); + } + + // Show again if we hid ourselves for the designer + if (wasShown) { + this._show(); + } + }, + configurable: true + }, + + /// + /// Sets the AppBarCommands in the _LegacyAppBar. This property accepts an array of AppBarCommand objects. + /// + commands: { + set: function _LegacyAppBar_set_commands(commands) { + // Fail if trying to set when shown + if (this.opened) { + throw new _ErrorFromName("WinJS.UI._LegacyAppBar.CannotChangeCommandsWhenVisible", _Resources._formatString(_Overlay._Overlay.commonstrings.cannotChangeCommandsWhenVisible, "_LegacyAppBar")); + } + + // Dispose old commands before tossing them out. + if (!this._initializing) { + // AppBarCommands defined in markup don't want to be disposed during initialization. + this._disposeChildren(); + } + this._layoutCommands(commands); + } + }, + + _layoutCommands: function _LegacyAppBar_layoutCommands(commands) { + // Function precondition: _LegacyAppBar must not be shown. + + // Empties _LegacyAppBar HTML and repopulates with passed in commands. + _ElementUtilities.empty(this._element); + this._element.appendChild(this._invokeButton); // Keep our Show/Hide button. + + // In case they had only one command to set... + if (!Array.isArray(commands)) { + commands = [commands]; + } + + this._layoutImpl.layout(commands); + }, + + /// + /// Gets/Sets how _LegacyAppBar will display itself while hidden. Values are "none", "minimal" and '"compact". + /// + closedDisplayMode: { + get: function _LegacyAppBar_get_closedDisplayMode() { + return this._closedDisplayMode; + }, + set: function _LegacyAppBar_set_closedDisplayMode(value) { + var oldValue = this._closedDisplayMode; + + if (oldValue !== value) { + + // Determine if the visible position is changing. This can be used to determine if we need to delay updating closedDisplayMode related CSS classes + // to avoid affecting the animation. + var changeVisiblePosition = _ElementUtilities.hasClass(this._element, _Constants.hiddenClass) || _ElementUtilities.hasClass(this._element, _Constants.hidingClass); + + if (value === closedDisplayModes.none) { + this._closedDisplayMode = closedDisplayModes.none; + if (!changeVisiblePosition || !oldValue) { + _ElementUtilities.removeClass(this._element, _Constants.minimalClass); + _ElementUtilities.removeClass(this._element, _Constants.compactClass); + } + } else if (value === closedDisplayModes.minimal) { + this._closedDisplayMode = closedDisplayModes.minimal; + if (!changeVisiblePosition || !oldValue || oldValue === closedDisplayModes.none) { + _ElementUtilities.addClass(this._element, _Constants.minimalClass); + _ElementUtilities.removeClass(this._element, _Constants.compactClass); + } + } else { + // Compact is default fallback. + this._closedDisplayMode = closedDisplayModes.compact; + _ElementUtilities.addClass(this._element, _Constants.compactClass); + _ElementUtilities.removeClass(this._element, _Constants.minimalClass); + } + + // The invoke button has changed the amount of available space in the _LegacyAppBar. Layout might need to scale. + this._layoutImpl.resize(); + + if (changeVisiblePosition) { + // If the value is being set while we are not showing, change to our new position. + this._changeVisiblePosition(displayModeVisiblePositions[this._closedDisplayMode]); + } + } + }, + }, + + /// + opened: { + get: function () { + // Returns true if _LegacyAppBar is not 'hidden'. + return !_ElementUtilities.hasClass(this._element, _Constants.hiddenClass) && + !_ElementUtilities.hasClass(this._element, _Constants.hidingClass) && + this._doNext !== displayModeVisiblePositions.minimal && + this._doNext !== displayModeVisiblePositions.compact && + this._doNext !== displayModeVisiblePositions.none; + }, + set: function (opened) { + var currentlyOpen = this.opened; + if (opened && !currentlyOpen) { + this._show(); + } else if (!opened && currentlyOpen) { + this._hide(); + } + } + }, + + /// + /// Occurs immediately before the control is opened. + /// + onbeforeopen: createEvent(EVENTS.beforeOpen), + + /// + /// Occurs immediately after the control is opened. + /// + onafteropen: createEvent(EVENTS.afterOpen), + + /// + /// Occurs immediately before the control is closed. + /// + onbeforeclose: createEvent(EVENTS.beforeClose), + + /// + /// Occurs immediately after the control is closed. + /// + onafterclose: createEvent(EVENTS.afterClose), + + getCommandById: function (id) { + /// + /// + /// Retrieves the command with the specified ID from this _LegacyAppBar. + /// If more than one command is found, this method returns them all. + /// + /// Id of the command to return. + /// + /// The command found, an array of commands if more than one have the same ID, or null if no command is found. + /// + /// + var commands = this._layoutImpl.commandsInOrder.filter(function (command) { + return command.id === id || command.element.id === id; + }); + + if (commands.length === 1) { + return commands[0]; + } else if (commands.length === 0) { + return null; + } + + return commands; + }, + + showCommands: function (commands) { + /// + /// + /// Show the specified commands of the _LegacyAppBar. + /// + /// + /// An array of the commands to show. The array elements may be AppBarCommand objects, or the string identifiers (IDs) of commands. + /// + /// + if (!commands) { + throw new _ErrorFromName("WinJS.UI._LegacyAppBar.RequiresCommands", strings.requiresCommands); + } + + this._layoutImpl.showCommands(commands); + }, + + hideCommands: function (commands) { + /// + /// + /// Hides the specified commands of the _LegacyAppBar. + /// + /// Required. Command or Commands to hide, either String, DOM elements, or WinJS objects. + /// + if (!commands) { + throw new _ErrorFromName("WinJS.UI._LegacyAppBar.RequiresCommands", strings.requiresCommands); + } + + this._layoutImpl.hideCommands(commands); + }, + + showOnlyCommands: function (commands) { + /// + /// + /// Show the specified commands, hiding all of the others in the _LegacyAppBar. + /// + /// + /// An array of the commands to show. The array elements may be AppBarCommand objects, or the string identifiers (IDs) of commands. + /// + /// + if (!commands) { + throw new _ErrorFromName("WinJS.UI._LegacyAppBar.RequiresCommands", strings.requiresCommands); + } + + this._layoutImpl.showOnlyCommands(commands); + }, + + open: function () { + /// + /// + /// Opens the _LegacyAppBar, if closed and not disabled, regardless of other state. + /// + /// + // Just wrap the private one, turning off keyboard invoked flag + this._writeProfilerMark("show,StartTM"); + this._show(); + }, + + _show: function _LegacyAppBar_show() { + + var toPosition = displayModeVisiblePositions.shown; + var showing = null; + + // If we're already shown, we are just going to animate our position, not fire events or manage focus. + if (!this.disabled && (_ElementUtilities.hasClass(this._element, _Constants.hiddenClass) || _ElementUtilities.hasClass(this._element, _Constants.hidingClass))) { + showing = appbarShownState; + } + + this._changeVisiblePosition(toPosition, showing); + + if (showing) { + // Clean up tabbing behavior by making sure first and final divs are correct after showing. + this._updateFirstAndFinalDiv(); + + _LightDismissService.shown(this._dismissable); + } + }, + + close: function () { + /// + /// + /// Closes the _LegacyAppBar. + /// + /// + // Just wrap the private one + this._writeProfilerMark("hide,StartTM"); + this._hide(); + }, + + _hide: function _LegacyAppBar_hide(toPosition) { + + var toPosition = toPosition || displayModeVisiblePositions[this.closedDisplayMode]; + var hiding = null; + + // If were already hidden, we are just going to animate our position, not fire events or manage focus again. + if (!_ElementUtilities.hasClass(this._element, _Constants.hiddenClass) && !_ElementUtilities.hasClass(this._element, _Constants.hidingClass)) { + hiding = appbarHiddenState; + } + + this._changeVisiblePosition(toPosition, hiding); + }, + + _dispose: function _LegacyAppBar_dispose() { + _Dispose.disposeSubTree(this.element); + _LightDismissService.hidden(this._dismissable); + this._layoutImpl.dispose(); + this.disabled = true; + this.close(); + }, + + _disposeChildren: function _LegacyAppBar_disposeChildren() { + // Be purposeful about what we dispose. + this._layoutImpl.disposeChildren(); + }, + + _handleKeyDown: function _LegacyAppBar_handleKeyDown(event) { + // On Left/Right arrow keys, moves focus to previous/next AppbarCommand element. + + // If the current active element isn't an intrinsic part of the _LegacyAppBar, + // Layout might want to handle additional keys. + if (!this._invokeButton.contains(_Global.document.activeElement)) { + this._layoutImpl.handleKeyDown(event); + } + }, + + _visiblePixels: { + get: function () { + // Returns object containing pixel height of each visible position + return { + hidden: knownVisibleHeights.hidden, + minimal: knownVisibleHeights.minimal, + compact: Math.max(this._heightWithoutLabels || 0, knownVisibleHeights.compact), + // Element can change size as content gets added or removed or if it + // experinces style changes. We have to look this up at run time. + shown: this._element.offsetHeight, + }; + } + }, + + _visiblePosition: { + // Returns string value of our nearest, stationary, visible position. + get: function () { + // If we're animating into a new posistion, return the position we're animating into. + if (this._animating && displayModeVisiblePositions[this._element.winAnimating]) { + return this._element.winAnimating; + } else { + return this._lastPositionVisited; + } + } + }, + + _visible: { + // Returns true if our visible position is not completely hidden, else false. + get: function () { + return (this._visiblePosition !== displayModeVisiblePositions.none); + } + }, + + _changeVisiblePosition: function (toPosition, newState) { + /// + /// + /// Changes the visible position of the _LegacyAppBar. + /// + /// + /// Name of the visible position we want to move to. + /// + /// + /// Name of the state we are entering. Values can be "showing", "hiding" or null. + /// If the value is null, then we are not changing states, only changing visible position. + /// + /// + + if ((this._visiblePosition === toPosition && !this._keyboardObscured) || + (this.disabled && toPosition !== displayModeVisiblePositions.disabled)) { + // If we want to go where we already are, or we're disabled, return false. + this._afterPositionChange(null); + } else if (this._animating || this._needToHandleShowingKeyboard || this._needToHandleHidingKeyboard) { + // Only do one thing at a time. If we are already animating, + // or the IHM is animating, schedule this for later. + this._doNext = toPosition; + this._afterPositionChange(null); + } else { + // Begin position changing sequence. + + // Set the animating flag to block any queued position changes until we're done. + this._element.winAnimating = toPosition; + var performAnimation = this._initializing ? false : true; + + // Assume we are animating from the last position visited. + var fromPosition = this._lastPositionVisited; + + // We'll need to measure our element to determine how far we need to animate. + // Make sure we have accurate dimensions. + this._element.style.display = ""; + + // Are we hiding completely, or about to become visible? + var hidingCompletely = (toPosition === displayModeVisiblePositions.hidden); + + if (this._keyboardObscured) { + // We're changing position while covered by the IHM. + if (hidingCompletely) { + // If we're covered by the IHM we already look hidden. + // We can skip our animation and just hide. + performAnimation = false; + } else { + // Some portion of the _LegacyAppBar should be visible to users after its position changes. + + // Un-obscure ourselves and become visible to the user again. + // Need to animate to our desired position as if we were coming up from behind the keyboard. + fromPosition = displayModeVisiblePositions.hidden; + } + this._keyboardObscured = false; + } + + // Fire "before" event if we are changing state. + if (newState === appbarShownState) { + this._beforeShow(); + } else if (newState === appbarHiddenState) { + this._beforeHide(); + } + + // Position our element into the correct "end of animation" position, + // also accounting for any viewport scrolling or soft keyboard positioning. + this._ensurePosition(); + + this._element.style.opacity = 1; + this._element.style.visibility = "visible"; + + this._animationPromise = (performAnimation) ? this._animatePositionChange(fromPosition, toPosition) : Promise.wrap(); + this._animationPromise.then( + function () { this._afterPositionChange(toPosition, newState); }.bind(this), + function () { this._afterPositionChange(toPosition, newState); }.bind(this) + ); + } + }, + + _afterPositionChange: function _LegacyAppBar_afterPositionChange(newPosition, newState) { + // Defines body of work to perform after changing positions. + if (this._disposed) { + return; + } + + if (newPosition) { + + // Update closedDisplayMode related CSS classes, which were delayed from the closedDisplayMode setter to avoid affecting the animation + if (newPosition === displayModeVisiblePositions.minimal) { + _ElementUtilities.addClass(this._element, _Constants.minimalClass); + _ElementUtilities.removeClass(this._element, _Constants.compactClass); + } + + if (newPosition === displayModeVisiblePositions.hidden && this.closedDisplayMode === closedDisplayModes.none) { + _ElementUtilities.removeClass(this._element, _Constants.minimalClass); + _ElementUtilities.removeClass(this._element, _Constants.compactClass); + } + + // Clear animation flag and record having visited this position. + this._element.winAnimating = ""; + this._lastPositionVisited = newPosition; + + if (this._doNext === this._lastPositionVisited) { + this._doNext = ""; + } + + if (newState === appbarHiddenState) { + _LightDismissService.hidden(this._dismissable); + } + + if (newPosition === displayModeVisiblePositions.hidden) { + // Make sure animation is finished. + this._element.style.visibility = "hidden"; + this._element.style.display = "none"; + } + + // Clean up animation transforms. + var transformProperty = _BaseUtils._browserStyleEquivalents["transform"].scriptName; + this._element.style[transformProperty] = ""; + + // Fire "after" event if we changed state. + if (newState === appbarShownState) { + this._afterShow(); + } else if (newState === appbarHiddenState) { + this._afterHide(); + } + + // If we had something queued, do that + Scheduler.schedule(this._checkDoNext, Scheduler.Priority.normal, this, "WinJS.UI._LegacyAppBar._checkDoNext"); + } + + this._afterPositionChangeCallBack(); + }, + + _afterPositionChangeCallBack: function () { + // Leave this blank for unit tests to overwrite. + }, + + _beforeShow: function _LegacyAppBar_beforeShow() { + // In case their event 'beforeopen' event listener is going to manipulate commands, + // first see if there are any queued command animations we can handle while we're still hidden. + if (this._queuedCommandAnimation) { + this._showAndHideFast(this._queuedToShow, this._queuedToHide); + this._queuedToShow = []; + this._queuedToHide = []; + } + + // Make sure everything fits before showing + this._layoutImpl.scale(); + + if (this.closedDisplayMode === closedDisplayModes.compact) { + this._heightWithoutLabels = this._element.offsetHeight; + } + + _ElementUtilities.removeClass(this._element, _Constants.hiddenClass); + _ElementUtilities.addClass(this._element, _Constants.showingClass); + + // Send our "beforeopen" event + this._sendEvent(EVENTS.beforeOpen); + }, + + _afterShow: function _LegacyAppBar_afterShow() { + _ElementUtilities.removeClass(this._element, _Constants.showingClass); + _ElementUtilities.addClass(this._element, _Constants.shownClass); + + // Send our "afteropen" event + this._sendEvent(EVENTS.afterOpen); + this._writeProfilerMark("show,StopTM"); + }, + + _beforeHide: function _LegacyAppBar_beforeHide() { + + _ElementUtilities.removeClass(this._element, _Constants.shownClass); + _ElementUtilities.addClass(this._element, _Constants.hidingClass); + + // Send our "beforeclose" event + this._sendEvent(EVENTS.beforeClose); + }, + + _afterHide: function _LegacyAppBar_afterHide() { + + // In case their 'afterclose' event handler is going to manipulate commands, + // first see if there are any queued command animations we can handle now we're hidden. + if (this._queuedCommandAnimation) { + this._showAndHideFast(this._queuedToShow, this._queuedToHide); + this._queuedToShow = []; + this._queuedToHide = []; + } + + _ElementUtilities.removeClass(this._element, _Constants.hidingClass); + _ElementUtilities.addClass(this._element, _Constants.hiddenClass); + + // Send our "afterclose" event + this._sendEvent(EVENTS.afterClose); + this._writeProfilerMark("hide,StopTM"); + }, + + _animatePositionChange: function _LegacyAppBar_animatePositionChange(fromPosition, toPosition) { + // Determines and executes the proper transition between visible positions + + var layoutElementsAnimationPromise = this._layoutImpl.positionChanging(fromPosition, toPosition), + appBarElementAnimationPromise; + + // Get values in terms of pixels to perform animation. + var beginningVisiblePixelHeight = this._visiblePixels[fromPosition], + endingVisiblePixelHeight = this._visiblePixels[toPosition], + distance = Math.abs(endingVisiblePixelHeight - beginningVisiblePixelHeight), + offsetTop = (this._placement === _Constants.appBarPlacementTop) ? -distance : distance; + + if ((this._placement === _Constants.appBarPlacementTop) && + ((fromPosition === displayModeVisiblePositions.shown && + toPosition === displayModeVisiblePositions.compact) || + (fromPosition === displayModeVisiblePositions.compact && + toPosition === displayModeVisiblePositions.shown))) { + // Command icons remain in the same location on a top appbar + // when going from compact > shown or shown > compact. + offsetTop = 0; + } + + // Animate + if (endingVisiblePixelHeight > beginningVisiblePixelHeight) { + var fromOffset = { top: offsetTop + "px", left: "0px" }; + appBarElementAnimationPromise = Animations.showEdgeUI(this._element, fromOffset, { mechanism: "transition" }); + } else { + var toOffset = { top: offsetTop + "px", left: "0px" }; + appBarElementAnimationPromise = Animations.hideEdgeUI(this._element, toOffset, { mechanism: "transition" }); + } + + return Promise.join([layoutElementsAnimationPromise, appBarElementAnimationPromise]); + }, + + _checkDoNext: function _LegacyAppBar_checkDoNext() { + // Do nothing if we're still animating + if (this._animating || this._needToHandleShowingKeyboard || this._needToHandleHidingKeyboard || this._disposed) { + return; + } + + if (this._doNext === displayModeVisiblePositions.disabled || + this._doNext === displayModeVisiblePositions.hidden || + this._doNext === displayModeVisiblePositions.minimal || + this._doNext === displayModeVisiblePositions.compact) { + // Do hide first because animating commands would be easier + this._hide(this._doNext); + this._doNext = ""; + } else if (this._queuedCommandAnimation) { + // Do queued commands before showing if possible + this._showAndHideQueue(); + } else if (this._doNext === displayModeVisiblePositions.shown) { + // Show last so that we don't unnecessarily animate commands + this._show(); + this._doNext = ""; + } + }, + + // Set focus to the passed in _LegacyAppBar + _setFocusToAppBar: function _LegacyAppBar_setFocusToAppBar(useSetActive, scroller) { + if (!this._focusOnFirstFocusableElement(useSetActive, scroller)) { + // No first element, set it to appbar itself + _Overlay._Overlay._trySetActive(this._element, scroller); + } + }, + + _commandsUpdated: function _LegacyAppBar_commandsUpdated() { + // If we are still initializing then we don't have a layout yet so it doesn't need updating. + if (!this._initializing) { + this._layoutImpl.commandsUpdated(); + this._layoutImpl.scale(); + } + }, + + _beginAnimateCommands: function _LegacyAppBar_beginAnimateCommands(showCommands, hideCommands, otherVisibleCommands) { + // The parameters are 3 mutually exclusive arrays of win-command elements contained in this Overlay. + // 1) showCommands[]: All of the HIDDEN win-command elements that ARE scheduled to show. + // 2) hideCommands[]: All of the VISIBLE win-command elements that ARE scheduled to hide. + // 3) otherVisibleCommands[]: All VISIBLE win-command elements that ARE NOT scheduled to hide. + this._layoutImpl.beginAnimateCommands(showCommands, hideCommands, otherVisibleCommands); + }, + + _endAnimateCommands: function _LegacyAppBar_endAnimateCommands() { + this._layoutImpl.endAnimateCommands(); + this._endAnimateCommandsCallBack(); + }, + + _endAnimateCommandsCallBack: function _LegacyAppBar_endAnimateCommandsCallBack() { + // Leave this blank for unit tests to overwrite. + }, + + // Get the top offset for top appbars. + _getTopOfVisualViewport: function _LegacyAppBar_getTopOfVisualViewPort() { + return _Overlay._Overlay._keyboardInfo._visibleDocTop; + }, + + // Get the bottom offset for bottom appbars. + _getAdjustedBottom: function _LegacyAppBar_getAdjustedBottom() { + // Need the distance the IHM moved as well. + return _Overlay._Overlay._keyboardInfo._visibleDocBottomOffset; + }, + + _showingKeyboard: function _LegacyAppBar_showingKeyboard(event) { + // Remember keyboard showing state. + this._keyboardObscured = false; + this._needToHandleHidingKeyboard = false; + + // If we're already moved, then ignore the whole thing + if (_Overlay._Overlay._keyboardInfo._visible && this._alreadyInPlace()) { + return; + } + + this._needToHandleShowingKeyboard = true; + // If focus is in the appbar, don't cause scrolling. + if (this.opened && this._element.contains(_Global.document.activeElement)) { + event.ensuredFocusedElementInView = true; + } + + // Check if appbar moves or if we're ok leaving it obscured instead. + if (this._visible && this._placement !== _Constants.appBarPlacementTop && _Overlay._Overlay._isFlyoutVisible()) { + // Remember that we're obscured + this._keyboardObscured = true; + } else { + // Don't be obscured, clear _scrollHappened flag to give us inference later on when to re-show ourselves. + this._scrollHappened = false; + } + + // Also set timeout regardless, so we can clean up our _keyboardShowing flag. + var that = this; + _Global.setTimeout(function (e) { that._checkKeyboardTimer(e); }, _Overlay._Overlay._keyboardInfo._animationShowLength + _Overlay._Overlay._scrollTimeout); + }, + + _hidingKeyboard: function _LegacyAppBar_hidingKeyboard() { + // We'll either just reveal the current space under the IHM or restore the window height. + + // We won't be obscured + this._keyboardObscured = false; + this._needToHandleShowingKeyboard = false; + this._needToHandleHidingKeyboard = true; + + // We'll either just reveal the current space or resize the window + if (!_Overlay._Overlay._keyboardInfo._isResized) { + // If we're not completely hidden, only fake hiding under keyboard, or already animating, + // then snap us to our final position. + if (this._visible || this._animating) { + // Not resized, update our final position immediately + this._checkScrollPosition(); + this._element.style.display = ""; + } + this._needToHandleHidingKeyboard = false; + } + // Else resize should clear keyboardHiding. + }, + + _resize: function _LegacyAppBar_resize(event) { + // If we're hidden by the keyboard, then hide bottom appbar so it doesn't pop up twice when it scrolls + if (this._needToHandleShowingKeyboard) { + // Top is allowed to scroll off the top, but we don't want bottom to peek up when + // scrolled into view since we'll show it ourselves and don't want a stutter effect. + if (this._visible) { + if (this._placement !== _Constants.appBarPlacementTop && !this._keyboardObscured) { + // If viewport doesn't match window, need to vanish momentarily so it doesn't scroll into view, + // however we don't want to toggle the visibility="hidden" hidden flag. + this._element.style.display = "none"; + } + } + // else if we're top we stay, and if there's a flyout, stay obscured by the keyboard. + } else if (this._needToHandleHidingKeyboard) { + this._needToHandleHidingKeyboard = false; + if (this._visible || this._animating) { + // Snap to final position + this._checkScrollPosition(); + this._element.style.display = ""; + } + } + + // Make sure everything still fits. + if (!this._initializing) { + this._layoutImpl.resize(event); + } + }, + + _checkKeyboardTimer: function _LegacyAppBar_checkKeyboardTimer() { + if (!this._scrollHappened) { + this._mayEdgeBackIn(); + } + }, + + _manipulationChanged: function _LegacyAppBar_manipulationChanged(event) { + // See if we're at the not manipulating state, and we had a scroll happen, + // which is implicitly after the keyboard animated. + if (event.currentState === 0 && this._scrollHappened) { + this._mayEdgeBackIn(); + } + }, + + _mayEdgeBackIn: function _LegacyAppBar_mayEdgeBackIn() { + // May need to react to IHM being resized event + if (this._needToHandleShowingKeyboard) { + // If not top appbar or viewport isn't still at top, then need to show again + this._needToHandleShowingKeyboard = false; + // If obscured (IHM + flyout showing), it's ok to stay obscured. + // If bottom we have to move, or if top scrolled off screen. + if (!this._keyboardObscured && + (this._placement !== _Constants.appBarPlacementTop || _Overlay._Overlay._keyboardInfo._visibleDocTop !== 0)) { + var toPosition = this._visiblePosition; + this._lastPositionVisited = displayModeVisiblePositions.hidden; + this._changeVisiblePosition(toPosition, false); + } else { + // Ensure any animations dropped during the showing keyboard are caught up. + this._checkDoNext(); + } + } + this._scrollHappened = false; + }, + + _ensurePosition: function _LegacyAppBar_ensurePosition() { + // Position the _LegacyAppBar element relative to the top or bottom edge of the visible + // document, based on the the visible position we think we need to be in. + var offSet = this._computePositionOffset(); + this._element.style.bottom = offSet.bottom; + this._element.style.top = offSet.top; + + }, + + _computePositionOffset: function _LegacyAppBar_computePositionOffset() { + // Calculates and returns top and bottom offsets for the _LegacyAppBar element, relative to the top or bottom edge of the visible + // document. + var positionOffSet = {}; + + if (this._placement === _Constants.appBarPlacementBottom) { + // If the IHM is open, the bottom of the visual viewport may or may not be obscured + // Use _getAdjustedBottom to account for the IHM if it is covering the bottom edge. + positionOffSet.bottom = this._getAdjustedBottom() + "px"; + positionOffSet.top = ""; + } else if (this._placement === _Constants.appBarPlacementTop) { + positionOffSet.bottom = ""; + positionOffSet.top = this._getTopOfVisualViewport() + "px"; + } + + return positionOffSet; + }, + + _checkScrollPosition: function _LegacyAppBar_checkScrollPosition() { + // If IHM has appeared, then remember we may come in + if (this._needToHandleShowingKeyboard) { + // Tag that it's OK to edge back in. + this._scrollHappened = true; + return; + } + + // We only need to update if we're not completely hidden. + if (this._visible || this._animating) { + this._ensurePosition(); + // Ensure any animations dropped during the showing keyboard are caught up. + this._checkDoNext(); + } + }, + + _alreadyInPlace: function _LegacyAppBar_alreadyInPlace() { + // See if we're already where we're supposed to be. + var offSet = this._computePositionOffset(); + return (offSet.top === this._element.style.top && offSet.bottom === this._element.style.bottom); + }, + + // If there is a shown non-sticky _LegacyAppBar then it sets the firstDiv tabIndex to + // the minimum tabIndex found in the _LegacyAppBars and finalDiv to the max found. + // Otherwise sets their tabIndex to -1 so they are not tab stops. + _updateFirstAndFinalDiv: function _LegacyAppBar_updateFirstAndFinalDiv() { + var appBarFirstDiv = this._element.querySelectorAll("." + _Constants.firstDivClass); + appBarFirstDiv = appBarFirstDiv.length >= 1 ? appBarFirstDiv[0] : null; + + var appBarFinalDiv = this._element.querySelectorAll("." + _Constants.finalDivClass); + appBarFinalDiv = appBarFinalDiv.length >= 1 ? appBarFinalDiv[0] : null; + + // Remove the firstDiv & finalDiv if they are not at the appropriate locations + if (appBarFirstDiv && (this._element.children[0] !== appBarFirstDiv)) { + appBarFirstDiv.parentNode.removeChild(appBarFirstDiv); + appBarFirstDiv = null; + } + if (appBarFinalDiv && (this._element.children[this._element.children.length - 1] !== appBarFinalDiv)) { + appBarFinalDiv.parentNode.removeChild(appBarFinalDiv); + appBarFinalDiv = null; + } + + // Create and add the firstDiv & finalDiv if they don't already exist + if (!appBarFirstDiv) { + // Add a firstDiv that will be the first child of the appBar. + // On focus set focus to the last element of the AppBar. + appBarFirstDiv = _Global.document.createElement("div"); + // display: inline is needed so that the div doesn't take up space and cause the page to scroll on focus + appBarFirstDiv.style.display = "inline"; + appBarFirstDiv.className = _Constants.firstDivClass; + appBarFirstDiv.tabIndex = -1; + appBarFirstDiv.setAttribute("aria-hidden", "true"); + _ElementUtilities._addEventListener(appBarFirstDiv, "focusin", this._focusOnLastFocusableElementOrThis.bind(this), false); + // add to beginning + if (this._element.children[0]) { + this._element.insertBefore(appBarFirstDiv, this._element.children[0]); + } else { + this._element.appendChild(appBarFirstDiv); + } + } + if (!appBarFinalDiv) { + // Add a finalDiv that will be the last child of the appBar. + // On focus set focus to the first element of the AppBar. + appBarFinalDiv = _Global.document.createElement("div"); + // display: inline is needed so that the div doesn't take up space and cause the page to scroll on focus + appBarFinalDiv.style.display = "inline"; + appBarFinalDiv.className = _Constants.finalDivClass; + appBarFinalDiv.tabIndex = -1; + appBarFinalDiv.setAttribute("aria-hidden", "true"); + _ElementUtilities._addEventListener(appBarFinalDiv, "focusin", this._focusOnFirstFocusableElementOrThis.bind(this), false); + this._element.appendChild(appBarFinalDiv); + } + + + // invokeButton should be the second to last element in the _LegacyAppBar's tab order. Second to the finalDiv. + if (this._element.children[this._element.children.length - 2] !== this._invokeButton) { + this._element.insertBefore(this._invokeButton, appBarFinalDiv); + } + var elms = this._element.getElementsByTagName("*"); + var highestTabIndex = _ElementUtilities._getHighestTabIndexInList(elms); + this._invokeButton.tabIndex = highestTabIndex; + + // Update the tabIndex of the firstDiv & finalDiv + if (appBarFirstDiv) { + appBarFirstDiv.tabIndex = _ElementUtilities._getLowestTabIndexInList(elms); + } + if (appBarFinalDiv) { + appBarFinalDiv.tabIndex = highestTabIndex; + } + }, + + _writeProfilerMark: function _LegacyAppBar_writeProfilerMark(text) { + _WriteProfilerMark("WinJS.UI._LegacyAppBar:" + this._id + ":" + text); + } + }, { + // Statics + _Events: EVENTS, + }); + + return _LegacyAppBar; + }) + }); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +// Menu +/// Menu,Menus,Flyout,Flyouts,Statics +define('WinJS/Controls/Menu',[ + 'exports', + '../Core/_Global', + '../Core/_Base', + '../Core/_BaseUtils', + '../Core/_ErrorFromName', + '../Core/_Resources', + '../Core/_WriteProfilerMark', + '../Promise', + '../Utilities/_ElementUtilities', + '../Utilities/_Hoverable', + '../Utilities/_KeyboardBehavior', + './_LegacyAppBar/_Constants', + './Flyout', + './Flyout/_Overlay', + './Menu/_Command' +], function menuInit(exports, _Global, _Base, _BaseUtils, _ErrorFromName, _Resources, _WriteProfilerMark, Promise, _ElementUtilities, _Hoverable, _KeyboardBehavior, _Constants, Flyout, _Overlay, _Command) { + "use strict"; + + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + /// + /// Represents a menu flyout for displaying commands. + /// + /// + /// Menu + /// + /// + /// + /// + /// ]]> + /// Raised just before showing a menu. + /// Raised immediately after a menu is fully shown. + /// Raised just before hiding a menu. + /// Raised immediately after a menu is fully hidden. + /// The Menu control itself + /// + /// + Menu: _Base.Namespace._lazy(function () { + var Key = _ElementUtilities.Key; + + var strings = { + get ariaLabel() { return _Resources._getWinJSString("ui/menuAriaLabel").value; }, + get requiresCommands() { return "Invalid argument: commands must not be empty"; }, + get nullCommand() { return "Invalid argument: command must not be null"; }, + }; + + function isCommandInMenu(object) { + // Verifies that we have a menuCommand element and that it is in a Menu. + var element = object.element || object; + return _ElementUtilities._matchesSelector(element, "." + _Constants.menuClass + " " + "." + _Constants.menuCommandClass); + } + + var Menu = _Base.Class.derive(Flyout.Flyout, function Menu_ctor(element, options) { + /// + /// + /// Creates a new Menu control. + /// + /// + /// The DOM element that will host the control. + /// + /// + /// The set of properties and values to apply to the control. + /// + /// The new Menu control. + /// + /// + + // We need to be built on top of a Flyout, so stomp on the user's input + options = options || {}; + + // Make sure there's an input element + this._element = element || _Global.document.createElement("div"); + this._id = this._element.id || _ElementUtilities._uniqueID(this._element); + this._writeProfilerMark("constructor,StartTM"); + + // validate that if they didn't set commands, in which + // case any HTML only contains commands. Do this first + // so that we don't leave partial Menus in the DOM. + if (!options.commands && this._element) { + // Shallow copy object so we can modify it. + options = _BaseUtils._shallowCopy(options); + options.commands = this._verifyCommandsOnly(this._element, "WinJS.UI.MenuCommand"); + } + + // Remember aria role in case base constructor changes it + var role = this._element ? this._element.getAttribute("role") : null; + var label = this._element ? this._element.getAttribute("aria-label") : null; + + // Call the base overlay constructor helper + this._baseFlyoutConstructor(this._element, options); + + // Make sure we have an ARIA role + if (role === null || role === "" || role === undefined) { + this._element.setAttribute("role", "menu"); + } + if (label === null || label === "" || label === undefined) { + this._element.setAttribute("aria-label", strings.ariaLabel); + } + + // Handle "esc" & "up/down" key presses + this._element.addEventListener("keydown", this._handleKeyDown.bind(this), true); + this._element.addEventListener(_Constants._menuCommandInvokedEvent, this._handleCommandInvoked.bind(this), false); + this._element.addEventListener("mouseover", this._handleMouseOver.bind(this), false); + this._element.addEventListener("mouseout", this._handleMouseOut.bind(this), false); + + // Attach our css class + _ElementUtilities.addClass(this._element, _Constants.menuClass); + + this._winKeyboard = new _KeyboardBehavior._WinKeyboard(this._element); + + // Need to set our commands, making sure we're hidden first + this.hide(); + this._writeProfilerMark("constructor,StopTM"); + }, { + // Public Properties + + /// + /// Sets the MenuCommand objects that appear in the Menu. You can set this to a single MenuCommand or an array of MenuCommand objects. + /// + /// + commands: { + set: function (value) { + // Fail if trying to set when visible + if (!this.hidden) { + throw new _ErrorFromName("WinJS.UI.Menu.CannotChangeCommandsWhenVisible", _Resources._formatString(_Overlay._Overlay.commonstrings.cannotChangeCommandsWhenVisible, "Menu")); + } + + // Start from scratch + _ElementUtilities.empty(this._element); + + // In case they had only one... + if (!Array.isArray(value)) { + value = [value]; + } + + // Add commands + var len = value.length; + for (var i = 0; i < len; i++) { + this._addCommand(value[i]); + } + } + }, + + getCommandById: function (id) { + /// + /// + /// Retrieve the command with the specified ID from this Menu. If more than one command is found, all are returned. + /// + /// The ID of the command to find. + /// + /// The command found, an array of commands if more than one have the same ID, or null if no command is found. + /// + /// + /// + var commands = this.element.querySelectorAll("#" + id); + var newCommands = []; + for (var count = 0, len = commands.length; count < len; count++) { + if (commands[count].winControl) { + newCommands.push(commands[count].winControl); + } + } + + if (newCommands.length === 1) { + return newCommands[0]; + } else if (newCommands.length === 0) { + return null; + } + + return newCommands; + }, + + + showCommands: function (commands) { + /// + /// + /// Shows the specified commands of the Menu. + /// + /// + /// The commands to show. The array elements may be Menu objects, or the string identifiers (IDs) of commands. + /// + /// + /// + if (!commands) { + throw new _ErrorFromName("WinJS.UI.Menu.RequiresCommands", strings.requiresCommands); + } + + this._showCommands(commands, true); + }, + + hideCommands: function (commands) { + /// + /// + /// Hides the Menu. + /// + /// + /// Required. Command or Commands to hide, either String, DOM elements, or WinJS objects. + /// + /// + /// + if (!commands) { + throw new _ErrorFromName("WinJS.UI.Menu.RequiresCommands", strings.requiresCommands); + } + + this._hideCommands(commands, true); + }, + + showOnlyCommands: function (commands) { + /// + /// + /// Shows the specified commands of the Menu while hiding all other commands. + /// + /// + /// The commands to show. The array elements may be MenuCommand objects, or the string identifiers (IDs) of commands. + /// + /// + /// + if (!commands) { + throw new _ErrorFromName("WinJS.UI.Menu.RequiresCommands", strings.requiresCommands); + } + + this._showOnlyCommands(commands, true); + }, + + show: function (anchor, placement, alignment) { + /// + /// + /// Shows the Menu, if hidden, regardless of other states. + /// + /// + /// The DOM element, or ID of a DOM element, to anchor the Menu. This parameter overrides the anchor property for this method call only. + /// + /// + /// The placement of the Menu to the anchor: 'auto' (default), 'autohorizontal', 'autovertical', 'top', 'bottom', 'left', or 'right'. This parameter overrides the placement + /// property for this method call only. + /// + /// + /// For 'top' or 'bottom' placement, the alignment of the Menu to the anchor's edge: 'center' (default), 'left', or 'right'. This parameter + /// overrides the alignment property for this method call only. + /// + /// + /// + // Just call private version to make appbar flags happy + this._writeProfilerMark("show,StartTM"); // The corresponding "stop" profiler mark is handled in _Overlay._baseEndShow(). + this._show(anchor, placement, alignment); + }, + + _show: function Menu_show(anchor, placement, alignment) { + if (!_ElementUtilities.hasClass(this.element, _Constants.menuMouseSpacingClass) && !_ElementUtilities.hasClass(this.element, _Constants.menuTouchSpacingClass)) { + // The Menu's spacing shouldn't change while it is already shown. Only + // add a spacing class if it doesn't already have one. It will get + // removed after the Menu hides. + _ElementUtilities.addClass( + this.element, + Flyout.Flyout._cascadeManager.inputType === _KeyboardBehavior._InputTypes.mouse || Flyout.Flyout._cascadeManager.inputType === _KeyboardBehavior._InputTypes.keyboard ? + _Constants.menuMouseSpacingClass : + _Constants.menuTouchSpacingClass + ); + } + // Call flyout show + this._baseFlyoutShow(anchor, placement, alignment); + + // Menu will need to adjust MenuCommand layouts based on the various + // types of commands visible in our Menu, but only after we send the beforeshow + // event, so the developer has a chance to show or hide more commands. + // Flyout's _findPosition will make that call. + }, + + _hide: function Menu_hide() { + if (this._hoverPromise) { + this._hoverPromise.cancel(); + } + Flyout.Flyout.prototype._hide.call(this); + }, + + _beforeEndHide: function Menu_beforeEndHide() { + _ElementUtilities.removeClass(this.element, _Constants.menuMouseSpacingClass); + _ElementUtilities.removeClass(this.element, _Constants.menuTouchSpacingClass); + Flyout.Flyout.prototype._beforeEndHide.call(this); + }, + + _addCommand: function Menu_addCommand(command) { + if (!command) { + throw new _ErrorFromName("WinJS.UI.Menu.NullCommand", strings.nullCommand); + } + // See if it's a command already + if (!command._element) { + // Not a command, so assume it's options for a command + command = new _Command.MenuCommand(null, command); + } + // If we were attached somewhere else, detach us + if (command._element.parentElement) { + command._element.parentElement.removeChild(command._element); + } + + // Reattach us + this._element.appendChild(command._element); + }, + + _dispose: function Menu_dispose() { + if (this._hoverPromise) { + this._hoverPromise.cancel(); + } + Flyout.Flyout.prototype._dispose.call(this); + + }, + + _commandsUpdated: function Menu_commandsUpdated() { + if (!this.hidden) { + this._checkMenuCommands(); + } + }, + + // Called when we show/hide commands or by flyout's _findPosition when the Menu is showing. + _checkMenuCommands: function Menu_checkMenuCommands() { + var menuCommands = this._element.querySelectorAll(".win-command"), + hasToggleCommands = false, + hasFlyoutCommands = false; + if (menuCommands) { + for (var i = 0, len = menuCommands.length; i < len; i++) { + var menuCommand = menuCommands[i].winControl; + if (menuCommand && !menuCommand.hidden) { + if (!hasToggleCommands && menuCommand.type === _Constants.typeToggle) { + hasToggleCommands = true; + } + if (!hasFlyoutCommands && menuCommand.type === _Constants.typeFlyout) { + hasFlyoutCommands = true; + } + } + } + } + + _ElementUtilities[hasToggleCommands ? 'addClass' : 'removeClass'](this._element, _Constants.menuContainsToggleCommandClass); + _ElementUtilities[hasFlyoutCommands ? 'addClass' : 'removeClass'](this._element, _Constants.menuContainsFlyoutCommandClass); + }, + + _handleKeyDown: function Menu_handleKeyDown(event) { + if (event.keyCode === Key.upArrow) { + Menu._focusOnPreviousElement(this.element); + + // Prevent the page from scrolling + event.preventDefault(); + } else if (event.keyCode === Key.downArrow) { + Menu._focusOnNextElement(this.element); + + // Prevent the page from scrolling + event.preventDefault(); + } else if ((event.keyCode === Key.space || event.keyCode === Key.enter) + && (this.element === _Global.document.activeElement)) { + event.preventDefault(); + this.hide(); + } else if (event.keyCode === Key.tab) { + event.preventDefault(); + } + }, + + _handleFocusIn: function Menu_handleFocusIn(event) { + // Menu focuses commands on mouseover. We need to handle cases involving activated flyout commands + // to ensure that mousing over different commands in a menu closes that command's sub flyout. + var target = event.target; + if (isCommandInMenu(target)) { + var command = target.winControl; + if (_ElementUtilities.hasClass(command.element, _Constants.menuCommandFlyoutActivatedClass)) { + // If it's an activated 'flyout' typed command, move focus onto the command's subFlyout. + // We expect this will collapse all decendant Flyouts of the subFlyout from the cascade. + command.flyout.element.focus(); + } else { + // Deactivate any currently activated command in the Menu to subsequently trigger all subFlyouts descendants to collapse. + var activatedSiblingCommand = this.element.querySelector("." + _Constants.menuCommandFlyoutActivatedClass); + if (activatedSiblingCommand) { + _Command.MenuCommand._deactivateFlyoutCommand(activatedSiblingCommand); + } + } + } else if (target === this.element) { + // The Menu itself is receiving focus. Rely on the Flyout base implementation to notify the cascadeManager. + // We expect this will only happen when other Menu event handling code causes the Menu to focus itself. + Flyout.Flyout.prototype._handleFocusIn.call(this, event); + } + }, + + _handleCommandInvoked: function Menu_handleCommandInvoked(event) { + // Cascading Menus hide when invoking a command commits an action, not when invoking a command opens a subFlyout. + if (this._hoverPromise) { + // Prevent pending duplicate invoke triggered via hover. + this._hoverPromise.cancel(); + } + var command = event.detail.command; + if (command._type !== _Constants.typeFlyout && command._type !== _Constants.typeSeparator) { + this._lightDismiss(); // Collapse all Menus/Flyouts. + } + }, + + _hoverPromise: null, + _handleMouseOver: function Menu_handleMouseOver(event) { + var target = event.target; + if (isCommandInMenu(target)) { + var command = target.winControl, + that = this; + + if (target.focus) { + target.focus(); + // remove keyboard focus rect since focus has been triggered by mouse over. + _ElementUtilities.removeClass(target, "win-keyboard"); + + if (command.type === _Constants.typeFlyout && command.flyout && command.flyout.hidden) { + this._hoverPromise = this._hoverPromise || Promise.timeout(_Constants.menuCommandHoverDelay).then( + function () { + if (!that.hidden && !that._disposed) { + command._invoke(event); + } + that._hoverPromise = null; + }, + function () { + that._hoverPromise = null; + }); + } + } + } + }, + + _handleMouseOut: function Menu_handleMouseOut(event) { + var target = event.target; + if (isCommandInMenu(target) && !target.contains(event.relatedTarget)) { + if (target === _Global.document.activeElement) { + // Menu gives focus to the menu itself + this.element.focus(); + } + if (this._hoverPromise) { + this._hoverPromise.cancel(); + } + } + }, + + _writeProfilerMark: function Menu_writeProfilerMark(text) { + _WriteProfilerMark("WinJS.UI.Menu:" + this._id + ":" + text); + } + }); + + // Statics + + // Set focus to next focusable element in the menu (loop if necessary). + // Note: The loop works by first setting focus to the menu itself. If the menu is + // what had focus before, then we break. Otherwise we try the first child next. + // Focus remains on the menu if nothing is focusable. + Menu._focusOnNextElement = function (menu) { + var _currentElement = _Global.document.activeElement; + + do { + if (_currentElement === menu) { + _currentElement = _currentElement.firstElementChild; + } else { + _currentElement = _currentElement.nextElementSibling; + } + + if (_currentElement) { + _currentElement.focus(); + } else { + _currentElement = menu; + } + + } while (_currentElement !== _Global.document.activeElement); + }; + + // Set focus to previous focusable element in the menu (loop if necessary). + // Note: The loop works by first setting focus to the menu itself. If the menu is + // what had focus before, then we break. Otherwise we try the last child next. + // Focus remains on the menu if nothing is focusable. + Menu._focusOnPreviousElement = function (menu) { + var _currentElement = _Global.document.activeElement; + + do { + if (_currentElement === menu) { + _currentElement = _currentElement.lastElementChild; + } else { + _currentElement = _currentElement.previousElementSibling; + } + + if (_currentElement) { + _currentElement.focus(); + } else { + _currentElement = menu; + } + + } while (_currentElement !== _Global.document.activeElement); + }; + + return Menu; + }) + }); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('WinJS/Controls/AutoSuggestBox/_SearchSuggestionManagerShim',[ + 'exports', + '../../_Signal', + '../../Core/_Base', + '../../Core/_BaseUtils', + '../../Core/_Events', + '../../BindingList', +], function SearchSuggestionManagerShimInit(exports, _Signal, _Base, _BaseUtils, _Events, BindingList) { + "use strict"; + + var CollectionChange = { + reset: 0, + itemInserted: 1, + itemRemoved: 2, + itemChanged: 3 + }; + var SearchSuggestionKind = { + Query: 0, + Result: 1, + Separator: 2 + }; + + var SuggestionVectorShim = _Base.Class.derive(Array, function SuggestionVectorShim_ctor() { + }, { + reset: function () { + this.length = 0; + this.dispatchEvent("vectorchanged", { collectionChange: CollectionChange.reset, index: 0 }); + }, + + insert: function (index, data) { + this.splice(index, 0, data); + this.dispatchEvent("vectorchanged", { collectionChange: CollectionChange.itemInserted, index: index }); + }, + + remove: function (index) { + this.splice(index, 1); + this.dispatchEvent("vectorchanged", { collectionChange: CollectionChange.itemRemoved, index: index }); + }, + }); + _Base.Class.mix(SuggestionVectorShim, _Events.eventMixin); + + var SearchSuggestionCollectionShim = _Base.Class.define(function SearchSuggestionCollectionShim_ctor() { + this._data = []; + }, { + size: { + get: function () { + return this._data.length; + } + }, + + appendQuerySuggestion: function (text) { + this._data.push({ kind: SearchSuggestionKind.Query, text: text }); + }, + appendQuerySuggestions: function (suggestions) { + suggestions.forEach(this.appendQuerySuggestion.bind(this)); + }, + appendResultSuggestion: function (text, detailText, tag, imageUrl, imageAlternateText) { + // 'image' must be null (not undefined) for SearchBox to fallback to use imageUrl instead + this._data.push({ kind: SearchSuggestionKind.Result, text: text, detailText: detailText, tag: tag, imageUrl: imageUrl, imageAlternateText: imageAlternateText, image: null }); + }, + appendSearchSeparator: function (label) { + this._data.push({ kind: SearchSuggestionKind.Separator, text: label }); + } + }); + + var SuggestionsRequestedEventArgShim = _Base.Class.define(function SuggestionsRequestedEventArgShim_ctor(queryText, language, linguisticDetails) { + this._queryText = queryText; + this._language = language; + this._linguisticDetails = linguisticDetails; + this._searchSuggestionCollection = new SearchSuggestionCollectionShim(); + }, { + language: { + get: function () { + return this._language; + } + }, + linguisticDetails: { + get: function () { + return this._linguisticDetails; + } + }, + queryText: { + get: function () { + return this._queryText; + } + }, + searchSuggestionCollection: { + get: function () { + return this._searchSuggestionCollection; + } + }, + getDeferral: function () { + return this._deferralSignal || (this._deferralSignal = new _Signal()); + }, + + _deferralSignal: null, + }); + + var SearchSuggestionManagerShim = _Base.Class.define(function SearchSuggestionManagerShim_ctor() { + this._updateVector = this._updateVector.bind(this); + + this._suggestionVector = new SuggestionVectorShim(); + this._query = ""; + this._history = { "": [] }; + + this._dataSource = []; + + this.searchHistoryContext = ""; + this.searchHistoryEnabled = true; + }, { + addToHistory: function (queryText /*, language */) { + if (!queryText || !queryText.trim()) { + return; + } + + var history = this._history[this.searchHistoryContext]; + var dupeIndex = -1; + for (var i = 0, l = history.length; i < l; i++) { + var item = history[i]; + if (item.text.toLowerCase() === queryText.toLowerCase()) { + dupeIndex = i; + break; + } + } + if (dupeIndex >= 0) { + history.splice(dupeIndex, 1); + } + + history.splice(0, 0, { text: queryText, kind: SearchSuggestionKind.Query }); + this._updateVector(); + }, + + clearHistory: function () { + this._history[this.searchHistoryContext] = []; + this._updateVector(); + }, + + setLocalContentSuggestionSettings: function (settings) { + }, + + setQuery: function (queryText) { + var that = this; + function update(arr) { + that._dataSource = arr; + that._updateVector(); + } + + this._query = queryText; + var arg = new SuggestionsRequestedEventArgShim(queryText); + this.dispatchEvent("suggestionsrequested", { request: arg }); + if (arg._deferralSignal) { + arg._deferralSignal.promise.then(update.bind(this, arg.searchSuggestionCollection._data)); + } else { + update(arg.searchSuggestionCollection._data); + } + }, + + searchHistoryContext: { + get: function () { + return "" + this._searchHistoryContext; + }, + set: function (value) { + value = "" + value; + if (!this._history[value]) { + this._history[value] = []; + } + this._searchHistoryContext = value; + } + }, + + searchHistoryEnabled: { + get: function () { + return this._searchHistoryEnabled; + }, + set: function (value) { + this._searchHistoryEnabled = value; + } + }, + + suggestions: { + get: function () { + return this._suggestionVector; + } + }, + + _updateVector: function () { + // Can never clear the entire suggestions list or it will cause a visual flash because + // the SearchBox control removes the suggestions list UI when the SSM fires vectorChanged + // with size === 0, then re-renders it when the first suggestion is added. + // Workaround is to insert a dummy entry, remove all old entries, add the new set of + // eligible suggestions, then remove the dummy entry. + this.suggestions.insert(this.suggestions.length, { text: "", kind: SearchSuggestionKind.Query }); + + while (this.suggestions.length > 1) { + this.suggestions.remove(0); + } + + var index = 0; + var added = {}; + if (this.searchHistoryEnabled) { + var q = this._query.toLowerCase(); + this._history[this.searchHistoryContext].forEach(function (item) { + var text = item.text.toLowerCase(); + if (text.indexOf(q) === 0) { + this.suggestions.insert(index, item); + added[text] = true; + index++; + } + }, this); + } + this._dataSource.forEach(function (item) { + if (item.kind === SearchSuggestionKind.Query) { + if (!added[item.text.toLowerCase()]) { + this.suggestions.insert(index, item); + index++; + } + } else { + this.suggestions.insert(index, item); + index++; + } + }, this); + + this.suggestions.remove(this.suggestions.length - 1); + }, + }); + _Base.Class.mix(SearchSuggestionManagerShim, _Events.eventMixin); + + _Base.Namespace._moduleDefine(exports, null, { + _CollectionChange: CollectionChange, + _SearchSuggestionKind: SearchSuggestionKind, + _SearchSuggestionManagerShim: SearchSuggestionManagerShim, + }); +}); + +define('require-style!less/styles-autosuggestbox',[],function(){}); + +define('require-style!less/colors-autosuggestbox',[],function(){}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('WinJS/Controls/AutoSuggestBox',[ + "exports", + "../Core/_Global", + "../Core/_WinRT", + "../Core/_Base", + "../Core/_ErrorFromName", + "../Core/_Events", + "../Core/_Resources", + "../Utilities/_Control", + "../Utilities/_ElementListUtilities", + "../Utilities/_ElementUtilities", + '../Utilities/_Hoverable', + "../_Accents", + "../Animations", + "../BindingList", + "../Promise", + "./Repeater", + "./AutoSuggestBox/_SearchSuggestionManagerShim", + "require-style!less/styles-autosuggestbox", + "require-style!less/colors-autosuggestbox" +], function autoSuggestBoxInit(exports, _Global, _WinRT, _Base, _ErrorFromName, _Events, _Resources, _Control, _ElementListUtilities, _ElementUtilities, _Hoverable, _Accents, Animations, BindingList, Promise, Repeater, _SuggestionManagerShim) { + "use strict"; + + _Accents.createAccentRule("html.win-hoverable .win-autosuggestbox .win-autosuggestbox-suggestion-selected:hover", [{ name: "background-color", value: _Accents.ColorTypes.listSelectHover }]); + _Accents.createAccentRule(".win-autosuggestbox .win-autosuggestbox-suggestion-selected", [{ name: "background-color", value: _Accents.ColorTypes.listSelectRest }]); + _Accents.createAccentRule(".win-autosuggestbox .win-autosuggestbox-suggestion-selected.win-autosuggestbox-suggestion-selected:hover:active", [{ name: "background-color", value: _Accents.ColorTypes.listSelectPress }]); + + var ClassNames = { + asb: "win-autosuggestbox", + asbDisabled: "win-autosuggestbox-disabled", + asbFlyout: "win-autosuggestbox-flyout", + asbFlyoutAbove: "win-autosuggestbox-flyout-above", + asbBoxFlyoutHighlightText: "win-autosuggestbox-flyout-highlighttext", + asbHitHighlightSpan: "win-autosuggestbox-hithighlight-span", + asbInput: "win-autosuggestbox-input", + asbInputFocus: "win-autosuggestbox-input-focus", + asbSuggestionQuery: "win-autosuggestbox-suggestion-query", + asbSuggestionResult: "win-autosuggestbox-suggestion-result", + asbSuggestionResultText: "win-autosuggestbox-suggestion-result-text", + asbSuggestionResultDetailedText: "win-autosuggestbox-suggestion-result-detailed-text", + asbSuggestionSelected: "win-autosuggestbox-suggestion-selected", + asbSuggestionSeparator: "win-autosuggestbox-suggestion-separator", + }; + + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + /// + /// + /// A rich input box that provides suggestions as the user types. + /// + /// + /// + /// + /// + /// ]]> + /// Raised when user or app changes the query text. + /// Raised when user presses Enter. + /// Raised when user clicks one of the displayed suggestions. + /// Raised when the system requests suggestions from this app. + /// Styles the entire Auto Suggest Box control. + /// Styles the query input box. + /// Styles the result suggestions flyout. + /// Styles the query type suggestion. + /// Styles the result type suggestion. + /// Styles the currently selected suggestion. + /// Styles the separator type suggestion. + /// + /// + AutoSuggestBox: _Base.Namespace._lazy(function () { + var Key = _ElementUtilities.Key; + + var EventNames = { + querychanged: "querychanged", + querysubmitted: "querysubmitted", + resultsuggestionchosen: "resultsuggestionchosen", + suggestionsrequested: "suggestionsrequested" + }; + + var Strings = { + get duplicateConstruction() { return "Invalid argument: Controls may only be instantiated one time for each DOM element"; }, + get invalidSuggestionKind() { return "Error: Invalid suggestion kind."; }, + + get ariaLabel() { return _Resources._getWinJSString("ui/autoSuggestBoxAriaLabel").value; }, + get ariaLabelInputNoPlaceHolder() { return _Resources._getWinJSString("ui/autoSuggestBoxAriaLabelInputNoPlaceHolder").value; }, + get ariaLabelInputPlaceHolder() { return _Resources._getWinJSString("ui/autoSuggestBoxAriaLabelInputPlaceHolder").value; }, + get ariaLabelQuery() { return _Resources._getWinJSString("ui/autoSuggestBoxAriaLabelQuery").value; }, + get ariaLabelResult() { return _Resources._getWinJSString("ui/autoSuggestBoxAriaLabelResult").value; }, + get ariaLabelSeparator() { return _Resources._getWinJSString("ui/autoSuggestBoxAriaLabelSeparator").value; }, + }; + + var AutoSuggestBox = _Base.Class.define(function asb_ctor(element, options) { + /// + /// + /// Creates a new AutoSuggestBox. + /// + /// + /// The DOM element that hosts the AutoSuggestBox. + /// + /// + /// An object that contains one or more property/value pairs to apply to the new control. + /// Each property of the options object corresponds to one of the control's properties or events. + /// Event names must begin with "on". For example, to provide a handler for the querychanged event, + /// add a property named "onquerychanged" to the options object and set its value to the event handler. + /// This parameter is optional. + /// + /// + /// The new AutoSuggestBox. + /// + /// + /// + element = element || _Global.document.createElement("div"); + options = options || {}; + + if (element.winControl) { + throw new _ErrorFromName("WinJS.UI.AutoSuggestBox.DuplicateConstruction", Strings.duplicateConstruction); + } + + this._suggestionsChangedHandler = this._suggestionsChangedHandler.bind(this); + this._suggestionsRequestedHandler = this._suggestionsRequestedHandler.bind(this); + + this._element = element; + element.winControl = this; + element.classList.add(ClassNames.asb); + element.classList.add("win-disposable"); + + this._setupDOM(); + this._setupSSM(); + + this._chooseSuggestionOnEnter = false; + this._currentFocusedIndex = -1; + this._currentSelectedIndex = -1; + this._flyoutOpenPromise = Promise.wrap(); + this._lastKeyPressLanguage = ""; + this._prevLinguisticDetails = this._getLinguisticDetails(); + this._prevQueryText = ""; + + _Control.setOptions(this, options); + + this._hideFlyout(); + }, { + /// + /// Raised when user clicks on one of the suggestions displayed. + /// + /// + onresultsuggestionchosen: _Events._createEventProperty(EventNames.resultsuggestionchosen), + + /// + /// Raised when user or app changes the query text. + /// + /// + onquerychanged: _Events._createEventProperty(EventNames.querychanged), + + /// + /// Raised when user submits the current query. + /// + /// + onquerysubmitted: _Events._createEventProperty(EventNames.querysubmitted), + + /// + /// Raised when Windows requests search suggestions from the app. + /// + /// + onsuggestionsrequested: _Events._createEventProperty(EventNames.suggestionsrequested), + + /// + element: { + get: function () { + return this._element; + } + }, + + /// + /// Gets or sets whether the first suggestion is chosen when the user presses Enter. When set to true, as the user types in the input box, a + /// focus rectangle is drawn on the first suggestion (if present and no IME composition in progress). Pressing enter will behave the same as + /// if clicked on the focused suggestion, and the down arrow key press will put real focus to the second suggestion and the up arrow key will + /// remove focus. + /// + /// + chooseSuggestionOnEnter: { + get: function () { + return this._chooseSuggestionOnEnter; + }, + set: function (value) { + this._chooseSuggestionOnEnter = !!value; + } + }, + + /// + /// Gets or sets a value that specifies whether the AutoSuggestBox is disabled. + /// + /// + disabled: { + get: function () { + return this._inputElement.disabled; + }, + set: function (value) { + if (this._inputElement.disabled === !!value) { + return; + } + + if (!value) { + this._enableControl(); + } else { + this._disableControl(); + } + } + }, + + /// + /// Gets or sets the placeholder text for the AutoSuggestBox. This text is displayed if there is no other text in the input box. + /// + /// + placeholderText: { + get: function () { + return this._inputElement.placeholder; + }, + set: function (value) { + this._inputElement.placeholder = value; + this._updateInputElementAriaLabel(); + } + }, + + /// + /// Gets or sets the query text for the AutoSuggestBox. + /// + /// + queryText: { + get: function () { + return this._inputElement.value; + }, + set: function (value) { + this._inputElement.value = ""; // This finalizes the IME composition + this._inputElement.value = value; + } + }, + + /// + /// Gets or sets a value that specifies whether history is disabled for the AutoSuggestBox. The default value is false. + /// + /// + searchHistoryDisabled: { + get: function () { + return !this._suggestionManager.searchHistoryEnabled; + }, + set: function (value) { + this._suggestionManager.searchHistoryEnabled = !value; + } + }, + + /// + /// Gets or sets the search history context for the AutoSuggestBox. The search history context string is used as a secondary key for storing search history. + /// (The primary key is the AppId.) An app can use the search history context string to store different search histories based on the context of the application. + /// If you don't set this property, the system assumes that all searches in your app occur in the same context. + /// If you update this property while the search pane is open with suggestions showing, the changes won't take effect until the user enters the next character. + /// + /// + searchHistoryContext: { + get: function () { + return this._suggestionManager.searchHistoryContext; + }, + set: function (value) { + this._suggestionManager.searchHistoryContext = value; + } + }, + + dispose: function asb_dispose() { + /// + /// + /// Disposes this control. + /// + /// + /// + if (this._disposed) { + return; + } + + // Cancel pending promises. + this._flyoutOpenPromise.cancel(); + + this._suggestions.removeEventListener("vectorchanged", this._suggestionsChangedHandler); + this._suggestionManager.removeEventListener("suggestionsrequested", this._suggestionsRequestedHandler); + + this._suggestionManager = null; + this._suggestions = null; + this._hitFinder = null; + + this._disposed = true; + }, + + setLocalContentSuggestionSettings: function asb_setLocalContentSuggestionSettings(settings) { + /// + /// + /// Specifies whether suggestions based on local files are automatically displayed in the input field, and defines the criteria that + /// the system uses to locate and filter these suggestions. + /// + /// + /// The new settings for local content suggestions. + /// + /// + /// + this._suggestionManager.setLocalContentSuggestionSettings(settings); + }, + + // Constructor Helpers + _setupDOM: function asb_setupDOM() { + var flyoutPointerReleasedHandler = this._flyoutPointerReleasedHandler.bind(this); + var inputOrImeChangeHandler = this._inputOrImeChangeHandler.bind(this); + + // Root element + if (!this._element.getAttribute("aria-label")) { + this._element.setAttribute("aria-label", Strings.ariaLabel); + } + this._element.setAttribute("role", "group"); + + // Input element + this._inputElement = _Global.document.createElement("input"); + this._inputElement.autocorrect = "off"; + this._inputElement.type = "search"; + this._inputElement.classList.add(ClassNames.asbInput); + this._inputElement.classList.add("win-textbox"); + this._inputElement.setAttribute("role", "textbox"); + this._inputElement.addEventListener("keydown", this._keyDownHandler.bind(this)); + this._inputElement.addEventListener("keypress", this._keyPressHandler.bind(this)); + this._inputElement.addEventListener("keyup", this._keyUpHandler.bind(this)); + this._inputElement.addEventListener("focus", this._inputFocusHandler.bind(this)); + this._inputElement.addEventListener("blur", this._inputBlurHandler.bind(this)); + this._inputElement.addEventListener("input", inputOrImeChangeHandler); + this._inputElement.addEventListener("compositionstart", inputOrImeChangeHandler); + this._inputElement.addEventListener("compositionupdate", inputOrImeChangeHandler); + this._inputElement.addEventListener("compositionend", inputOrImeChangeHandler); + _ElementUtilities._addEventListener(this._inputElement, "pointerdown", this._inputPointerDownHandler.bind(this)); + this._updateInputElementAriaLabel(); + this._element.appendChild(this._inputElement); + var context = this._tryGetInputContext(); + if (context) { + context.addEventListener("MSCandidateWindowShow", this._msCandidateWindowShowHandler.bind(this)); + context.addEventListener("MSCandidateWindowHide", this._msCandidateWindowHideHandler.bind(this)); + } + + // Flyout element + this._flyoutElement = _Global.document.createElement("div"); + this._flyoutElement.classList.add(ClassNames.asbFlyout); + this._flyoutElement.addEventListener("blur", this._flyoutBlurHandler.bind(this)); + _ElementUtilities._addEventListener(this._flyoutElement, "pointerup", flyoutPointerReleasedHandler); + _ElementUtilities._addEventListener(this._flyoutElement, "pointercancel", flyoutPointerReleasedHandler); + _ElementUtilities._addEventListener(this._flyoutElement, "pointerout", flyoutPointerReleasedHandler); + _ElementUtilities._addEventListener(this._flyoutElement, "pointerdown", this._flyoutPointerDownHandler.bind(this)); + this._element.appendChild(this._flyoutElement); + + // Repeater + var that = this; + function repeaterTemplate(suggestion) { + return that._renderSuggestion(suggestion); + } + this._suggestionsData = new BindingList.List(); + this._repeaterElement = _Global.document.createElement("div"); + this._repeater = new Repeater.Repeater(this._repeaterElement, { + data: this._suggestionsData, + template: repeaterTemplate, + }); + _ElementUtilities._ensureId(this._repeaterElement); + this._repeaterElement.setAttribute("role", "listbox"); + this._repeaterElement.setAttribute("aria-live", "polite"); + this._flyoutElement.appendChild(this._repeaterElement); + }, + + _setupSSM: function asb_setupSSM() { + // Get the search suggestion provider if it is available + this._suggestionManager = new _SuggestionManagerShim._SearchSuggestionManagerShim(); + this._suggestions = this._suggestionManager.suggestions; + + this._suggestions.addEventListener("vectorchanged", this._suggestionsChangedHandler); + this._suggestionManager.addEventListener("suggestionsrequested", this._suggestionsRequestedHandler); + }, + + // Flyout functions + _hideFlyout: function asb_hideFlyout() { + if (this._isFlyoutShown()) { + this._flyoutElement.style.display = "none"; + } + }, + + _showFlyout: function asb_showFlyout() { + var prevNumSuggestions = this._prevNumSuggestions || 0; + this._prevNumSuggestions = this._suggestionsData.length; + + if (this._isFlyoutShown() && prevNumSuggestions === this._suggestionsData.length) { + return; + } + + if (this._suggestionsData.length === 0) { + return; + } + + this._flyoutElement.style.display = "block"; + + var inputRect = this._inputElement.getBoundingClientRect(); + var flyoutRect = this._flyoutElement.getBoundingClientRect(); + var documentClientWidth = _Global.document.documentElement.clientWidth; + + // Display above vs below - the ASB flyout always opens in the direction where there is more space + var spaceAbove = inputRect.top; + var spaceBelow = _Global.document.documentElement.clientHeight - inputRect.bottom; + this._flyoutBelowInput = spaceBelow >= spaceAbove; + if (this._flyoutBelowInput) { + this._flyoutElement.classList.remove(ClassNames.asbFlyoutAbove); + this._flyoutElement.scrollTop = 0; + } else { + this._flyoutElement.classList.add(ClassNames.asbFlyoutAbove); + this._flyoutElement.scrollTop = this._flyoutElement.scrollHeight - this._flyoutElement.clientHeight; + } + + this._addFlyoutIMEPaddingIfRequired(); + + // Align left vs right edge + var alignRight; + if (_Global.getComputedStyle(this._flyoutElement).direction === "rtl") { + // RTL: Align to the right edge if there is enough space to the left of the control's + // right edge, or if there is not enough space to fit the flyout aligned to either edge. + alignRight = ((inputRect.right - flyoutRect.width) >= 0) || ((inputRect.left + flyoutRect.width) > documentClientWidth); + + } else { + // LTR: Align to the right edge if there isn't enough space to the right of the control's + // left edge, but there is enough space to the left of the control's right edge. + alignRight = ((inputRect.left + flyoutRect.width) > documentClientWidth) && ((inputRect.right - flyoutRect.width) >= 0); + } + + if (alignRight) { + this._flyoutElement.style.left = (inputRect.width - flyoutRect.width - this._element.clientLeft) + "px"; + } else { + this._flyoutElement.style.left = "-" + this._element.clientLeft + "px"; + } + + // ms-scroll-chaining:none will still chain scroll parent element if child div does + // not have a scroll bar. Prevent this by setting and updating touch action + this._flyoutElement.style.touchAction = this._flyoutElement.scrollHeight > flyoutRect.height ? "pan-y" : "none"; + + this._flyoutOpenPromise.cancel(); + var animationKeyframe = this._flyoutBelowInput ? "WinJS-flyoutBelowASB-showPopup" : "WinJS-flyoutAboveASB-showPopup"; + this._flyoutOpenPromise = Animations.showPopup(this._flyoutElement, { top: "0px", left: "0px", keyframe: animationKeyframe }); + }, + + _addFlyoutIMEPaddingIfRequired: function asb_addFlyoutIMEPaddingIfRequired() { + // Check if we have InputContext APIs + var context = this._tryGetInputContext(); + if (!context) { + return; + } + + // Check if flyout is visible and below input + if (!this._isFlyoutShown() || !this._flyoutBelowInput) { + return; + } + + // Check if IME is occluding flyout + var flyoutRect = this._flyoutElement.getBoundingClientRect(); + var imeRect = context.getCandidateWindowClientRect(); + var inputRect = this._inputElement.getBoundingClientRect(); + var flyoutTop = inputRect.bottom; + var flyoutBottom = inputRect.bottom + flyoutRect.height; + if (imeRect.top > flyoutBottom || imeRect.bottom < flyoutTop) { + return; + } + + // Shift the flyout down or to the right depending on IME/ASB width ratio. + // When the IME width is less than 45% of the ASB's width, the flyout gets + // shifted right, otherwise shifted down. + var animation = Animations.createRepositionAnimation(this._flyoutElement); + if (imeRect.width < (inputRect.width * 0.45)) { + this._flyoutElement.style.marginLeft = imeRect.width + "px"; + } else { + this._flyoutElement.style.marginTop = (imeRect.bottom - imeRect.top + 4) + "px"; + } + animation.execute(); + }, + + _findNextSuggestionElementIndex: function asb_findNextSuggestionElementIndex(curIndex) { + // Returns -1 if there are no focusable elements after curIndex + // Returns first element if curIndex < 0 + var startIndex = curIndex < 0 ? 0 : curIndex + 1; + for (var i = startIndex; i < this._suggestionsData.length; i++) { + if ((this._repeater.elementFromIndex(i)) && (this._isSuggestionSelectable(this._suggestionsData.getAt(i)))) { + return i; + } + } + return -1; + }, + + _findPreviousSuggestionElementIndex: function asb_findPreviousSuggestionElementIndex(curIndex) { + // Returns -1 if there are no focusable elements before curIndex + // Returns last element if curIndex >= suggestionsdata.length + var startIndex = curIndex >= this._suggestionsData.length ? this._suggestionsData.length - 1 : curIndex - 1; + for (var i = startIndex; i >= 0; i--) { + if ((this._repeater.elementFromIndex(i)) && (this._isSuggestionSelectable(this._suggestionsData.getAt(i)))) { + return i; + } + } + return -1; + }, + + _isFlyoutShown: function asb_isFlyoutShown() { + return (this._flyoutElement.style.display !== "none"); + }, + + _isSuggestionSelectable: function asb_isSuggestionSelectable(suggestion) { + return ((suggestion.kind === _SuggestionManagerShim._SearchSuggestionKind.Query) || + (suggestion.kind === _SuggestionManagerShim._SearchSuggestionKind.Result)); + }, + + _processSuggestionChosen: function asb_processSuggestionChosen(item, event) { + this.queryText = item.text; + if (item.kind === _SuggestionManagerShim._SearchSuggestionKind.Query) { + this._submitQuery(item.text, false /*fillLinguisticDetails*/, event); // force empty linguistic details since explicitly chosen suggestion from list + } else if (item.kind === _SuggestionManagerShim._SearchSuggestionKind.Result) { + this._fireEvent(EventNames.resultsuggestionchosen, { + tag: item.tag, + keyModifiers: getKeyModifiers(event), + storageFile: null + }); + } + this._hideFlyout(); + }, + + _selectSuggestionAtIndex: function asb_selectSuggestionAtIndex(indexToSelect) { + var that = this; + function scrollToView(targetElement) { + var popupHeight = that._flyoutElement.getBoundingClientRect().bottom - that._flyoutElement.getBoundingClientRect().top; + if ((targetElement.offsetTop + targetElement.offsetHeight) > (that._flyoutElement.scrollTop + popupHeight)) { + // Element to scroll is below popup visible area + var scrollDifference = (targetElement.offsetTop + targetElement.offsetHeight) - (that._flyoutElement.scrollTop + popupHeight); + _ElementUtilities._zoomTo(that._flyoutElement, { contentX: 0, contentY: (that._flyoutElement.scrollTop + scrollDifference), viewportX: 0, viewportY: 0 }); + } else if (targetElement.offsetTop < that._flyoutElement.scrollTop) { + // Element to scroll is above popup visible area + _ElementUtilities._zoomTo(that._flyoutElement, { contentX: 0, contentY: targetElement.offsetTop, viewportX: 0, viewportY: 0 }); + } + } + + // Sets focus on the specified element and removes focus from others. + // Clears selection if index is outside of suggestiondata index range. + var curElement = null; + for (var i = 0; i < this._suggestionsData.length; i++) { + curElement = this._repeater.elementFromIndex(i); + if (i !== indexToSelect) { + curElement.classList.remove(ClassNames.asbSuggestionSelected); + curElement.setAttribute("aria-selected", "false"); + } else { + curElement.classList.add(ClassNames.asbSuggestionSelected); + scrollToView(curElement); + curElement.setAttribute("aria-selected", "true"); + } + } + this._currentSelectedIndex = indexToSelect; + if (curElement) { + this._inputElement.setAttribute("aria-activedescendant", this._repeaterElement.id + indexToSelect); + } else if (this._inputElement.hasAttribute("aria-activedescendant")) { + this._inputElement.removeAttribute("aria-activedescendant"); + } + }, + + _updateFakeFocus: function asb_updateFakeFocus() { + var firstElementIndex; + if (this._isFlyoutShown() && (this._chooseSuggestionOnEnter)) { + firstElementIndex = this._findNextSuggestionElementIndex(-1); + } else { + // This will clear the fake focus. + firstElementIndex = -1; + } + + this._selectSuggestionAtIndex(firstElementIndex); + }, + + _updateQueryTextWithSuggestionText: function asb_updateQueryTextWithSuggestionText(suggestionIndex) { + if ((suggestionIndex >= 0) && (suggestionIndex < this._suggestionsData.length)) { + this.queryText = this._suggestionsData.getAt(suggestionIndex).text; + } + }, + + // Helpers + _disableControl: function asb_disableControl() { + if (this._isFlyoutShown()) { + this._hideFlyout(); + } + this._element.disabled = true; + this._element.classList.add(ClassNames.asbDisabled); + this._inputElement.disabled = true; + }, + + _enableControl: function asb_enableControl() { + this._element.disabled = false; + this._element.classList.remove(ClassNames.asbDisabled); + this._inputElement.disabled = false; + if (_Global.document.activeElement === this._element) { + _ElementUtilities._setActive(this._inputElement); + } + }, + + _fireEvent: function asb_fireEvent(type, detail) { + // Returns true if ev.preventDefault() was not called + var event = _Global.document.createEvent("CustomEvent"); + event.initCustomEvent(type, true, true, detail); + return this._element.dispatchEvent(event); + }, + + _getLinguisticDetails: function asb_getLinguisticDetails(useCache, createFilled) { // createFilled=false always creates an empty linguistic details object, otherwise generate it or use the cache + function createQueryLinguisticDetails(compositionAlternatives, compositionStartOffset, compositionLength, queryTextPrefix, queryTextSuffix) { + var linguisticDetails = null; + + // The linguistic alternatives we receive are only for the composition string being composed. We need to provide the linguistic alternatives + // in the form of the full query text with alternatives embedded. + var fullCompositionAlternatives = []; + for (var i = 0; i < compositionAlternatives.length; i++) { + fullCompositionAlternatives[i] = queryTextPrefix + compositionAlternatives[i] + queryTextSuffix; + } + + if (_WinRT.Windows.ApplicationModel.Search.SearchQueryLinguisticDetails) { + try { + linguisticDetails = new _WinRT.Windows.ApplicationModel.Search.SearchQueryLinguisticDetails(fullCompositionAlternatives, compositionStartOffset, compositionLength); + } catch (e) { + // WP10 currently exposes SQLD API but throws on instantiation. + } + } + + if (!linguisticDetails) { + // If we're in web compartment, create a script version of the WinRT SearchQueryLinguisticDetails object + linguisticDetails = { + queryTextAlternatives: fullCompositionAlternatives, + queryTextCompositionStart: compositionStartOffset, + queryTextCompositionLength: compositionLength + }; + } + return linguisticDetails; + } + + var linguisticDetails = null; + if ((this._inputElement.value === this._prevQueryText) && useCache && this._prevLinguisticDetails && createFilled) { + linguisticDetails = this._prevLinguisticDetails; + } else { + var compositionAlternatives = []; + var compositionStartOffset = 0; + var compositionLength = 0; + var queryTextPrefix = ""; + var queryTextSuffix = ""; + if (createFilled) { + var context = this._tryGetInputContext(); + if (context && context.getCompositionAlternatives) { + compositionAlternatives = context.getCompositionAlternatives(); + compositionStartOffset = context.compositionStartOffset; + compositionLength = context.compositionEndOffset - context.compositionStartOffset; + + if ((this._inputElement.value !== this._prevQueryText) || (this._prevCompositionLength === 0) || (compositionLength > 0)) { + queryTextPrefix = this._inputElement.value.substring(0, compositionStartOffset); + queryTextSuffix = this._inputElement.value.substring(compositionStartOffset + compositionLength); + } else { + // composition ended, but alternatives have been kept, need to reuse the previous query prefix/suffix, but still report to the client that the composition has ended (start & length of composition of 0) + queryTextPrefix = this._inputElement.value.substring(0, this._prevCompositionStart); + queryTextSuffix = this._inputElement.value.substring(this._prevCompositionStart + this._prevCompositionLength); + } + } + } + linguisticDetails = createQueryLinguisticDetails(compositionAlternatives, compositionStartOffset, compositionLength, queryTextPrefix, queryTextSuffix); + } + return linguisticDetails; + }, + + _isElementInSearchControl: function asb_isElementInSearchControl(targetElement) { + return this.element.contains(targetElement) || (this.element === targetElement); + }, + + _renderSuggestion: function asb_renderSuggestion(suggestion) { + var root = null; + if (!suggestion) { + return root; + } + if (suggestion.kind === _SuggestionManagerShim._SearchSuggestionKind.Query) { + root = querySuggestionRenderer(this, suggestion); + } else if (suggestion.kind === _SuggestionManagerShim._SearchSuggestionKind.Separator) { + root = separatorSuggestionRenderer(suggestion); + } else if (suggestion.kind === _SuggestionManagerShim._SearchSuggestionKind.Result) { + root = resultSuggestionRenderer(this, suggestion); + } else { + throw new _ErrorFromName("WinJS.UI.AutoSuggestBox.invalidSuggestionKind", Strings.invalidSuggestionKind); + } + return root; + }, + + _shouldIgnoreInput: function asb_shouldIgnoreInput() { + var processingIMEFocusLossKey = this._isProcessingDownKey || this._isProcessingUpKey || this._isProcessingTabKey || this._isProcessingEnterKey; + return processingIMEFocusLossKey || this._isFlyoutPointerDown; + }, + + _submitQuery: function asb_submitQuery(queryText, fillLinguisticDetails, event) { + if (this._disposed) { + return; + } + + // get the most up to date value of the input langauge from WinRT if available + if (_WinRT.Windows.Globalization.Language) { + this._lastKeyPressLanguage = _WinRT.Windows.Globalization.Language.currentInputMethodLanguageTag; + } + + this._fireEvent(EventNames.querysubmitted, { + language: this._lastKeyPressLanguage, + linguisticDetails: this._getLinguisticDetails(true /*useCache*/, fillLinguisticDetails), // allow caching, but generate empty linguistic details if suggestion is used + queryText: queryText, + keyModifiers: getKeyModifiers(event) + }); + + if (this._suggestionManager) { + this._suggestionManager.addToHistory(this._inputElement.value, this._lastKeyPressLanguage); + } + }, + + _tryGetInputContext: function asb_tryGetInputContext() { + // On WP, msGetInputContext is defined but throws when invoked + if (this._inputElement.msGetInputContext) { + try { + return this._inputElement.msGetInputContext(); + } catch (e) { + return null; + } + } + return null; + }, + + _updateInputElementAriaLabel: function asb_updateInputElementAriaLabel() { + this._inputElement.setAttribute("aria-label", + this._inputElement.placeholder ? _Resources._formatString(Strings.ariaLabelInputPlaceHolder, this._inputElement.placeholder) : Strings.ariaLabelInputNoPlaceHolder + ); + }, + + // Event Handlers + _flyoutBlurHandler: function asb_flyoutBlurHandler(event) { + if (this._isElementInSearchControl(_Global.document.activeElement)) { + this._internalFocusMove = true; + } else { + this._element.classList.remove(ClassNames.asbInputFocus); + this._hideFlyout(); + } + }, + + _flyoutPointerDownHandler: function asb_flyoutPointerDownHandler(ev) { + var that = this; + var srcElement = ev.target; + function findSuggestionElementIndex() { + if (srcElement) { + for (var i = 0; i < that._suggestionsData.length; i++) { + if (that._repeater.elementFromIndex(i) === srcElement) { + return i; + } + } + } + return -1; + } + + this._isFlyoutPointerDown = true; + while (srcElement && (srcElement.parentNode !== this._repeaterElement)) { + srcElement = srcElement.parentNode; + } + var index = findSuggestionElementIndex(); + if ((index >= 0) && (index < this._suggestionsData.length) && (this._currentFocusedIndex !== index)) { + if (this._isSuggestionSelectable(this._suggestionsData.getAt(index))) { + this._currentFocusedIndex = index; + this._selectSuggestionAtIndex(index); + this._updateQueryTextWithSuggestionText(this._currentFocusedIndex); + } + } + // Prevent default so focus does not leave input element. + ev.preventDefault(); + }, + + _flyoutPointerReleasedHandler: function asb_flyoutPointerReleasedHandler() { + this._isFlyoutPointerDown = false; + + if (this._reflowImeOnPointerRelease) { + this._reflowImeOnPointerRelease = false; + var animation = Animations.createRepositionAnimation(this._flyoutElement); + this._flyoutElement.style.marginTop = ""; + this._flyoutElement.style.marginLeft = ""; + animation.execute(); + } + }, + + _inputBlurHandler: function asb_inputBlurHandler(event) { + // Hide flyout if focus is leaving the control + if (!this._isElementInSearchControl(_Global.document.activeElement)) { + this._element.classList.remove(ClassNames.asbInputFocus); + this._hideFlyout(); + } + this.queryText = this._prevQueryText; // Finalize IME composition + this._isProcessingDownKey = false; + this._isProcessingUpKey = false; + this._isProcessingTabKey = false; + this._isProcessingEnterKey = false; + }, + + _inputFocusHandler: function asb_inputFocusHandler(event) { + // Refresh hit highlighting if text has changed since focus was present + // This can happen if the user committed a suggestion previously. + if (this._inputElement.value !== this._prevQueryText) { + if (_WinRT.Windows.Data.Text.SemanticTextQuery) { + if (this._inputElement.value !== "") { + this._hitFinder = new _WinRT.Windows.Data.Text.SemanticTextQuery(this._inputElement.value, this._inputElement.lang); + } else { + this._hitFinder = null; + } + } + } + + // If focus is returning to the input box from outside the control, show the flyout and refresh the suggestions + if (event.target === this._inputElement && !this._internalFocusMove) { + this._showFlyout(); + if (this._currentFocusedIndex !== -1) { + // Focus is not in input + this._selectSuggestionAtIndex(this._currentFocusedIndex); + } else { + this._updateFakeFocus(); + } + + this._suggestionManager.setQuery( + this._inputElement.value, + this._lastKeyPressLanguage, + this._getLinguisticDetails(true /*useCache*/, true /*createFilled*/) + ); + } + + this._internalFocusMove = false; + this._element.classList.add(ClassNames.asbInputFocus); + }, + + _inputOrImeChangeHandler: function asb_inputImeChangeHandler() { + var that = this; + function hasLinguisticDetailsChanged(newLinguisticDetails) { + var hasLinguisticDetailsChanged = false; + if ((that._prevLinguisticDetails.queryTextCompositionStart !== newLinguisticDetails.queryTextCompositionStart) || + (that._prevLinguisticDetails.queryTextCompositionLength !== newLinguisticDetails.queryTextCompositionLength) || + (that._prevLinguisticDetails.queryTextAlternatives.length !== newLinguisticDetails.queryTextAlternatives.length)) { + hasLinguisticDetailsChanged = true; + } + that._prevLinguisticDetails = newLinguisticDetails; + return hasLinguisticDetailsChanged; + } + + // swallow the IME change event that gets fired when composition is ended due to keyboarding down to the suggestion list & mouse down on the button + if (!this._shouldIgnoreInput()) { + var linguisticDetails = this._getLinguisticDetails(false /*useCache*/, true /*createFilled*/); // never cache on explicit user changes + var hasLinguisticDetailsChanged = hasLinguisticDetailsChanged(linguisticDetails); // updates this._prevLinguisticDetails + + // Keep the previous composition cache up to date, execpt when composition ended with no text change and alternatives are kept. + // In that case, we need to use the cached values to correctly generate the query prefix/suffix for substituting alternatives, but still report to the client that the composition has ended (via start & length of composition of 0) + if ((this._inputElement.value !== this._prevQueryText) || (this._prevCompositionLength === 0) || (linguisticDetails.queryTextCompositionLength > 0)) { + this._prevCompositionStart = linguisticDetails.queryTextCompositionStart; + this._prevCompositionLength = linguisticDetails.queryTextCompositionLength; + } + + if ((this._prevQueryText === this._inputElement.value) && !hasLinguisticDetailsChanged) { + // Sometimes the input change is fired even if there is no change in input. + // Swallow event in those cases. + return; + } + this._prevQueryText = this._inputElement.value; + + // get the most up to date value of the input langauge from WinRT if available + if (_WinRT.Windows.Globalization.Language) { + this._lastKeyPressLanguage = _WinRT.Windows.Globalization.Language.currentInputMethodLanguageTag; + } + + if (_WinRT.Windows.Data.Text.SemanticTextQuery) { + if (this._inputElement.value !== "") { + this._hitFinder = new _WinRT.Windows.Data.Text.SemanticTextQuery(this._inputElement.value, this._lastKeyPressLanguage); + } else { + this._hitFinder = null; + } + } + + this._fireEvent(EventNames.querychanged, { + language: this._lastKeyPressLanguage, + queryText: this._inputElement.value, + linguisticDetails: linguisticDetails + }); + + this._suggestionManager.setQuery( + this._inputElement.value, + this._lastKeyPressLanguage, + linguisticDetails + ); + } + }, + + _inputPointerDownHandler: function asb_inputPointerDownHandler() { + if ((_Global.document.activeElement === this._inputElement) && (this._currentSelectedIndex !== -1)) { + this._currentFocusedIndex = -1; + this._selectSuggestionAtIndex(this._currentFocusedIndex); + } + }, + + _keyDownHandler: function asb_keyDownHandler(event) { + var that = this; + function setSelection(index) { + that._currentFocusedIndex = index; + that._selectSuggestionAtIndex(index); + event.preventDefault(); + event.stopPropagation(); + } + + this._lastKeyPressLanguage = event.locale; + if (event.keyCode === Key.tab) { + this._isProcessingTabKey = true; + } else if (event.keyCode === Key.upArrow) { + this._isProcessingUpKey = true; + } else if (event.keyCode === Key.downArrow) { + this._isProcessingDownKey = true; + } else if ((event.keyCode === Key.enter) && (event.locale === "ko")) { + this._isProcessingEnterKey = true; + } + // Ignore keys handled by ime. + if (event.keyCode !== Key.IME) { + if (event.keyCode === Key.tab) { + var closeFlyout = true; + if (event.shiftKey) { + if (this._currentFocusedIndex !== -1) { + // Focus is not in input + setSelection(-1); + closeFlyout = false; + } + } else if (this._currentFocusedIndex === -1) { + this._currentFocusedIndex = + this._flyoutBelowInput + ? this._findNextSuggestionElementIndex(this._currentFocusedIndex) + : this._findPreviousSuggestionElementIndex(this._suggestionsData.length); + if (this._currentFocusedIndex !== -1) { + // Found a selectable element + setSelection(this._currentFocusedIndex); + this._updateQueryTextWithSuggestionText(this._currentFocusedIndex); + closeFlyout = false; + } + } + + if (closeFlyout) { + this._hideFlyout(); + } + } else if (event.keyCode === Key.escape) { + if (this._currentFocusedIndex !== -1) { + // Focus is not in input + this.queryText = this._prevQueryText; + setSelection(-1); + } else if (this.queryText !== "") { + this.queryText = ""; + this._inputOrImeChangeHandler(null); + event.preventDefault(); + event.stopPropagation(); + } + } else if ((this._flyoutBelowInput && event.keyCode === Key.upArrow) || (!this._flyoutBelowInput && event.keyCode === Key.downArrow)) { + var prevIndex; + if (this._currentSelectedIndex !== -1) { + prevIndex = this._findPreviousSuggestionElementIndex(this._currentSelectedIndex); + // Restore user entered query when user navigates back to input. + if (prevIndex === -1) { + this.queryText = this._prevQueryText; + } + } else { + prevIndex = this._findPreviousSuggestionElementIndex(this._suggestionsData.length); + } + setSelection(prevIndex); + this._updateQueryTextWithSuggestionText(this._currentFocusedIndex); + } else if ((this._flyoutBelowInput && event.keyCode === Key.downArrow) || (!this._flyoutBelowInput && event.keyCode === Key.upArrow)) { + var nextIndex = this._findNextSuggestionElementIndex(this._currentSelectedIndex); + // Restore user entered query when user navigates back to input. + if ((this._currentSelectedIndex !== -1) && (nextIndex === -1)) { + this.queryText = this._prevQueryText; + } + setSelection(nextIndex); + this._updateQueryTextWithSuggestionText(this._currentFocusedIndex); + } else if (event.keyCode === Key.enter) { + if (this._currentSelectedIndex === -1) { + this._submitQuery(this._inputElement.value, true /*fillLinguisticDetails*/, event); + } else { + this._processSuggestionChosen(this._suggestionsData.getAt(this._currentSelectedIndex), event); + } + this._hideFlyout(); + } + } + }, + + _keyUpHandler: function asb_keyUpHandler(event) { + if (event.keyCode === Key.tab) { + this._isProcessingTabKey = false; + } else if (event.keyCode === Key.upArrow) { + this._isProcessingUpKey = false; + } else if (event.keyCode === Key.downArrow) { + this._isProcessingDownKey = false; + } else if (event.keyCode === Key.enter) { + this._isProcessingEnterKey = false; + } + }, + + _keyPressHandler: function asb_keyPressHandler(event) { + this._lastKeyPressLanguage = event.locale; + }, + + _msCandidateWindowHideHandler: function asb_msCandidateWindowHideHandler() { + if (!this._isFlyoutPointerDown) { + var animation = Animations.createRepositionAnimation(this._flyoutElement); + this._flyoutElement.style.marginTop = ""; + this._flyoutElement.style.marginLeft = ""; + animation.execute(); + } else { + this._reflowImeOnPointerRelease = true; + } + }, + + _msCandidateWindowShowHandler: function asb_msCandidateWindowShowHandler() { + this._addFlyoutIMEPaddingIfRequired(); + this._reflowImeOnPointerRelease = false; + }, + + _suggestionsChangedHandler: function asb_suggestionsChangedHandler(event) { + var collectionChange = event.collectionChange || event.detail.collectionChange; + var changeIndex = (+event.index === event.index) ? event.index : event.detail.index; + var ChangeEnum = _SuggestionManagerShim._CollectionChange; + if (collectionChange === ChangeEnum.reset) { + if (this._isFlyoutShown()) { + this._hideFlyout(); + } + this._suggestionsData.splice(0, this._suggestionsData.length); + } else if (collectionChange === ChangeEnum.itemInserted) { + var suggestion = this._suggestions[changeIndex]; + this._suggestionsData.splice(changeIndex, 0, suggestion); + + this._showFlyout(); + + } else if (collectionChange === ChangeEnum.itemRemoved) { + if ((this._suggestionsData.length === 1)) { + _ElementUtilities._setActive(this._inputElement); + + this._hideFlyout(); + } + this._suggestionsData.splice(changeIndex, 1); + } else if (collectionChange === ChangeEnum.itemChanged) { + var suggestion = this._suggestions[changeIndex]; + if (suggestion !== this._suggestionsData.getAt(changeIndex)) { + this._suggestionsData.setAt(changeIndex, suggestion); + } else { + // If the suggestions manager gives us an identical item, it means that only the hit highlighted text has changed. + var existingElement = this._repeater.elementFromIndex(changeIndex); + if (_ElementUtilities.hasClass(existingElement, ClassNames.asbSuggestionQuery)) { + addHitHighlightedText(existingElement, suggestion, suggestion.text); + } else { + var resultSuggestionDiv = existingElement.querySelector("." + ClassNames.asbSuggestionResultText); + if (resultSuggestionDiv) { + addHitHighlightedText(resultSuggestionDiv, suggestion, suggestion.text); + var resultSuggestionDetailDiv = existingElement.querySelector("." + ClassNames.asbSuggestionResultDetailedText); + if (resultSuggestionDetailDiv) { + addHitHighlightedText(resultSuggestionDetailDiv, suggestion, suggestion.detailText); + } + } + } + } + } + + if (_Global.document.activeElement === this._inputElement) { + this._updateFakeFocus(); + } + }, + + _suggestionsRequestedHandler: function asb_suggestionsRequestedHandler(event) { + // get the most up to date value of the input langauge from WinRT if available + if (_WinRT.Windows.Globalization.Language) { + this._lastKeyPressLanguage = _WinRT.Windows.Globalization.Language.currentInputMethodLanguageTag; + } + + var request = event.request || event.detail.request; + var deferral; + this._fireEvent(EventNames.suggestionsrequested, { + setPromise: function (promise) { + deferral = request.getDeferral(); + promise.then(function () { + deferral.complete(); + }); + }, + searchSuggestionCollection: request.searchSuggestionCollection, + language: this._lastKeyPressLanguage, + linguisticDetails: this._getLinguisticDetails(true /*useCache*/, true /*createFilled*/), + queryText: this._inputElement.value + }); + }, + }, { + createResultSuggestionImage: function asb_createResultSuggestionImage(url) { + /// + /// + /// Creates the image argument for SearchSuggestionCollection.appendResultSuggestion. + /// + /// + /// The url of the image. + /// + /// + /// + if (_WinRT.Windows.Foundation.Uri && _WinRT.Windows.Storage.Streams.RandomAccessStreamReference) { + return _WinRT.Windows.Storage.Streams.RandomAccessStreamReference.createFromUri(new _WinRT.Windows.Foundation.Uri(url)); + } + return url; + }, + + _EventNames: EventNames, + + _sortAndMergeHits: function asb_sortAndMergeHits(hitsProvided) { + function hitStartPositionAscendingSorter(firstHit, secondHit) { + var returnValue = 0; + if (firstHit.startPosition < secondHit.startPosition) { + returnValue = -1; + } else if (firstHit.startPosition > secondHit.startPosition) { + returnValue = 1; + } + return returnValue; + } + function hitIntersectionReducer(reducedHits, nextHit, currentIndex) { + if (currentIndex === 0) { + reducedHits.push(nextHit); + } else { + var curHit = reducedHits[reducedHits.length - 1]; + var curHitEndPosition = curHit.startPosition + curHit.length; + if (nextHit.startPosition <= curHitEndPosition) { + // The next hit intersects or is next to current hit. Merge it. + var nextHitEndPosition = nextHit.startPosition + nextHit.length; + if (nextHitEndPosition > curHitEndPosition) { + curHit.length = nextHitEndPosition - curHit.startPosition; + } + } else { + // No intersection, simply add to reduced list. + reducedHits.push(nextHit); + } + } + return reducedHits; + } + + var reducedHits = []; + if (hitsProvided) { + // Copy hitsprovided array as winrt objects are immutable. + var hits = new Array(hitsProvided.length); + for (var i = 0; i < hitsProvided.length; i++) { + hits.push({ startPosition: hitsProvided[i].startPosition, length: hitsProvided[i].length }); + } + hits.sort(hitStartPositionAscendingSorter); + hits.reduce(hitIntersectionReducer, reducedHits); + } + return reducedHits; + } + }); + + function addHitHighlightedText(element, item, text, hitFinder) { + function addNewSpan(element, textContent, insertBefore) { + // Adds new span element with specified inner text as child to element, placed before insertBefore + var spanElement = _Global.document.createElement("span"); + spanElement.textContent = textContent; + spanElement.setAttribute("aria-hidden", "true"); + spanElement.classList.add(ClassNames.asbHitHighlightSpan); + element.insertBefore(spanElement, insertBefore); + return spanElement; + } + + if (text) { + // Remove any existing hit highlighted text spans + _ElementListUtilities.query("." + ClassNames.asbHitHighlightSpan, element).forEach(function (childElement) { + childElement.parentNode.removeChild(childElement); + }); + + // Insert spans at the front of element + var firstChild = element.firstChild; + + var hitsProvided = item.hits; + if ((!hitsProvided) && (hitFinder) && (item.kind !== _SuggestionManagerShim._SearchSuggestionKind.Separator)) { + hitsProvided = hitFinder.find(text); + } + + var hits = AutoSuggestBox._sortAndMergeHits(hitsProvided); + + var lastPosition = 0; + for (var i = 0; i < hits.length; i++) { + var hit = hits[i]; + + // Add previous normal text + addNewSpan(element, text.substring(lastPosition, hit.startPosition), firstChild); + + lastPosition = hit.startPosition + hit.length; + + // Add hit highlighted text + var spanHitHighlightedText = addNewSpan(element, text.substring(hit.startPosition, lastPosition), firstChild); + _ElementUtilities.addClass(spanHitHighlightedText, ClassNames.asbBoxFlyoutHighlightText); + } + + // Add final normal text + if (lastPosition < text.length) { + addNewSpan(element, text.substring(lastPosition), firstChild); + } + } + } + + function getKeyModifiers(ev) { + // Returns the same value as http://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.system.virtualkeymodifiers + var VirtualKeys = { + ctrlKey: 1, + altKey: 2, + shiftKey: 4 + }; + + var keyModifiers = 0; + if (ev.ctrlKey) { + keyModifiers |= VirtualKeys.ctrlKey; + } + if (ev.altKey) { + keyModifiers |= VirtualKeys.altKey; + } + if (ev.shiftKey) { + keyModifiers |= VirtualKeys.shiftKey; + } + return keyModifiers; + } + + function resultSuggestionRenderer(asb, item) { + function handleInvoke(e) { + asb._internalFocusMove = true; + asb._inputElement.focus(); + asb._processSuggestionChosen(item, e); + } + + var root = _Global.document.createElement("div"); + var image = new _Global.Image(); + image.style.opacity = 0; + var loadImage = function (url) { + function onload() { + image.removeEventListener("load", onload, false); + Animations.fadeIn(image); + } + image.addEventListener("load", onload, false); + image.src = url; + }; + + if (item.image !== null) { + item.image.openReadAsync().then(function (streamWithContentType) { + if (streamWithContentType !== null) { + loadImage(_Global.URL.createObjectURL(streamWithContentType, { oneTimeOnly: true })); + } + }); + } else if (item.imageUrl !== null) { + loadImage(item.imageUrl); + } + image.setAttribute("aria-hidden", "true"); + root.appendChild(image); + + var divElement = _Global.document.createElement("div"); + _ElementUtilities.addClass(divElement, ClassNames.asbSuggestionResultText); + addHitHighlightedText(divElement, item, item.text); + divElement.title = item.text; + divElement.setAttribute("aria-hidden", "true"); + root.appendChild(divElement); + + var brElement = _Global.document.createElement("br"); + divElement.appendChild(brElement); + + var divDetailElement = _Global.document.createElement("span"); + _ElementUtilities.addClass(divDetailElement, ClassNames.asbSuggestionResultDetailedText); + addHitHighlightedText(divDetailElement, item, item.detailText); + divDetailElement.title = item.detailText; + divDetailElement.setAttribute("aria-hidden", "true"); + divElement.appendChild(divDetailElement); + + _ElementUtilities.addClass(root, ClassNames.asbSuggestionResult); + + _ElementUtilities._addEventListener(root, "click", function (e) { + if (!asb._isFlyoutPointerDown) { + handleInvoke(e); + } + }); + _ElementUtilities._addEventListener(root, "pointerup", handleInvoke); + + root.setAttribute("role", "option"); + var ariaLabel = _Resources._formatString(Strings.ariaLabelResult, item.text, item.detailText); + root.setAttribute("aria-label", ariaLabel); + return root; + } + + function querySuggestionRenderer(asb, item) { + function handleInvoke(e) { + asb._internalFocusMove = true; + asb._inputElement.focus(); + asb._processSuggestionChosen(item, e); + } + + var root = _Global.document.createElement("div"); + + addHitHighlightedText(root, item, item.text); + root.title = item.text; + + root.classList.add(ClassNames.asbSuggestionQuery); + + _ElementUtilities._addEventListener(root, "click", function (e) { + if (!asb._isFlyoutPointerDown) { + handleInvoke(e); + } + }); + _ElementUtilities._addEventListener(root, "pointerup", handleInvoke); + + var ariaLabel = _Resources._formatString(Strings.ariaLabelQuery, item.text); + root.setAttribute("role", "option"); + root.setAttribute("aria-label", ariaLabel); + + return root; + } + + function separatorSuggestionRenderer(item) { + var root = _Global.document.createElement("div"); + if (item.text.length > 0) { + var textElement = _Global.document.createElement("div"); + textElement.textContent = item.text; + textElement.title = item.text; + textElement.setAttribute("aria-hidden", "true"); + root.appendChild(textElement); + } + root.insertAdjacentHTML("beforeend", "
"); + _ElementUtilities.addClass(root, ClassNames.asbSuggestionSeparator); + root.setAttribute("role", "separator"); + var ariaLabel = _Resources._formatString(Strings.ariaLabelSeparator, item.text); + root.setAttribute("aria-label", ariaLabel); + return root; + } + + _Base.Class.mix(AutoSuggestBox, _Control.DOMEventMixin); + return AutoSuggestBox; + }) + }); + exports.ClassNames = ClassNames; +}); + + +define('require-style!less/styles-searchbox',[],function(){}); + +define('require-style!less/colors-searchbox',[],function(){}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('WinJS/Controls/SearchBox',[ + '../Core/_Global', + '../Core/_WinRT', + '../Core/_Base', + '../Core/_ErrorFromName', + '../Core/_Events', + '../Core/_Resources', + './AutoSuggestBox', + '../_Accents', + '../Utilities/_Control', + '../Utilities/_ElementUtilities', + './AutoSuggestBox/_SearchSuggestionManagerShim', + '../Application', + 'require-style!less/styles-searchbox', + 'require-style!less/colors-searchbox' +], function searchboxInit(_Global, _WinRT, _Base, _ErrorFromName, _Events, _Resources, AutoSuggestBox, _Accents, _Control, _ElementUtilities, _SuggestionManagerShim, Application) { + "use strict"; + + _Accents.createAccentRule("html.win-hoverable .win-searchbox-button:not(.win-searchbox-button-disabled):hover", [{ name: "color", value: _Accents.ColorTypes.accent }, ]); + _Accents.createAccentRule(".win-searchbox-button.win-searchbox-button:not(.win-searchbox-button-disabled):hover:active", [{ name: "background-color", value: _Accents.ColorTypes.accent }, ]); + + _Base.Namespace.define("WinJS.UI", { + /// + /// + /// Enables the user to perform search queries and select suggestions. + /// + /// + /// + /// + /// + /// ]]> + /// + /// Raised when the app automatically redirects focus to the search box. This event can only be raised when the focusOnKeyboardInput property is set to true. + /// + /// Styles the entire Search box control. + /// Styles the query input box. + /// Styles the search button. + /// Styles the result suggestions flyout. + /// Styles the result type suggestion. + /// Styles the query type suggestion. + /// + /// Styles the separator type suggestion. + /// + /// + /// Styles the currently selected suggestion. + /// + /// + /// + SearchBox: _Base.Namespace._lazy(function () { + + // Enums + var ClassName = { + searchBox: "win-searchbox", + searchBoxDisabled: "win-searchbox-disabled", + searchBoxInput: "win-searchbox-input", + searchBoxInputFocus: "win-searchbox-input-focus", + searchBoxButton: "win-searchbox-button", + searchBoxFlyout: "win-searchbox-flyout", + searchBoxFlyoutHighlightText: "win-searchbox-flyout-highlighttext", + searchBoxHitHighlightSpan: "win-searchbox-hithighlight-span", + searchBoxSuggestionResult: "win-searchbox-suggestion-result", + searchBoxSuggestionResultText: "win-searchbox-suggestion-result-text", + searchBoxSuggestionResultDetailedText: "win-searchbox-suggestion-result-detailed-text", + searchBoxSuggestionSelected: "win-searchbox-suggestion-selected", + searchBoxSuggestionQuery: "win-searchbox-suggestion-query", + searchBoxSuggestionSeparator: "win-searchbox-suggestion-separator", + searchBoxButtonInputFocus: "win-searchbox-button-input-focus", + searchBoxButtonDisabled: "win-searchbox-button-disabled" + }; + + var EventName = { + receivingfocusonkeyboardinput: "receivingfocusonkeyboardinput" + }; + + var strings = { + get invalidSearchBoxSuggestionKind() { return "Error: Invalid search suggestion kind."; }, + get ariaLabel() { return _Resources._getWinJSString("ui/searchBoxAriaLabel").value; }, + get ariaLabelInputNoPlaceHolder() { return _Resources._getWinJSString("ui/searchBoxAriaLabelInputNoPlaceHolder").value; }, + get ariaLabelInputPlaceHolder() { return _Resources._getWinJSString("ui/searchBoxAriaLabelInputPlaceHolder").value; }, + get searchBoxDeprecated() { return "SearchBox is deprecated and may not be available in future releases. Instead use AutoSuggestBox."; } + }; + + var SearchBox = _Base.Class.derive(AutoSuggestBox.AutoSuggestBox, function SearchBox_ctor(element, options) { + /// + /// + /// Creates a new SearchBox. + /// + /// + /// The DOM element that hosts the SearchBox. + /// + /// + /// An object that contains one or more property/value pairs to apply to the new control. + /// Each property of the options object corresponds to one of the control's properties or events. + /// Event names must begin with "on". For example, to provide a handler for the querychanged event, + /// add a property named "onquerychanged" to the options object and set its value to the event handler. + /// This parameter is optional. + /// + /// + /// The new SearchBox. + /// + /// + /// SearchBox is deprecated and may not be available in future releases. Instead use AutoSuggestBox. + /// + /// + /// + + _ElementUtilities._deprecated(strings.searchBoxDeprecated); + + this._requestingFocusOnKeyboardInputHandlerBind = this._requestingFocusOnKeyboardInputHandler.bind(this); + + // Elements + this._buttonElement = _Global.document.createElement("div"); + + // Variables + this._focusOnKeyboardInput = false; + + // Calling the super constructor - since the super constructor processes the options, + // any property setter at this point must be functional. + AutoSuggestBox.AutoSuggestBox.call(this, element, options); + + // Add SearchBox classes to DOM elements + this.element.classList.add(ClassName.searchBox); + this._flyoutElement.classList.add(ClassName.searchBoxFlyout); + + this._inputElement.classList.add(ClassName.searchBoxInput); + this._inputElement.addEventListener("blur", this._searchboxInputBlurHandler.bind(this)); + this._inputElement.addEventListener("focus", this._searchboxInputFocusHandler.bind(this)); + + this._buttonElement.tabIndex = -1; + this._buttonElement.classList.add(ClassName.searchBoxButton); + this._buttonElement.addEventListener("click", this._buttonClickHandler.bind(this)); + _ElementUtilities._addEventListener(this._buttonElement, "pointerdown", this._buttonPointerDownHandler.bind(this)); + this.element.appendChild(this._buttonElement); + }, { + /// + /// Enable automatically focusing the search box when the user types into the app window (off by default) While this is enabled, + /// input on the current thread will be intercepted and redirected to the search box. Only textual input will trigger the search box to focus. + /// The caller will continue to receive non-text keys (such as arrows, tab, etc + /// This will also not affect WIN/CTRL/ALT key combinations (except for Ctrl-V for paste). + /// If the client needs more to happen than just set focus in the box (make control visible, etc.), they will need to handle the event. + /// If enabled, the app must be sure to disable this if the user puts focus in some other edit field. + /// + /// + focusOnKeyboardInput: { + get: function () { + return this._focusOnKeyboardInput; + }, + set: function (value) { + if (this._focusOnKeyboardInput && !value) { + Application._applicationListener.removeEventListener(this.element, "requestingfocusonkeyboardinput", this._requestingFocusOnKeyboardInputHandlerBind); + } else if (!this._focusOnKeyboardInput && !!value) { + Application._applicationListener.addEventListener(this.element, "requestingfocusonkeyboardinput", this._requestingFocusOnKeyboardInputHandlerBind); + } + this._focusOnKeyboardInput = !!value; + } + }, + + // Methods + dispose: function SearchBox() { + /// + /// + /// Disposes this control. + /// + /// + /// + if (this._disposed) { + return; + } + AutoSuggestBox.AutoSuggestBox.prototype.dispose.call(this); + + if (this._focusOnKeyboardInput) { + Application._applicationListener.removeEventListener(this.element, "requestingfocusonkeyboardinput", this._requestingFocusOnKeyboardInputHandlerBind); + } + }, + + // Private methods + _disableControl: function SearchBox_disableControl() { + AutoSuggestBox.AutoSuggestBox.prototype._disableControl.call(this); + this._buttonElement.disabled = true; + this._buttonElement.classList.add(ClassName.searchBoxButtonDisabled); + this.element.classList.add(ClassName.searchBoxDisabled); + }, + + _enableControl: function SearchBox_enableControl() { + AutoSuggestBox.AutoSuggestBox.prototype._enableControl.call(this); + this._buttonElement.disabled = false; + this._buttonElement.classList.remove(ClassName.searchBoxButtonDisabled); + this.element.classList.remove(ClassName.searchBoxDisabled); + }, + + _renderSuggestion: function SearchBox_renderSuggestion(suggestion) { + // Overrides base class + var render = AutoSuggestBox.AutoSuggestBox.prototype._renderSuggestion.call(this, suggestion); + if (suggestion.kind === _SuggestionManagerShim._SearchSuggestionKind.Query) { + render.classList.add(ClassName.searchBoxSuggestionQuery); + } else if (suggestion.kind === _SuggestionManagerShim._SearchSuggestionKind.Separator) { + render.classList.add(ClassName.searchBoxSuggestionSeparator); + } else { + render.classList.add(ClassName.searchBoxSuggestionResult); + + var resultText = render.querySelector("." + AutoSuggestBox.ClassNames.asbSuggestionResultText); + resultText.classList.add(ClassName.searchBoxSuggestionResultText); + + var resultDetailText = render.querySelector("." + AutoSuggestBox.ClassNames.asbSuggestionResultDetailedText); + resultDetailText.classList.add(ClassName.searchBoxSuggestionResultDetailedText); + + var spans = render.querySelectorAll("." + AutoSuggestBox.ClassNames.asbHitHighlightSpan); + for (var i = 0, len = spans.length; i < len; i++) { + spans[i].classList.add(ClassName.searchBoxHitHighlightSpan); + } + var highlightTexts = render.querySelectorAll("." + AutoSuggestBox.ClassNames.asbBoxFlyoutHighlightText); + for (var i = 0, len = highlightTexts.length; i < len; i++) { + highlightTexts[i].classList.add(ClassName.searchBoxFlyoutHighlightText); + } + } + return render; + }, + + _selectSuggestionAtIndex: function SearchBox_selectSuggestionAtIndex(indexToSelect) { + // Overrides base class + AutoSuggestBox.AutoSuggestBox.prototype._selectSuggestionAtIndex.call(this, indexToSelect); + + var currentSelected = this.element.querySelector("." + ClassName.searchBoxSuggestionSelected); + currentSelected && currentSelected.classList.remove(ClassName.searchBoxSuggestionSelected); + var newSelected = this.element.querySelector("." + AutoSuggestBox.ClassNames.asbSuggestionSelected); + newSelected && newSelected.classList.add(ClassName.searchBoxSuggestionSelected); + }, + + _shouldIgnoreInput: function SearchBox_shouldIgnoreInput() { + // Overrides base class + var shouldIgnore = AutoSuggestBox.AutoSuggestBox.prototype._shouldIgnoreInput(); + var isButtonDown = _ElementUtilities._matchesSelector(this._buttonElement, ":active"); + + return shouldIgnore || isButtonDown; + }, + + _updateInputElementAriaLabel: function SearchBox_updateInputElementAriaLabel() { + // Override base class + this._inputElement.setAttribute("aria-label", + this._inputElement.placeholder ? _Resources._formatString(strings.ariaLabelInputPlaceHolder, this._inputElement.placeholder) : strings.ariaLabelInputNoPlaceHolder + ); + }, + + // Event Handlers + _buttonPointerDownHandler: function SearchBox_buttonPointerDownHandler(e) { + this._inputElement.focus(); + e.preventDefault(); + }, + + _buttonClickHandler: function SearchBox_buttonClickHandler(event) { + this._inputElement.focus(); + this._submitQuery(this._inputElement.value, true /*fillLinguisticDetails*/, event); + this._hideFlyout(); + }, + + _searchboxInputBlurHandler: function SearchBox_inputBlurHandler() { + _ElementUtilities.removeClass(this.element, ClassName.searchBoxInputFocus); + _ElementUtilities.removeClass(this._buttonElement, ClassName.searchBoxButtonInputFocus); + }, + + _searchboxInputFocusHandler: function SearchBox_inputFocusHandler() { + _ElementUtilities.addClass(this.element, ClassName.searchBoxInputFocus); + _ElementUtilities.addClass(this._buttonElement, ClassName.searchBoxButtonInputFocus); + }, + + // Type to search helpers + _requestingFocusOnKeyboardInputHandler: function SearchBox_requestingFocusOnKeyboardInputHandler() { + this._fireEvent(EventName.receivingfocusonkeyboardinput, null); + if (_Global.document.activeElement !== this._inputElement) { + try { + this._inputElement.focus(); + } catch (e) { + } + } + } + + }, { + createResultSuggestionImage: function SearchBox_createResultSuggestionImage(url) { + /// + /// + /// Creates the image argument for SearchSuggestionCollection.appendResultSuggestion. + /// + /// + /// The url of the image. + /// + /// + /// + if (_WinRT.Windows.Foundation.Uri && _WinRT.Windows.Storage.Streams.RandomAccessStreamReference) { + return _WinRT.Windows.Storage.Streams.RandomAccessStreamReference.createFromUri(new _WinRT.Windows.Foundation.Uri(url)); + } + return url; + }, + + _getKeyModifiers: function SearchBox_getKeyModifiers(ev) { + // Returns the same value as http://msdn.microsoft.com/en-us/library/windows/apps/xaml/windows.system.virtualkeymodifiers + var VirtualKeys = { + ctrlKey: 1, + altKey: 2, + shiftKey: 4 + }; + + var keyModifiers = 0; + if (ev.ctrlKey) { + keyModifiers |= VirtualKeys.ctrlKey; + } + if (ev.altKey) { + keyModifiers |= VirtualKeys.altKey; + } + if (ev.shiftKey) { + keyModifiers |= VirtualKeys.shiftKey; + } + return keyModifiers; + }, + + _isTypeToSearchKey: function searchBox__isTypeToSearchKey(event) { + if (event.shiftKey || event.ctrlKey || event.altKey) { + return false; + } + return true; + } + }); + _Base.Class.mix(SearchBox, _Control.DOMEventMixin); + return SearchBox; + }) + }); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// appbar,Flyout,Flyouts,registeredforsettings,SettingsFlyout,Statics,Syriac +define('WinJS/Controls/SettingsFlyout',[ + '../Core/_Global', + '../Core/_WinRT', + '../Core/_Base', + '../Core/_BaseUtils', + '../Core/_ErrorFromName', + '../Core/_Events', + '../Core/_Resources', + '../Core/_WriteProfilerMark', + '../Animations', + '../Pages', + '../Promise', + '../_LightDismissService', + '../Utilities/_Dispose', + '../Utilities/_ElementUtilities', + '../Utilities/_ElementListUtilities', + '../Utilities/_Hoverable', + './_LegacyAppBar/_Constants', + './Flyout/_Overlay' + ], function settingsFlyoutInit(_Global, _WinRT, _Base, _BaseUtils, _ErrorFromName, _Events, _Resources, _WriteProfilerMark, Animations, Pages, Promise, _LightDismissService, _Dispose, _ElementUtilities, _ElementListUtilities, _Hoverable, _Constants, _Overlay) { + "use strict"; + + _Base.Namespace.define("WinJS.UI", { + /// + /// Provides users with fast, in-context access to settings that affect the current app. + /// + /// + /// Settings Flyout + /// + /// + /// + ///
+ /// + ///
Custom Settings
+ ///
+ ///
+ /// {Your Content Here} + ///
+ /// ]]>
+ /// Raised just before showing a SettingsFlyout. + /// Raised immediately after a SettingsFlyout is fully shown. + /// Raised just before hiding a SettingsFlyout. + /// Raised immediately after a SettingsFlyout is fully hidden. + /// The SettingsFlyout control itself. + /// + /// + SettingsFlyout: _Base.Namespace._lazy(function () { + var Key = _ElementUtilities.Key; + + var createEvent = _Events._createEventProperty; + + var settingsPageIsFocusedOnce; + + // Constants for width + var settingsNarrow = "narrow", + settingsWide = "wide"; + + // Determine if the settings pane (system language) is RTL or not. + function _shouldAnimateFromLeft() { + if (_WinRT.Windows.UI.ApplicationSettings.SettingsEdgeLocation) { + var appSettings = _WinRT.Windows.UI.ApplicationSettings; + return (appSettings.SettingsPane.edge === appSettings.SettingsEdgeLocation.left); + } else { + return false; + } + } + + // Get the settings control by matching the settingsCommandId + // if no match we'll try to match element id + function _getChildSettingsControl(parentElement, id) { + var settingElements = parentElement.querySelectorAll("." + _Constants.settingsFlyoutClass); + var retValue, + control; + for (var i = 0; i < settingElements.length; i++) { + control = settingElements[i].winControl; + if (control) { + if (control.settingsCommandId === id) { + retValue = control; + break; + } + if (settingElements[i].id === id) { + retValue = retValue || control; + } + } + } + + return retValue; + } + + var SettingsFlyout = _Base.Class.derive(_Overlay._Overlay, function SettingsFlyout_ctor(element, options) { + /// + /// Creates a new SettingsFlyout control. + /// + /// The DOM element that will host the control. + /// + /// + /// The set of properties and values to apply to the new SettingsFlyout. + /// + /// The new SettingsFlyout control. + /// + /// SettingsFlyout is deprecated and may not be available in future releases. Instead, put + /// settings on their own page within the app. + /// + /// + /// + + _ElementUtilities._deprecated(strings.settingsFlyoutIsDeprecated); + + // Make sure there's an input element + this._element = element || _Global.document.createElement("div"); + this._id = this._element.id || _ElementUtilities._uniqueID(this._element); + this._writeProfilerMark("constructor,StartTM"); + + // Call the base overlay constructor helper + this._baseOverlayConstructor(this._element, options); + + this._addFirstDiv(); + this._addFinalDiv(); + + // Handle "esc" & "tab" key presses + this._element.addEventListener("keydown", this._handleKeyDown, true); + + // Start settings hidden + this._element.style.visibilty = "hidden"; + this._element.style.display = "none"; + + // Attach our css class + _ElementUtilities.addClass(this._element, _Constants.settingsFlyoutClass); + + var that = this; + this._dismissable = new _LightDismissService.LightDismissableElement({ + element: this._element, + tabIndex: this._element.hasAttribute("tabIndex") ? this._element.tabIndex : -1, + onLightDismiss: function () { + that.hide(); + }, + onTakeFocus: function (useSetActive) { + if (!that._dismissable.restoreFocus()) { + var firstDiv = that.element.querySelector("." + _Constants.firstDivClass); + if (firstDiv) { + if (!firstDiv.msSettingsFlyoutFocusOut) { + _ElementUtilities._addEventListener(firstDiv, "focusout", function () { settingsPageIsFocusedOnce = 1; }, false); + firstDiv.msSettingsFlyoutFocusOut = true; + } + + settingsPageIsFocusedOnce = 0; + _ElementUtilities._tryFocus(firstDiv, useSetActive); + } + } + }, + }); + + // apply the light theme styling to the win-content elements inside the SettingsFlyout + _ElementListUtilities.query("div.win-content", this._element). + forEach(function (e) { + if (!_ElementUtilities._matchesSelector(e, '.win-ui-dark, .win-ui-dark *')){ + _ElementUtilities.addClass(e, _Constants.flyoutLightClass); + } + }); + + // Make sure we have an ARIA role + var role = this._element.getAttribute("role"); + if (role === null || role === "" || role === undefined) { + this._element.setAttribute("role", "dialog"); + } + var label = this._element.getAttribute("aria-label"); + if (label === null || label === "" || label === undefined) { + this._element.setAttribute("aria-label", strings.ariaLabel); + } + + // Make sure animations are hooked up + this._currentAnimateIn = this._animateSlideIn; + this._currentAnimateOut = this._animateSlideOut; + this._writeProfilerMark("constructor,StopTM"); + }, { + // Public Properties + + /// + /// Width of the SettingsFlyout, "narrow", or "wide". + /// + /// SettingsFlyout.width may be altered or unavailable in future versions. Instead, style the CSS width property on elements with the .win-settingsflyout class. + /// + /// + /// + width: { + get: function () { + return this._width; + }, + + set: function (value) { + _ElementUtilities._deprecated(strings.widthDeprecationMessage); + if (value === this._width) { + return; + } + // Get rid of old class + if (this._width === settingsNarrow) { + _ElementUtilities.removeClass(this._element, _Constants.narrowClass); + } else if (this._width === settingsWide) { + _ElementUtilities.removeClass(this._element, _Constants.wideClass); + } + this._width = value; + + // Attach our new css class + if (this._width === settingsNarrow) { + _ElementUtilities.addClass(this._element, _Constants.narrowClass); + } else if (this._width === settingsWide) { + _ElementUtilities.addClass(this._element, _Constants.wideClass); + } + } + }, + + /// + /// Define the settings command Id for the SettingsFlyout control. + /// + /// + settingsCommandId: { + get: function () { + return this._settingsCommandId; + }, + + set: function (value) { + this._settingsCommandId = value; + } + }, + + /// Disable SettingsFlyout, setting or getting the HTML disabled attribute. When disabled the SettingsFlyout will no longer display with show(), and will hide if currently visible. + disabled: { + get: function () { + // Ensure it's a boolean because we're using the DOM element to keep in-sync + return !!this._element.disabled; + }, + set: function (value) { + // Force this check into a boolean because our current state could be a bit confused since we tie to the DOM element + value = !!value; + var oldValue = !!this._element.disabled; + if (oldValue !== value) { + this._element.disabled = value; + if (!this.hidden && this._element.disabled) { + this._dismiss(); + } + } + } + }, + + /// + /// Occurs immediately before the control is shown. + /// + onbeforeshow: createEvent(_Overlay._Overlay.beforeShow), + + /// + /// Occurs immediately after the control is shown. + /// + onaftershow: createEvent(_Overlay._Overlay.afterShow), + + /// + /// Occurs immediately before the control is hidden. + /// + onbeforehide: createEvent(_Overlay._Overlay.beforeHide), + + /// + /// Occurs immediately after the control is hidden. + /// + onafterhide: createEvent(_Overlay._Overlay.afterHide), + + show: function () { + /// + /// + /// Shows the SettingsFlyout, if hidden. + /// + /// + /// + // Just call private version to make appbar flags happy + + // Don't do anything if disabled + if (this.disabled) { + return; + } + this._writeProfilerMark("show,StartTM"); // The corresponding "stop" profiler mark is handled in _Overlay._baseEndShow(). + this._show(); + }, + + _dispose: function SettingsFlyout_dispose() { + _LightDismissService.hidden(this._dismissable); + _Dispose.disposeSubTree(this.element); + this._dismiss(); + }, + + _show: function SettingsFlyout_show() { + // We call our base "_baseShow" because SettingsFlyout overrides show + if (this._baseShow()) { + // Verify that the firstDiv and finalDiv are in the correct location. + // Move them to the correct location or add them if they are not. + if (!_ElementUtilities.hasClass(this.element.children[0], _Constants.firstDivClass)) { + var firstDiv = this.element.querySelectorAll("." + _Constants.firstDivClass); + if (firstDiv && firstDiv.length > 0) { + firstDiv.item(0).parentNode.removeChild(firstDiv.item(0)); + } + + this._addFirstDiv(); + } + + if (!_ElementUtilities.hasClass(this.element.children[this.element.children.length - 1], _Constants.finalDivClass)) { + var finalDiv = this.element.querySelectorAll("." + _Constants.finalDivClass); + if (finalDiv && finalDiv.length > 0) { + finalDiv.item(0).parentNode.removeChild(finalDiv.item(0)); + } + + this._addFinalDiv(); + } + + this._setBackButtonsAriaLabel(); + + _LightDismissService.shown(this._dismissable); + } + }, + + _setBackButtonsAriaLabel: function SettingsFlyout_setBackButtonsAriaLabel() { + var backbuttons = this.element.querySelectorAll(".win-backbutton"); + var label; + for (var i = 0; i < backbuttons.length; i++) { + label = backbuttons[i].getAttribute("aria-label"); + if (label === null || label === "" || label === undefined) { + backbuttons[i].setAttribute("aria-label", strings.backbuttonAriaLabel); + } + } + }, + + hide: function () { + /// + /// + /// Hides the SettingsFlyout, if visible, regardless of other state. + /// + /// + /// + // Just call private version to make appbar flags happy + this._writeProfilerMark("hide,StartTM"); // The corresponding "stop" profiler mark is handled in _Overlay._baseEndHide(). + this._hide(); + }, + + _hide: function SettingsFlyout_hide() { + this._baseHide(); + }, + + _beforeEndHide: function SettingsFlyout_beforeEndHide() { + _LightDismissService.hidden(this._dismissable); + }, + + // SettingsFlyout animations + _animateSlideIn: function SettingsFlyout_animateSlideIn() { + var animateFromLeft = _shouldAnimateFromLeft(); + var offset = animateFromLeft ? "-100px" : "100px"; + _ElementListUtilities.query("div.win-content", this._element). + forEach(function (e) { Animations.enterPage(e, { left: offset }); }); + + var where, + width = this._element.offsetWidth; + // Slide in from right side or left side? + if (animateFromLeft) { + // RTL + where = { top: "0px", left: "-" + width + "px" }; + this._element.style.right = "auto"; + this._element.style.left = "0px"; + } else { + // From right side + where = { top: "0px", left: width + "px" }; + this._element.style.right = "0px"; + this._element.style.left = "auto"; + } + + this._element.style.opacity = 1; + this._element.style.visibility = "visible"; + + return Animations.showPanel(this._element, where); + }, + + _animateSlideOut: function SettingsFlyout_animateSlideOut() { + var where, + width = this._element.offsetWidth; + if (_shouldAnimateFromLeft()) { + // RTL + where = { top: "0px", left: width + "px" }; + this._element.style.right = "auto"; + this._element.style.left = "-" + width + "px"; + } else { + // From right side + where = { top: "0px", left: "-" + width + "px" }; + this._element.style.right = "-" + width + "px"; + this._element.style.left = "auto"; + } + + return Animations.showPanel(this._element, where); + }, + + _fragmentDiv: { + get: function SettingsFlyout_fragmentDiv_get() { + return this._fragDiv; + }, + + set: function SettingsFlyout_fragmentDiv_set(value) { + this._fragDiv = value; + } + }, + + _unloadPage: function SettingsFlyout_unloadPage(event) { + var settingsControl = event.currentTarget.winControl; + settingsControl.removeEventListener(_Overlay._Overlay.afterHide, this._unloadPage, false); + + Promise.as().then(function () { + if (settingsControl._fragmentDiv) { + _Global.document.body.removeChild(settingsControl._fragmentDiv); + settingsControl._fragmentDiv = null; + } + }); + }, + + _dismiss: function SettingsFlyout_dismiss() { + this.addEventListener(_Overlay._Overlay.afterHide, this._unloadPage, false); + this._hide(); + }, + + _handleKeyDown: function SettingsFlyout_handleKeyDown(event) { + if ((event.keyCode === Key.space || event.keyCode === Key.enter) + && (this.children[0] === _Global.document.activeElement)) { + event.preventDefault(); + event.stopPropagation(); + this.winControl._dismiss(); + } else if (event.shiftKey && event.keyCode === Key.tab + && this.children[0] === _Global.document.activeElement) { + event.preventDefault(); + event.stopPropagation(); + var _elms = this.getElementsByTagName("*"); + + for (var i = _elms.length - 2; i >= 0; i--) { + _elms[i].focus(); + + if (_elms[i] === _Global.document.activeElement) { + break; + } + } + } + }, + + _focusOnLastFocusableElementFromParent: function SettingsFlyout_focusOnLastFocusableElementFromParent() { + var active = _Global.document.activeElement; + if (!settingsPageIsFocusedOnce || !active || !_ElementUtilities.hasClass(active, _Constants.firstDivClass)) { + return; + } + + var _elms = this.parentElement.getElementsByTagName("*"); + + // There should be at least 1 element in addition to the firstDiv & finalDiv + if (_elms.length <= 2) { + return; + } + + // Get the tabIndex set to the finalDiv (which is the highest) + var _highestTabIndex = _elms[_elms.length - 1].tabIndex; + + // If there are positive tabIndices, set focus to the element with the highest tabIndex. + // Otherwise set focus to the last focusable element in DOM order. + var i; + if (_highestTabIndex) { + for (i = _elms.length - 2; i > 0; i--) { + if (_elms[i].tabIndex === _highestTabIndex) { + _elms[i].focus(); + break; + } + } + } else { + for (i = _elms.length - 2; i > 0; i--) { + // Skip
with undefined tabIndex (To work around Win8 bug #622245) + if ((_elms[i].tagName !== "DIV") || (_elms[i].getAttribute("tabIndex") !== null)) { + _elms[i].focus(); + + if (_elms[i] === _Global.document.activeElement) { + break; + } + } + } + } + }, + + _focusOnFirstFocusableElementFromParent: function SettingsFlyout_focusOnFirstFocusableElementFromParent() { + var active = _Global.document.activeElement; + if (!active || !_ElementUtilities.hasClass(active, _Constants.finalDivClass)) { + return; + } + var _elms = this.parentElement.getElementsByTagName("*"); + + // There should be at least 1 element in addition to the firstDiv & finalDiv + if (_elms.length <= 2) { + return; + } + + // Get the tabIndex set to the firstDiv (which is the lowest) + var _lowestTabIndex = _elms[0].tabIndex; + + // If there are positive tabIndices, set focus to the element with the lowest tabIndex. + // Otherwise set focus to the first focusable element in DOM order. + var i; + if (_lowestTabIndex) { + for (i = 1; i < _elms.length - 1; i++) { + if (_elms[i].tabIndex === _lowestTabIndex) { + _elms[i].focus(); + break; + } + } + } else { + for (i = 1; i < _elms.length - 1; i++) { + // Skip
with undefined tabIndex (To work around Win8 bug #622245) + if ((_elms[i].tagName !== "DIV") || (_elms[i].getAttribute("tabIndex") !== null)) { + _elms[i].focus(); + + if (_elms[i] === _Global.document.activeElement) { + break; + } + } + } + } + }, + + // Create and add a new first div to the beginning of the list + _addFirstDiv: function SettingsFlyout_addFirstDiv() { + var _elms = this._element.getElementsByTagName("*"); + var _minTab = 0; + for (var i = 0; i < _elms.length; i++) { + if ((0 < _elms[i].tabIndex) && (_minTab === 0 || _elms[i].tabIndex < _minTab)) { + _minTab = _elms[i].tabIndex; + } + } + var firstDiv = _Global.document.createElement("div"); + firstDiv.className = _Constants.firstDivClass; + firstDiv.style.display = "inline"; + firstDiv.setAttribute("role", "menuitem"); + firstDiv.setAttribute("aria-hidden", "true"); + firstDiv.tabIndex = _minTab; + _ElementUtilities._addEventListener(firstDiv, "focusin", this._focusOnLastFocusableElementFromParent, false); + + // add to beginning + if (this._element.children[0]) { + this._element.insertBefore(firstDiv, this._element.children[0]); + } else { + this._element.appendChild(firstDiv); + } + }, + + // Create and add a new final div to the end of the list + _addFinalDiv: function SettingsFlyout_addFinalDiv() { + var _elms = this._element.getElementsByTagName("*"); + var _maxTab = 0; + for (var i = 0; i < _elms.length; i++) { + if (_elms[i].tabIndex > _maxTab) { + _maxTab = _elms[i].tabIndex; + } + } + var finalDiv = _Global.document.createElement("div"); + finalDiv.className = _Constants.finalDivClass; + finalDiv.style.display = "inline"; + finalDiv.setAttribute("role", "menuitem"); + finalDiv.setAttribute("aria-hidden", "true"); + finalDiv.tabIndex = _maxTab; + _ElementUtilities._addEventListener(finalDiv, "focusin", this._focusOnFirstFocusableElementFromParent, false); + + this._element.appendChild(finalDiv); + }, + + _writeProfilerMark: function SettingsFlyout_writeProfilerMark(text) { + _WriteProfilerMark("WinJS.UI.SettingsFlyout:" + this._id + ":" + text); + } + }); + + // Statics + SettingsFlyout.show = function () { + /// + /// + /// Shows the SettingsPane UI, if hidden, regardless of other states. + /// + /// + /// + /// Show the main settings pane + if (_WinRT.Windows.UI.ApplicationSettings.SettingsPane) { + _WinRT.Windows.UI.ApplicationSettings.SettingsPane.show(); + } + // And hide the WWA one + var elements = _Global.document.querySelectorAll('div[data-win-control="WinJS.UI.SettingsFlyout"]'); + var len = elements.length; + for (var i = 0; i < len; i++) { + var settingsFlyout = elements[i].winControl; + if (settingsFlyout) { + settingsFlyout._dismiss(); + } + } + }; + + var _settingsEvent = { event: undefined }; + SettingsFlyout.populateSettings = function (e) { + /// + /// + /// Loads a portion of the SettingsFlyout. Your app calls this when the user invokes a settings command and the WinJS.Application.onsettings event occurs. + /// + /// + /// An object that contains information about the event, received from the WinJS.Application.onsettings event. The detail property of this object contains + /// the applicationcommands sub-property that you set to an array of settings commands. + /// + /// + /// + _settingsEvent.event = e.detail; + + if (_settingsEvent.event.applicationcommands) { + var n = _WinRT.Windows.UI.ApplicationSettings; + Object.keys(_settingsEvent.event.applicationcommands).forEach(function (name) { + var setting = _settingsEvent.event.applicationcommands[name]; + if (!setting.title) { setting.title = name; } + var command = new n.SettingsCommand(name, setting.title, SettingsFlyout._onSettingsCommand); + _settingsEvent.event.e.request.applicationCommands.append(command); + }); + } + }; + + SettingsFlyout._onSettingsCommand = function (command) { + var id = command.id; + if (_settingsEvent.event.applicationcommands && _settingsEvent.event.applicationcommands[id]) { + SettingsFlyout.showSettings(id, _settingsEvent.event.applicationcommands[id].href); + } + }; + + SettingsFlyout.showSettings = function (id, path) { + /// + /// + /// Show the SettingsFlyout using the settings element identifier (ID) and the path of the page that contains the settings element. + /// + /// + /// The ID of the settings element. + /// + /// + /// The path of the page that contains the settings element. + /// + /// + /// + var control = _getChildSettingsControl(_Global.document, id); + if (control) { + control.show(); + } else if (path) { + var divElement = _Global.document.createElement("div"); + divElement = _Global.document.body.appendChild(divElement); + Pages.render(path, divElement).then(function () { + control = _getChildSettingsControl(divElement, id); + if (control) { + control._fragmentDiv = divElement; + control.show(); + } else { + _Global.document.body.removeChild(divElement); + } + }); + } else { + throw new _ErrorFromName("WinJS.UI.SettingsFlyout.BadReference", strings.badReference); + } + }; + + var strings = { + get ariaLabel() { return _Resources._getWinJSString("ui/settingsFlyoutAriaLabel").value; }, + get badReference() { return "Invalid argument: Invalid href to settings flyout fragment"; }, + get backbuttonAriaLabel() { return _Resources._getWinJSString("ui/backbuttonarialabel").value; }, + get widthDeprecationMessage() { return "SettingsFlyout.width may be altered or unavailable in future versions. Instead, style the CSS width property on elements with the .win-settingsflyout class."; }, + get settingsFlyoutIsDeprecated() { return "SettingsFlyout is deprecated and may not be available in future releases. Instead, put settings on their own page within the app."; } + }; + + return SettingsFlyout; + }) + }); + + +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('WinJS/Controls/NavBar/_Command',[ + 'exports', + '../../Core/_Global', + '../../Core/_Base', + '../../Core/_ErrorFromName', + '../../Core/_Resources', + '../../ControlProcessor', + '../../Navigation', + '../../Utilities/_Control', + '../../Utilities/_ElementUtilities', + '../AppBar/_Icon' + ], function NavBarCommandInit(exports, _Global, _Base, _ErrorFromName, _Resources, ControlProcessor, Navigation, _Control, _ElementUtilities, _Icon) { + "use strict"; + + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + _WinPressed: _Base.Namespace._lazy(function () { + var WinPressed = _Base.Class.define(function _WinPressed_ctor(element) { + // WinPressed is the combination of :hover:active + // :hover is delayed by trident for touch by 300ms so if you want :hover:active to work quickly you need to + // use this behavior. + // :active does not bubble to its parent like :hover does so this is also useful for that scenario. + this._element = element; + _ElementUtilities._addEventListener(this._element, "pointerdown", this._MSPointerDownButtonHandler.bind(this)); + }, { + _MSPointerDownButtonHandler: function _WinPressed_MSPointerDownButtonHandler(ev) { + if (!this._pointerUpBound) { + this._pointerUpBound = this._MSPointerUpHandler.bind(this); + this._pointerCancelBound = this._MSPointerCancelHandler.bind(this); + this._pointerOverBound = this._MSPointerOverHandler.bind(this); + this._pointerOutBound = this._MSPointerOutHandler.bind(this); + } + + if (ev.isPrimary) { + if (this._pointerId) { + this._resetPointer(); + } + + if (!_ElementUtilities._matchesSelector(ev.target, ".win-interactive, .win-interactive *")) { + this._pointerId = ev.pointerId; + + _ElementUtilities._addEventListener(_Global, "pointerup", this._pointerUpBound, true); + _ElementUtilities._addEventListener(_Global, "pointercancel", this._pointerCancelBound), true; + _ElementUtilities._addEventListener(this._element, "pointerover", this._pointerOverBound, true); + _ElementUtilities._addEventListener(this._element, "pointerout", this._pointerOutBound, true); + + _ElementUtilities.addClass(this._element, WinPressed.winPressed); + } + } + }, + + _MSPointerOverHandler: function _WinPressed_MSPointerOverHandler(ev) { + if (this._pointerId === ev.pointerId) { + _ElementUtilities.addClass(this._element, WinPressed.winPressed); + } + }, + + _MSPointerOutHandler: function _WinPressed_MSPointerOutHandler(ev) { + if (this._pointerId === ev.pointerId) { + _ElementUtilities.removeClass(this._element, WinPressed.winPressed); + } + }, + + _MSPointerCancelHandler: function _WinPressed_MSPointerCancelHandler(ev) { + if (this._pointerId === ev.pointerId) { + this._resetPointer(); + } + }, + + _MSPointerUpHandler: function _WinPressed_MSPointerUpHandler(ev) { + if (this._pointerId === ev.pointerId) { + this._resetPointer(); + } + }, + + _resetPointer: function _WinPressed_resetPointer() { + this._pointerId = null; + + _ElementUtilities._removeEventListener(_Global, "pointerup", this._pointerUpBound, true); + _ElementUtilities._removeEventListener(_Global, "pointercancel", this._pointerCancelBound, true); + _ElementUtilities._removeEventListener(this._element, "pointerover", this._pointerOverBound, true); + _ElementUtilities._removeEventListener(this._element, "pointerout", this._pointerOutBound, true); + + _ElementUtilities.removeClass(this._element, WinPressed.winPressed); + }, + + dispose: function _WinPressed_dispose() { + if (this._disposed) { + return; + } + this._disposed = true; + + this._resetPointer(); + } + }, { + winPressed: "win-pressed" + }); + + return WinPressed; + }), + /// + /// + /// Represents a navigation command in an NavBarContainer. + /// + /// + /// + /// + /// + ///
]]> + /// Styles the entire NavBarCommand control. + /// Styles the main button in a NavBarCommand. + /// Styles the split button in a NavBarCommand + /// Styles the icon in the main button of a NavBarCommand. + /// Styles the label in the main button of a NavBarCommand. + /// + /// + NavBarCommand: _Base.Namespace._lazy(function () { + var Key = _ElementUtilities.Key; + + var strings = { + get duplicateConstruction() { return "Invalid argument: Controls may only be instantiated one time for each DOM element"; } + }; + + var NavBarCommand = _Base.Class.define(function NavBarCommand_ctor(element, options) { + /// + /// + /// Creates a new NavBarCommand. + /// + /// + /// The DOM element that will host the new NavBarCommand control. + /// + /// + /// An object that contains one or more property/value pairs to apply to the new control. + /// Each property of the options object corresponds to one of the control's properties or events. + /// Event names must begin with "on". + /// + /// + /// The new NavBarCommand. + /// + /// + /// + element = element || _Global.document.createElement("DIV"); + options = options || {}; + + if (element.winControl) { + throw new _ErrorFromName("WinJS.UI.NavBarCommand.DuplicateConstruction", strings.duplicateConstruction); + } + + // Attaching JS control to DOM element + element.winControl = this; + this._element = element; + _ElementUtilities.addClass(this.element, NavBarCommand._ClassName.navbarcommand); + _ElementUtilities.addClass(this.element, "win-disposable"); + + this._tooltip = null; + this._splitOpened = false; + this._buildDom(); + element.addEventListener('keydown', this._keydownHandler.bind(this)); + + _Control.setOptions(this, options); + }, { + /// + element: { + get: function () { + return this._element; + } + }, + + /// + /// Gets or sets the label of the NavBarCommand. + /// + /// + label: { + get: function () { + return this._label; + }, + set: function (value) { + this._label = value; + this._labelEl.textContent = value; + } + }, + + /// + /// Gets or sets the tooltip of the NavBarCommand. + /// + /// + tooltip: { + get: function () { + return this._tooltip; + }, + set: function (value) { + this._tooltip = value; + if (this._tooltip || this._tooltip === "") { + this._element.setAttribute('title', this._tooltip); + } else { + this._element.removeAttribute('title'); + } + } + }, + + /// + /// Gets or sets the icon of the NavBarCommand. This value is either one of the values of the AppBarIcon enumeration or the path of a custom PNG file. + /// + /// + icon: { + get: function () { + return this._icon; + }, + set: function (value) { + this._icon = (_Icon[value] || value); + + // If the icon's a single character, presume a glyph + if (this._icon && this._icon.length === 1) { + // Set the glyph + this._imageSpan.textContent = this._icon; + this._imageSpan.style.backgroundImage = ""; + this._imageSpan.style.msHighContrastAdjust = ""; + this._imageSpan.style.display = ""; + } else if (this._icon && this._icon.length > 1) { + // Must be an image, set that + this._imageSpan.textContent = ""; + this._imageSpan.style.backgroundImage = this._icon; + this._imageSpan.style.msHighContrastAdjust = "none"; + this._imageSpan.style.display = ""; + } else { + this._imageSpan.textContent = ""; + this._imageSpan.style.backgroundImage = ""; + this._imageSpan.style.msHighContrastAdjust = ""; + this._imageSpan.style.display = "none"; + } + } + }, + + /// + /// Gets or sets the command's target location. + /// + /// + location: { + get: function () { + return this._location; + }, + set: function (value) { + this._location = value; + } + }, + + /// + /// Gets or sets the state value used for navigation. The command passes this object to the WinJS.Navigation.navigate function. + /// + /// + state: { + get: function () { + return this._state; + }, + set: function (value) { + this._state = value; + } + }, + + /// + /// Gets or sets a value that specifies whether the NavBarCommand has a split button. + /// + /// + splitButton: { + get: function () { + return this._split; + }, + set: function (value) { + this._split = value; + if (this._split) { + this._splitButtonEl.style.display = ""; + } else { + this._splitButtonEl.style.display = "none"; + } + } + }, + + /// + splitOpened: { + get: function () { + return this._splitOpened; + }, + set: function (value) { + if (this._splitOpened !== !!value) { + this._toggleSplit(); + } + } + }, + + _toggleSplit: function NavBarCommand_toggleSplit() { + this._splitOpened = !this._splitOpened; + if (this._splitOpened) { + _ElementUtilities.addClass(this._splitButtonEl, NavBarCommand._ClassName.navbarcommandsplitbuttonopened); + this._splitButtonEl.setAttribute("aria-expanded", "true"); + } else { + _ElementUtilities.removeClass(this._splitButtonEl, NavBarCommand._ClassName.navbarcommandsplitbuttonopened); + this._splitButtonEl.setAttribute("aria-expanded", "false"); + } + this._fireEvent(NavBarCommand._EventName._splitToggle); + }, + + _rtl: { + get: function () { + return _Global.getComputedStyle(this.element).direction === "rtl"; + } + }, + + _keydownHandler: function NavBarCommand_keydownHandler(ev) { + if (_ElementUtilities._matchesSelector(ev.target, ".win-interactive, .win-interactive *")) { + return; + } + + var leftStr = this._rtl ? Key.rightArrow : Key.leftArrow; + var rightStr = this._rtl ? Key.leftArrow : Key.rightArrow; + + if (!ev.altKey && (ev.keyCode === leftStr || ev.keyCode === Key.home || ev.keyCode === Key.end) && ev.target === this._splitButtonEl) { + _ElementUtilities._setActive(this._buttonEl); + if (ev.keyCode === leftStr) { + ev.stopPropagation(); + } + ev.preventDefault(); + } else if (!ev.altKey && ev.keyCode === rightStr && this.splitButton && (ev.target === this._buttonEl || this._buttonEl.contains(ev.target))) { + _ElementUtilities._setActive(this._splitButtonEl); + if (ev.keyCode === rightStr) { + ev.stopPropagation(); + } + ev.preventDefault(); + } else if ((ev.keyCode === Key.space || ev.keyCode === Key.enter) && (ev.target === this._buttonEl || this._buttonEl.contains(ev.target))) { + if (this.location) { + Navigation.navigate(this.location, this.state); + } + this._fireEvent(NavBarCommand._EventName._invoked); + } else if ((ev.keyCode === Key.space || ev.keyCode === Key.enter) && ev.target === this._splitButtonEl) { + this._toggleSplit(); + } + }, + + _getFocusInto: function NavBarCommand_getFocusInto(keyCode) { + var leftStr = this._rtl ? Key.rightArrow : Key.leftArrow; + if ((keyCode === leftStr) && this.splitButton) { + return this._splitButtonEl; + } else { + return this._buttonEl; + } + }, + + _buildDom: function NavBarCommand_buildDom() { + var markup = + '' + + ''; + this.element.insertAdjacentHTML("afterBegin", markup); + + this._buttonEl = this.element.firstElementChild; + this._buttonPressedBehavior = new exports._WinPressed(this._buttonEl); + this._contentEl = this._buttonEl.firstElementChild; + this._imageSpan = this._contentEl.firstElementChild; + this._imageSpan.style.display = "none"; + this._labelEl = this._imageSpan.nextElementSibling; + this._splitButtonEl = this._buttonEl.nextElementSibling; + this._splitButtonPressedBehavior = new exports._WinPressed(this._splitButtonEl); + this._splitButtonEl.style.display = "none"; + + _ElementUtilities._ensureId(this._buttonEl); + this._splitButtonEl.setAttribute("aria-labelledby", this._buttonEl.id); + + this._buttonEl.addEventListener("click", this._handleButtonClick.bind(this)); + + var mutationObserver = new _ElementUtilities._MutationObserver(this._splitButtonAriaExpandedPropertyChangeHandler.bind(this)); + mutationObserver.observe(this._splitButtonEl, { attributes: true, attributeFilter: ["aria-expanded"] }); + this._splitButtonEl.addEventListener("click", this._handleSplitButtonClick.bind(this)); + + // reparent any other elements. + var tempEl = this._splitButtonEl.nextSibling; + while (tempEl) { + this._buttonEl.insertBefore(tempEl, this._contentEl); + if (tempEl.nodeName !== "#text") { + ControlProcessor.processAll(tempEl); + } + tempEl = this._splitButtonEl.nextSibling; + } + }, + + _handleButtonClick: function NavBarCommand_handleButtonClick(ev) { + var srcElement = ev.target; + if (!_ElementUtilities._matchesSelector(srcElement, ".win-interactive, .win-interactive *")) { + if (this.location) { + Navigation.navigate(this.location, this.state); + } + this._fireEvent(NavBarCommand._EventName._invoked); + } + }, + + _splitButtonAriaExpandedPropertyChangeHandler: function NavBarCommand_splitButtonAriaExpandedPropertyChangeHandler() { + if ((this._splitButtonEl.getAttribute("aria-expanded") === "true") !== this._splitOpened) { + this._toggleSplit(); + } + }, + + _handleSplitButtonClick: function NavBarCommand_handleSplitButtonClick() { + this._toggleSplit(); + }, + + _fireEvent: function NavBarCommand_fireEvent(type, detail) { + var event = _Global.document.createEvent("CustomEvent"); + event.initCustomEvent(type, true, false, detail); + this.element.dispatchEvent(event); + }, + + dispose: function NavBarCommand_dispose() { + /// + /// + /// Disposes this control. + /// + /// + /// + if (this._disposed) { + return; + } + this._disposed = true; + + this._buttonPressedBehavior.dispose(); + this._splitButtonPressedBehavior.dispose(); + } + }, { + _ClassName: { + navbarcommand: "win-navbarcommand", + navbarcommandbutton: "win-navbarcommand-button", + navbarcommandbuttoncontent: "win-navbarcommand-button-content", + navbarcommandsplitbutton: "win-navbarcommand-splitbutton", + navbarcommandsplitbuttonopened: "win-navbarcommand-splitbutton-opened", + navbarcommandicon: "win-navbarcommand-icon", + navbarcommandlabel: "win-navbarcommand-label" + }, + _EventName: { + _invoked: "_invoked", + _splitToggle: "_splittoggle" + } + }); + _Base.Class.mix(NavBarCommand, _Control.DOMEventMixin); + return NavBarCommand; + }) + }); + +}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('WinJS/Controls/NavBar/_Container',[ + 'exports', + '../../Core/_Global', + '../../Core/_Base', + '../../Core/_BaseUtils', + '../../Core/_ErrorFromName', + '../../Core/_Events', + '../../Core/_Log', + '../../Core/_Resources', + '../../Core/_WriteProfilerMark', + '../../Animations', + '../../Animations/_TransitionAnimation', + '../../BindingList', + '../../ControlProcessor', + '../../Navigation', + '../../Promise', + '../../Scheduler', + '../../Utilities/_Control', + '../../Utilities/_ElementUtilities', + '../../Utilities/_KeyboardBehavior', + '../../Utilities/_UI', + '../_LegacyAppBar/_Constants', + '../Repeater', + './_Command' +], function NavBarContainerInit(exports, _Global, _Base, _BaseUtils, _ErrorFromName, _Events, _Log, _Resources, _WriteProfilerMark, Animations, _TransitionAnimation, BindingList, ControlProcessor, Navigation, Promise, Scheduler, _Control, _ElementUtilities, _KeyboardBehavior, _UI, _Constants, Repeater, _Command) { + "use strict"; + + function nobodyHasFocus() { + return _Global.document.activeElement === null || _Global.document.activeElement === _Global.document.body; + } + + _Base.Namespace._moduleDefine(exports, "WinJS.UI", { + /// + /// + /// Contains a group of NavBarCommand objects in a NavBar. + /// + /// + /// + /// + /// + /// + ///
+ ///
]]> + /// Raised when a NavBarCommand is invoked. + /// Raised when the split button on a NavBarCommand is toggled. + /// Styles the entire NavBarContainer control. + /// + /// Styles the page indication for the NavBarContainer. + /// + /// Styles the page indication for each page. + /// + /// Styles the indication of the current page. + /// + /// Styles the area that contains items for the NavBarContainer. + /// Styles left and right navigation arrows. + /// Styles the left navigation arrow. + /// Styles the right navigation arrow. + /// + /// + NavBarContainer: _Base.Namespace._lazy(function () { + var Key = _ElementUtilities.Key; + + var buttonFadeDelay = 3000; + var PT_TOUCH = _ElementUtilities._MSPointerEvent.MSPOINTER_TYPE_TOUCH || "touch"; + var MS_MANIPULATION_STATE_STOPPED = 0; + + var createEvent = _Events._createEventProperty; + var eventNames = { + invoked: "invoked", + splittoggle: "splittoggle" + }; + + var strings = { + get duplicateConstruction() { return "Invalid argument: Controls may only be instantiated one time for each DOM element"; }, + get navBarContainerViewportAriaLabel() { return _Resources._getWinJSString("ui/navBarContainerViewportAriaLabel").value; } + }; + + var NavBarContainer = _Base.Class.define(function NavBarContainer_ctor(element, options) { + /// + /// + /// Creates a new NavBarContainer. + /// + /// + /// The DOM element that will host the NavBarContainer control. + /// + /// + /// An object that contains one or more property/value pairs to apply to the new control. + /// Each property of the options object corresponds to one of the control's properties or events. + /// Event names must begin with "on". + /// + /// + /// The new NavBarContainer. + /// + /// + /// + + element = element || _Global.document.createElement("DIV"); + this._id = element.id || _ElementUtilities._uniqueID(element); + this._writeProfilerMark("constructor,StartTM"); + + options = options || {}; + + if (element.winControl) { + throw new _ErrorFromName("WinJS.UI.NavBarContainer.DuplicateConstruction", strings.duplicateConstruction); + } + + // Attaching JS control to DOM element + element.winControl = this; + this._element = element; + _ElementUtilities.addClass(this.element, NavBarContainer._ClassName.navbarcontainer); + _ElementUtilities.addClass(this.element, "win-disposable"); + if (!element.getAttribute("tabIndex")) { + element.tabIndex = -1; + } + + this._focusCurrentItemPassivelyBound = this._focusCurrentItemPassively.bind(this); + this._closeSplitAndResetBound = this._closeSplitAndReset.bind(this); + this._currentManipulationState = MS_MANIPULATION_STATE_STOPPED; + + this._panningDisabled = !_ElementUtilities._supportsSnapPoints; + this._fixedSize = false; + this._maxRows = 1; + this._sizes = {}; + + this._setupTree(); + + this._duringConstructor = true; + + this._dataChangingBound = this._dataChanging.bind(this); + this._dataChangedBound = this._dataChanged.bind(this); + + Navigation.addEventListener('navigated', this._closeSplitAndResetBound); + + // Don't use set options for the properties so we can control the ordering to avoid rendering multiple times. + this.layout = options.layout || _UI.Orientation.horizontal; + if (options.maxRows) { + this.maxRows = options.maxRows; + } + if (options.template) { + this.template = options.template; + } + if (options.data) { + this.data = options.data; + } + if (options.fixedSize) { + this.fixedSize = options.fixedSize; + } + + // Events only + _Control._setOptions(this, options, true); + + this._duringConstructor = false; + + if (options.currentIndex) { + this.currentIndex = options.currentIndex; + } + + this._updatePageUI(); + + Scheduler.schedule(function NavBarContainer_async_initialize() { + this._updateAppBarReference(); + }, Scheduler.Priority.normal, this, "WinJS.UI.NavBarContainer_async_initialize"); + + this._writeProfilerMark("constructor,StopTM"); + }, { + /// + element: { + get: function () { + return this._element; + } + }, + + /// + /// Gets or sets a Template or custom rendering function that defines the HTML of each item within the NavBarContainer. + /// + /// + template: { + get: function () { + return this._template; + }, + set: function (value) { + this._template = value; + if (this._repeater) { + var hadFocus = this.element.contains(_Global.document.activeElement); + + if (!this._duringConstructor) { + this._closeSplitIfOpen(); + } + + // the repeater's template is wired up to this._render() so just resetting it will rebuild the tree. + this._repeater.template = this._repeater.template; + + if (!this._duringConstructor) { + this._measured = false; + this._sizes.itemMeasured = false; + this._reset(); + if (hadFocus) { + this._keyboardBehavior._focus(0); + } + } + } + } + }, + + _render: function NavBarContainer_render(item) { + var navbarCommandEl = _Global.document.createElement('div'); + + var template = this._template; + if (template) { + if (template.render) { + template.render(item, navbarCommandEl); + } else if (template.winControl && template.winControl.render) { + template.winControl.render(item, navbarCommandEl); + } else { + navbarCommandEl.appendChild(template(item)); + } + } + + // Create the NavBarCommand after calling render so that the reparenting in navbarCommand works. + var navbarCommand = new _Command.NavBarCommand(navbarCommandEl, item); + return navbarCommand._element; + }, + + /// + /// Gets or sets the WinJS.Binding.List that provides the NavBarContainer with items to display. + /// + /// + data: { + get: function () { + return this._repeater && this._repeater.data; + }, + set: function (value) { + if (!value) { + value = new BindingList.List(); + } + + if (!this._duringConstructor) { + this._closeSplitIfOpen(); + } + + this._removeDataChangingEvents(); + this._removeDataChangedEvents(); + + var hadFocus = this.element.contains(_Global.document.activeElement); + + if (!this._repeater) { + this._surfaceEl.innerHTML = ""; + this._repeater = new Repeater.Repeater(this._surfaceEl, { + template: this._render.bind(this) + }); + } + + this._addDataChangingEvents(value); + this._repeater.data = value; + this._addDataChangedEvents(value); + + if (!this._duringConstructor) { + this._measured = false; + this._sizes.itemMeasured = false; + this._reset(); + if (hadFocus) { + this._keyboardBehavior._focus(0); + } + } + } + }, + + /// + /// Gets or sets the number of rows allowed to be used before items are placed on additional pages. + /// + /// + maxRows: { + get: function () { + return this._maxRows; + }, + set: function (value) { + value = (+value === value) ? value : 1; + this._maxRows = Math.max(1, value); + + if (!this._duringConstructor) { + this._closeSplitIfOpen(); + + this._measured = false; + this._reset(); + } + } + }, + + /// + /// Gets or sets a value that specifies whether the NavBarContainer has a horizontal or vertical layout. The default is "horizontal". + /// + /// + layout: { + get: function () { + return this._layout; + }, + set: function (value) { + if (value === _UI.Orientation.vertical) { + this._layout = _UI.Orientation.vertical; + _ElementUtilities.removeClass(this.element, NavBarContainer._ClassName.horizontal); + _ElementUtilities.addClass(this.element, NavBarContainer._ClassName.vertical); + } else { + this._layout = _UI.Orientation.horizontal; + _ElementUtilities.removeClass(this.element, NavBarContainer._ClassName.vertical); + _ElementUtilities.addClass(this.element, NavBarContainer._ClassName.horizontal); + } + + this._viewportEl.style.msScrollSnapType = ""; + this._zooming = false; + + if (!this._duringConstructor) { + this._measured = false; + this._sizes.itemMeasured = false; + this._ensureVisible(this._keyboardBehavior.currentIndex, true); + this._updatePageUI(); + this._closeSplitIfOpen(); + } + } + }, + + /// + currentIndex: { + get: function () { + return this._keyboardBehavior.currentIndex; + }, + set: function (value) { + if (value === +value) { + var hadFocus = this.element.contains(_Global.document.activeElement); + + this._keyboardBehavior.currentIndex = value; + + this._ensureVisible(this._keyboardBehavior.currentIndex, true); + + if (hadFocus) { + this._keyboardBehavior._focus(); + } + } + } + }, + + /// + /// Gets or sets a value that specifies whether child NavBarCommand objects should be a fixed width when there are multiple pages. A value of true indicates + /// that the NavBarCommand objects use a fixed width; a value of false indicates that they use a dynamic width. + /// + /// + fixedSize: { + get: function () { + return this._fixedSize; + }, + set: function (value) { + this._fixedSize = !!value; + + if (!this._duringConstructor) { + this._closeSplitIfOpen(); + + if (!this._measured) { + this._measure(); + } else if (this._surfaceEl.children.length > 0) { + this._updateGridStyles(); + } + } + } + }, + + /// + /// Raised when a NavBarCommand has been invoked. + /// + /// + oninvoked: createEvent(eventNames.invoked), + + /// + /// Raised when the split button on a NavBarCommand is toggled. + /// + /// + onsplittoggle: createEvent(eventNames.splittoggle), + + forceLayout: function NavBarContainer_forceLayout() { + /// + /// + /// Forces the NavBarContainer to update scroll positions and if the NavBar has changed size, it will also re-measure. + /// Use this function when making the NavBarContainer visible again after you set its style.display property to "none". + /// + /// + /// + this._resizeHandler(); + if (this._measured) { + this._scrollPosition = _ElementUtilities.getScrollPosition(this._viewportEl)[(this.layout === _UI.Orientation.horizontal ? "scrollLeft" : "scrollTop")]; + } + + this._duringForceLayout = true; + this._ensureVisible(this._keyboardBehavior.currentIndex, true); + this._updatePageUI(); + this._duringForceLayout = false; + }, + + _updateAppBarReference: function NavBarContainer_updateAppBarReference() { + if (!this._appBarEl || !this._appBarEl.contains(this.element)) { + if (this._appBarEl) { + this._appBarEl.removeEventListener('beforeopen', this._closeSplitAndResetBound); + this._appBarEl.removeEventListener('beforeopen', this._resizeImplBound); + this._appBarEl.removeEventListener('afteropen', this._focusCurrentItemPassivelyBound); + } + + var appBarEl = this.element.parentNode; + while (appBarEl && !_ElementUtilities.hasClass(appBarEl, _Constants.appBarClass)) { + appBarEl = appBarEl.parentNode; + } + this._appBarEl = appBarEl; + + if (this._appBarEl) { + this._appBarEl.addEventListener('beforeopen', this._closeSplitAndResetBound); + this._appBarEl.addEventListener('afteropen', this._focusCurrentItemPassivelyBound); + } + } + }, + + _closeSplitAndReset: function NavBarContainer_closeSplitAndReset() { + this._closeSplitIfOpen(); + this._reset(); + }, + + _dataChanging: function NavBarContainer_dataChanging(ev) { + // Store the element that was active so that we can detect + // if the focus went away because of the data change. + this._elementHadFocus = _Global.document.activeElement; + + if (this._currentSplitNavItem && this._currentSplitNavItem.splitOpened) { + if (ev.type === "itemremoved") { + if (this._surfaceEl.children[ev.detail.index].winControl === this._currentSplitNavItem) { + this._closeSplitIfOpen(); + } + } else if (ev.type === "itemchanged") { + if (this._surfaceEl.children[ev.detail.index].winControl === this._currentSplitNavItem) { + this._closeSplitIfOpen(); + } + } else if (ev.type === "itemmoved") { + if (this._surfaceEl.children[ev.detail.oldIndex].winControl === this._currentSplitNavItem) { + this._closeSplitIfOpen(); + } + } else if (ev.type === "reload") { + this._closeSplitIfOpen(); + } + } + }, + + _dataChanged: function NavBarContainer_dataChanged(ev) { + this._measured = false; + + if (ev.type === "itemremoved") { + if (ev.detail.index < this._keyboardBehavior.currentIndex) { + this._keyboardBehavior.currentIndex--; + } else if (ev.detail.index === this._keyboardBehavior.currentIndex) { + // This clamps if the item being removed was the last item in the list + this._keyboardBehavior.currentIndex = this._keyboardBehavior.currentIndex; + if (nobodyHasFocus() && this._elementHadFocus) { + this._keyboardBehavior._focus(); + } + } + } else if (ev.type === "itemchanged") { + if (ev.detail.index === this._keyboardBehavior.currentIndex) { + if (nobodyHasFocus() && this._elementHadFocus) { + this._keyboardBehavior._focus(); + } + } + } else if (ev.type === "iteminserted") { + if (ev.detail.index <= this._keyboardBehavior.currentIndex) { + this._keyboardBehavior.currentIndex++; + } + } else if (ev.type === "itemmoved") { + if (ev.detail.oldIndex === this._keyboardBehavior.currentIndex) { + this._keyboardBehavior.currentIndex = ev.detail.newIndex; + if (nobodyHasFocus() && this._elementHadFocus) { + this._keyboardBehavior._focus(); + } + } + } else if (ev.type === "reload") { + this._keyboardBehavior.currentIndex = 0; + if (nobodyHasFocus() && this._elementHadFocus) { + this._keyboardBehavior._focus(); + } + } + + this._ensureVisible(this._keyboardBehavior.currentIndex, true); + this._updatePageUI(); + }, + + _focusCurrentItemPassively: function NavBarContainer_focusCurrentItemPassively() { + if (this.element.contains(_Global.document.activeElement)) { + this._keyboardBehavior._focus(); + } + }, + + _reset: function NavBarContainer_reset() { + this._keyboardBehavior.currentIndex = 0; + + if (this.element.contains(_Global.document.activeElement)) { + this._keyboardBehavior._focus(0); + } + + this._viewportEl.style.msScrollSnapType = ""; + this._zooming = false; + + this._ensureVisible(0, true); + this._updatePageUI(); + }, + + _removeDataChangedEvents: function NavBarContainer_removeDataChangedEvents() { + if (this._repeater) { + this._repeater.data.removeEventListener("itemchanged", this._dataChangedBound); + this._repeater.data.removeEventListener("iteminserted", this._dataChangedBound); + this._repeater.data.removeEventListener("itemmoved", this._dataChangedBound); + this._repeater.data.removeEventListener("itemremoved", this._dataChangedBound); + this._repeater.data.removeEventListener("reload", this._dataChangedBound); + } + }, + + _addDataChangedEvents: function NavBarContainer_addDataChangedEvents() { + if (this._repeater) { + this._repeater.data.addEventListener("itemchanged", this._dataChangedBound); + this._repeater.data.addEventListener("iteminserted", this._dataChangedBound); + this._repeater.data.addEventListener("itemmoved", this._dataChangedBound); + this._repeater.data.addEventListener("itemremoved", this._dataChangedBound); + this._repeater.data.addEventListener("reload", this._dataChangedBound); + } + }, + + _removeDataChangingEvents: function NavBarContainer_removeDataChangingEvents() { + if (this._repeater) { + this._repeater.data.removeEventListener("itemchanged", this._dataChangingBound); + this._repeater.data.removeEventListener("iteminserted", this._dataChangingBound); + this._repeater.data.removeEventListener("itemmoved", this._dataChangingBound); + this._repeater.data.removeEventListener("itemremoved", this._dataChangingBound); + this._repeater.data.removeEventListener("reload", this._dataChangingBound); + } + }, + + _addDataChangingEvents: function NavBarContainer_addDataChangingEvents(bindingList) { + bindingList.addEventListener("itemchanged", this._dataChangingBound); + bindingList.addEventListener("iteminserted", this._dataChangingBound); + bindingList.addEventListener("itemmoved", this._dataChangingBound); + bindingList.addEventListener("itemremoved", this._dataChangingBound); + bindingList.addEventListener("reload", this._dataChangingBound); + }, + + _mouseleave: function NavBarContainer_mouseleave() { + if (this._mouseInViewport) { + this._mouseInViewport = false; + this._updateArrows(); + } + }, + + _MSPointerDown: function NavBarContainer_MSPointerDown(ev) { + if (ev.pointerType === PT_TOUCH) { + if (this._mouseInViewport) { + this._mouseInViewport = false; + this._updateArrows(); + } + } + }, + + _MSPointerMove: function NavBarContainer_MSPointerMove(ev) { + if (ev.pointerType !== PT_TOUCH) { + if (!this._mouseInViewport) { + this._mouseInViewport = true; + this._updateArrows(); + } + } + }, + + _setupTree: function NavBarContainer_setupTree() { + this._animateNextPreviousButtons = Promise.wrap(); + this._element.addEventListener('mouseleave', this._mouseleave.bind(this)); + _ElementUtilities._addEventListener(this._element, 'pointerdown', this._MSPointerDown.bind(this)); + _ElementUtilities._addEventListener(this._element, 'pointermove', this._MSPointerMove.bind(this)); + _ElementUtilities._addEventListener(this._element, "focusin", this._focusHandler.bind(this), false); + + this._pageindicatorsEl = _Global.document.createElement('div'); + _ElementUtilities.addClass(this._pageindicatorsEl, NavBarContainer._ClassName.pageindicators); + this._element.appendChild(this._pageindicatorsEl); + + this._ariaStartMarker = _Global.document.createElement("div"); + this._element.appendChild(this._ariaStartMarker); + + this._viewportEl = _Global.document.createElement('div'); + _ElementUtilities.addClass(this._viewportEl, NavBarContainer._ClassName.viewport); + this._element.appendChild(this._viewportEl); + this._viewportEl.setAttribute("role", "group"); + this._viewportEl.setAttribute("aria-label", strings.navBarContainerViewportAriaLabel); + + this._boundResizeHandler = this._resizeHandler.bind(this); + _ElementUtilities._resizeNotifier.subscribe(this._element, this._boundResizeHandler); + this._viewportEl.addEventListener("mselementresize", this._resizeHandler.bind(this)); + this._viewportEl.addEventListener("scroll", this._scrollHandler.bind(this)); + this._viewportEl.addEventListener("MSManipulationStateChanged", this._MSManipulationStateChangedHandler.bind(this)); + + this._ariaEndMarker = _Global.document.createElement("div"); + this._element.appendChild(this._ariaEndMarker); + + this._surfaceEl = _Global.document.createElement('div'); + _ElementUtilities.addClass(this._surfaceEl, NavBarContainer._ClassName.surface); + this._viewportEl.appendChild(this._surfaceEl); + + this._surfaceEl.addEventListener("_invoked", this._navbarCommandInvokedHandler.bind(this)); + this._surfaceEl.addEventListener("_splittoggle", this._navbarCommandSplitToggleHandler.bind(this)); + _ElementUtilities._addEventListener(this._surfaceEl, "focusin", this._itemsFocusHandler.bind(this), false); + this._surfaceEl.addEventListener("keydown", this._keyDownHandler.bind(this)); + + // Reparent NavBarCommands which were in declarative markup + var tempEl = this.element.firstElementChild; + while (tempEl !== this._pageindicatorsEl) { + this._surfaceEl.appendChild(tempEl); + ControlProcessor.process(tempEl); + tempEl = this.element.firstElementChild; + } + + this._leftArrowEl = _Global.document.createElement('div'); + _ElementUtilities.addClass(this._leftArrowEl, NavBarContainer._ClassName.navleftarrow); + _ElementUtilities.addClass(this._leftArrowEl, NavBarContainer._ClassName.navarrow); + this._element.appendChild(this._leftArrowEl); + this._leftArrowEl.addEventListener('click', this._goLeft.bind(this)); + this._leftArrowEl.style.opacity = 0; + this._leftArrowEl.style.visibility = 'hidden'; + this._leftArrowFadeOut = Promise.wrap(); + + this._rightArrowEl = _Global.document.createElement('div'); + _ElementUtilities.addClass(this._rightArrowEl, NavBarContainer._ClassName.navrightarrow); + _ElementUtilities.addClass(this._rightArrowEl, NavBarContainer._ClassName.navarrow); + this._element.appendChild(this._rightArrowEl); + this._rightArrowEl.addEventListener('click', this._goRight.bind(this)); + this._rightArrowEl.style.opacity = 0; + this._rightArrowEl.style.visibility = 'hidden'; + this._rightArrowFadeOut = Promise.wrap(); + + this._keyboardBehavior = new _KeyboardBehavior._KeyboardBehavior(this._surfaceEl, { + scroller: this._viewportEl + }); + this._winKeyboard = new _KeyboardBehavior._WinKeyboard(this._surfaceEl); + }, + + _goRight: function NavBarContainer_goRight() { + if (this._sizes.rtl) { + this._goPrev(); + } else { + this._goNext(); + } + }, + + _goLeft: function NavBarContainer_goLeft() { + if (this._sizes.rtl) { + this._goNext(); + } else { + this._goPrev(); + } + }, + + _goNext: function NavBarContainer_goNext() { + this._measure(); + var itemsPerPage = this._sizes.rowsPerPage * this._sizes.columnsPerPage; + var targetPage = Math.min(Math.floor(this._keyboardBehavior.currentIndex / itemsPerPage) + 1, this._sizes.pages - 1); + this._keyboardBehavior.currentIndex = Math.min(itemsPerPage * targetPage, this._surfaceEl.children.length); + this._keyboardBehavior._focus(); + }, + + _goPrev: function NavBarContainer_goPrev() { + this._measure(); + var itemsPerPage = this._sizes.rowsPerPage * this._sizes.columnsPerPage; + var targetPage = Math.max(0, Math.floor(this._keyboardBehavior.currentIndex / itemsPerPage) - 1); + this._keyboardBehavior.currentIndex = Math.max(itemsPerPage * targetPage, 0); + this._keyboardBehavior._focus(); + }, + + _currentPage: { + get: function () { + if (this.layout === _UI.Orientation.horizontal) { + this._measure(); + if (this._sizes.viewportOffsetWidth > 0) { + return Math.min(this._sizes.pages - 1, Math.round(this._scrollPosition / this._sizes.viewportOffsetWidth)); + } + } + return 0; + } + }, + + _resizeHandler: function NavBarContainer_resizeHandler() { + if (this._disposed) { return; } + if (!this._measured) { return; } + var viewportResized = this.layout === _UI.Orientation.horizontal + ? this._sizes.viewportOffsetWidth !== parseFloat(_Global.getComputedStyle(this._viewportEl).width) + : this._sizes.viewportOffsetHeight !== parseFloat(_Global.getComputedStyle(this._viewportEl).height); + if (!viewportResized) { return; } + + this._measured = false; + + if (!this._pendingResize) { + this._pendingResize = true; + + this._resizeImplBound = this._resizeImplBound || this._resizeImpl.bind(this); + + this._updateAppBarReference(); + + if (this._appBarEl && this._appBarEl.winControl && !this._appBarEl.winControl.opened) { + // Do resize lazily. + Scheduler.schedule(this._resizeImplBound, Scheduler.Priority.idle, null, "WinJS.UI.NavBarContainer._resizeImpl"); + this._appBarEl.addEventListener('beforeopen', this._resizeImplBound); + } else { + // Do resize now + this._resizeImpl(); + } + } + }, + + _resizeImpl: function NavBarContainer_resizeImpl() { + if (!this._disposed && this._pendingResize) { + this._pendingResize = false; + if (this._appBarEl) { + this._appBarEl.removeEventListener('beforeopen', this._resizeImplBound); + } + + this._keyboardBehavior.currentIndex = 0; + if (this.element.contains(_Global.document.activeElement)) { + this._keyboardBehavior._focus(this._keyboardBehavior.currentIndex); + } + this._closeSplitIfOpen(); + this._ensureVisible(this._keyboardBehavior.currentIndex, true); + this._updatePageUI(); + } + }, + + _keyDownHandler: function NavBarContainer_keyDownHandler(ev) { + var keyCode = ev.keyCode; + if (!ev.altKey && (keyCode === Key.pageUp || keyCode === Key.pageDown)) { + var srcElement = ev.target; + if (_ElementUtilities._matchesSelector(srcElement, ".win-interactive, .win-interactive *")) { + return; + } + + var index = this._keyboardBehavior.currentIndex; + this._measure(); + + var sizes = this._sizes; + var page = Math.floor(index / (sizes.columnsPerPage * sizes.rowsPerPage)); + + var scrollPositionTarget = null; + if (keyCode === Key.pageUp) { + if (this.layout === _UI.Orientation.horizontal) { + var indexOfFirstItemOnPage = page * sizes.columnsPerPage * sizes.rowsPerPage; + if (index === indexOfFirstItemOnPage && this._surfaceEl.children[index].winControl._buttonEl === _Global.document.activeElement) { + // First item on page so go back 1 page. + index = index - sizes.columnsPerPage * sizes.rowsPerPage; + } else { + // Not first item on page so go to the first item on page. + index = indexOfFirstItemOnPage; + } + } else { + var currentItem = this._surfaceEl.children[index]; + var top = currentItem.offsetTop; + var bottom = top + currentItem.offsetHeight; + var scrollPosition = this._zooming ? this._zoomPosition : this._scrollPosition; + + if (top >= scrollPosition && bottom < scrollPosition + sizes.viewportOffsetHeight) { + // current item is fully on screen. + while (index > 0 && + this._surfaceEl.children[index - 1].offsetTop > scrollPosition) { + index--; + } + } + + if (this._keyboardBehavior.currentIndex === index) { + var scrollPositionForOnePageAboveItem = bottom - sizes.viewportOffsetHeight; + index = Math.max(0, index - 1); + while (index > 0 && + this._surfaceEl.children[index - 1].offsetTop > scrollPositionForOnePageAboveItem) { + index--; + } + if (index > 0) { + scrollPositionTarget = this._surfaceEl.children[index].offsetTop - this._sizes.itemMarginTop; + } else { + scrollPositionTarget = 0; + } + } + } + + index = Math.max(index, 0); + this._keyboardBehavior.currentIndex = index; + + var element = this._surfaceEl.children[index].winControl._buttonEl; + + if (scrollPositionTarget !== null) { + this._scrollTo(scrollPositionTarget); + } + + _ElementUtilities._setActive(element, this._viewportEl); + } else { + if (this.layout === _UI.Orientation.horizontal) { + var indexOfLastItemOnPage = (page + 1) * sizes.columnsPerPage * sizes.rowsPerPage - 1; + + if (index === indexOfLastItemOnPage) { + // Last item on page so go forward 1 page. + index = index + sizes.columnsPerPage * sizes.rowsPerPage; + } else { + // Not Last item on page so go to last item on page. + index = indexOfLastItemOnPage; + } + } else { + var currentItem = this._surfaceEl.children[this._keyboardBehavior.currentIndex]; + var top = currentItem.offsetTop; + var bottom = top + currentItem.offsetHeight; + var scrollPosition = this._zooming ? this._zoomPosition : this._scrollPosition; + + if (top >= scrollPosition && bottom < scrollPosition + sizes.viewportOffsetHeight) { + // current item is fully on screen. + while (index < this._surfaceEl.children.length - 1 && + this._surfaceEl.children[index + 1].offsetTop + this._surfaceEl.children[index + 1].offsetHeight < scrollPosition + sizes.viewportOffsetHeight) { + index++; + } + } + + if (index === this._keyboardBehavior.currentIndex) { + var scrollPositionForOnePageBelowItem = top + sizes.viewportOffsetHeight; + index = Math.min(this._surfaceEl.children.length - 1, index + 1); + while (index < this._surfaceEl.children.length - 1 && + this._surfaceEl.children[index + 1].offsetTop + this._surfaceEl.children[index + 1].offsetHeight < scrollPositionForOnePageBelowItem) { + index++; + } + + if (index < this._surfaceEl.children.length - 1) { + scrollPositionTarget = this._surfaceEl.children[index + 1].offsetTop - this._sizes.viewportOffsetHeight; + } else { + scrollPositionTarget = this._scrollLength - this._sizes.viewportOffsetHeight; + } + } + } + + index = Math.min(index, this._surfaceEl.children.length - 1); + this._keyboardBehavior.currentIndex = index; + + var element = this._surfaceEl.children[index].winControl._buttonEl; + + if (scrollPositionTarget !== null) { + this._scrollTo(scrollPositionTarget); + } + + try { + _ElementUtilities._setActive(element, this._viewportEl); + } catch (e) { + } + } + } + }, + + _focusHandler: function NavBarContainer_focusHandler(ev) { + var srcElement = ev.target; + if (!this._surfaceEl.contains(srcElement)) { + // Forward focus from NavBarContainer, viewport or surface to the currentIndex. + this._skipEnsureVisible = true; + this._keyboardBehavior._focus(this._keyboardBehavior.currentIndex); + } + }, + + _itemsFocusHandler: function NavBarContainer_itemsFocusHandler(ev) { + // Find the item which is being focused and scroll it to view. + var srcElement = ev.target; + if (srcElement === this._surfaceEl) { + return; + } + + while (srcElement.parentNode !== this._surfaceEl) { + srcElement = srcElement.parentNode; + } + + var index = -1; + while (srcElement) { + index++; + srcElement = srcElement.previousSibling; + } + + if (this._skipEnsureVisible) { + this._skipEnsureVisible = false; + } else { + this._ensureVisible(index); + } + }, + + _ensureVisible: function NavBarContainer_ensureVisible(index, withoutAnimation) { + this._measure(); + + if (this.layout === _UI.Orientation.horizontal) { + var page = Math.floor(index / (this._sizes.rowsPerPage * this._sizes.columnsPerPage)); + this._scrollTo(page * this._sizes.viewportOffsetWidth, withoutAnimation); + } else { + var element = this._surfaceEl.children[index]; + var maxScrollPosition; + if (index > 0) { + maxScrollPosition = element.offsetTop - this._sizes.itemMarginTop; + } else { + maxScrollPosition = 0; + } + var minScrollPosition; + if (index < this._surfaceEl.children.length - 1) { + minScrollPosition = this._surfaceEl.children[index + 1].offsetTop - this._sizes.viewportOffsetHeight; + } else { + minScrollPosition = this._scrollLength - this._sizes.viewportOffsetHeight; + } + + var newScrollPosition = this._zooming ? this._zoomPosition : this._scrollPosition; + newScrollPosition = Math.max(newScrollPosition, minScrollPosition); + newScrollPosition = Math.min(newScrollPosition, maxScrollPosition); + this._scrollTo(newScrollPosition, withoutAnimation); + } + }, + + _scrollTo: function NavBarContainer_scrollTo(targetScrollPosition, withoutAnimation) { + this._measure(); + if (this.layout === _UI.Orientation.horizontal) { + targetScrollPosition = Math.max(0, Math.min(this._scrollLength - this._sizes.viewportOffsetWidth, targetScrollPosition)); + } else { + targetScrollPosition = Math.max(0, Math.min(this._scrollLength - this._sizes.viewportOffsetHeight, targetScrollPosition)); + } + + if (withoutAnimation) { + if (Math.abs(this._scrollPosition - targetScrollPosition) > 1) { + this._zooming = false; + + this._scrollPosition = targetScrollPosition; + this._updatePageUI(); + if (!this._duringForceLayout) { + this._closeSplitIfOpen(); + } + + var newScrollPos = {}; + newScrollPos[(this.layout === _UI.Orientation.horizontal ? "scrollLeft" : "scrollTop")] = targetScrollPosition; + _ElementUtilities.setScrollPosition(this._viewportEl, newScrollPos); + } + } else { + if ((!this._zooming && Math.abs(this._scrollPosition - targetScrollPosition) > 1) || (this._zooming && Math.abs(this._zoomPosition - targetScrollPosition) > 1)) { + this._zoomPosition = targetScrollPosition; + + this._zooming = true; + + if (this.layout === _UI.Orientation.horizontal) { + this._viewportEl.style.msScrollSnapType = "none"; + _ElementUtilities._zoomTo(this._viewportEl, { contentX: targetScrollPosition, contentY: 0, viewportX: 0, viewportY: 0 }); + } else { + _ElementUtilities._zoomTo(this._viewportEl, { contentX: 0, contentY: targetScrollPosition, viewportX: 0, viewportY: 0 }); + } + + this._closeSplitIfOpen(); + } + } + }, + + _MSManipulationStateChangedHandler: function NavBarContainer_MSManipulationStateChangedHandler(e) { + this._currentManipulationState = e.currentState; + + if (e.currentState === e.MS_MANIPULATION_STATE_ACTIVE) { + this._viewportEl.style.msScrollSnapType = ""; + this._zooming = false; + } + + _Global.clearTimeout(this._manipulationStateTimeoutId); + // The extra stop event is firing when an zoomTo is called during another zoomTo and + // also the first zoomTo after a resize. + if (e.currentState === e.MS_MANIPULATION_STATE_STOPPED) { + this._manipulationStateTimeoutId = _Global.setTimeout(function () { + this._viewportEl.style.msScrollSnapType = ""; + this._zooming = false; + this._updateCurrentIndexIfPageChanged(); + }.bind(this), 100); + } + }, + + _scrollHandler: function NavBarContainer_scrollHandler() { + if (this._disposed) { return; } + + this._measured = false; + if (!this._checkingScroll) { + var that = this; + this._checkingScroll = _BaseUtils._requestAnimationFrame(function () { + if (that._disposed) { return; } + that._checkingScroll = null; + + var newScrollPosition = _ElementUtilities.getScrollPosition(that._viewportEl)[(that.layout === _UI.Orientation.horizontal ? "scrollLeft" : "scrollTop")]; + if (newScrollPosition !== that._scrollPosition) { + that._scrollPosition = newScrollPosition; + that._closeSplitIfOpen(); + } + that._updatePageUI(); + + if (!that._zooming && that._currentManipulationState === MS_MANIPULATION_STATE_STOPPED) { + that._updateCurrentIndexIfPageChanged(); + } + }); + } + }, + + _updateCurrentIndexIfPageChanged: function NavBarContainer_updateCurrentIndexIfPageChanged() { + // If you change pages via pagination arrows, mouse wheel, or panning we need to update the current + // item to be the first item on the new page. + if (this.layout === _UI.Orientation.horizontal) { + this._measure(); + var currentPage = this._currentPage; + var firstIndexOnPage = currentPage * this._sizes.rowsPerPage * this._sizes.columnsPerPage; + var lastIndexOnPage = (currentPage + 1) * this._sizes.rowsPerPage * this._sizes.columnsPerPage - 1; + + if (this._keyboardBehavior.currentIndex < firstIndexOnPage || this._keyboardBehavior.currentIndex > lastIndexOnPage) { + // Page change occurred. + this._keyboardBehavior.currentIndex = firstIndexOnPage; + + if (this.element.contains(_Global.document.activeElement)) { + this._keyboardBehavior._focus(this._keyboardBehavior.currentIndex); + } + } + } + }, + + _measure: function NavBarContainer_measure() { + if (!this._measured) { + this._resizeImpl(); + this._writeProfilerMark("measure,StartTM"); + + var sizes = this._sizes; + + sizes.rtl = _Global.getComputedStyle(this._element).direction === "rtl"; + + var itemCount = this._surfaceEl.children.length; + if (itemCount > 0) { + if (!this._sizes.itemMeasured) { + this._writeProfilerMark("measureItem,StartTM"); + + var elementToMeasure = this._surfaceEl.firstElementChild; + // Clear inline margins set by NavBarContainer before measuring. + elementToMeasure.style.margin = ""; + elementToMeasure.style.width = ""; + var elementComputedStyle = _Global.getComputedStyle(elementToMeasure); + sizes.itemOffsetWidth = parseFloat(_Global.getComputedStyle(elementToMeasure).width); + if (elementToMeasure.offsetWidth === 0) { + sizes.itemOffsetWidth = 0; + } + sizes.itemMarginLeft = parseFloat(elementComputedStyle.marginLeft); + sizes.itemMarginRight = parseFloat(elementComputedStyle.marginRight); + sizes.itemWidth = sizes.itemOffsetWidth + sizes.itemMarginLeft + sizes.itemMarginRight; + sizes.itemOffsetHeight = parseFloat(_Global.getComputedStyle(elementToMeasure).height); + if (elementToMeasure.offsetHeight === 0) { + sizes.itemOffsetHeight = 0; + } + sizes.itemMarginTop = parseFloat(elementComputedStyle.marginTop); + sizes.itemMarginBottom = parseFloat(elementComputedStyle.marginBottom); + sizes.itemHeight = sizes.itemOffsetHeight + sizes.itemMarginTop + sizes.itemMarginBottom; + if (sizes.itemOffsetWidth > 0 && sizes.itemOffsetHeight > 0) { + sizes.itemMeasured = true; + } + this._writeProfilerMark("measureItem,StopTM"); + } + + sizes.viewportOffsetWidth = parseFloat(_Global.getComputedStyle(this._viewportEl).width); + if (this._viewportEl.offsetWidth === 0) { + sizes.viewportOffsetWidth = 0; + } + sizes.viewportOffsetHeight = parseFloat(_Global.getComputedStyle(this._viewportEl).height); + if (this._viewportEl.offsetHeight === 0) { + sizes.viewportOffsetHeight = 0; + } + + if (sizes.viewportOffsetWidth === 0 || sizes.itemOffsetHeight === 0) { + this._measured = false; + } else { + this._measured = true; + } + + if (this.layout === _UI.Orientation.horizontal) { + this._scrollPosition = _ElementUtilities.getScrollPosition(this._viewportEl).scrollLeft; + + sizes.leadingEdge = this._leftArrowEl.offsetWidth + parseInt(_Global.getComputedStyle(this._leftArrowEl).marginLeft) + parseInt(_Global.getComputedStyle(this._leftArrowEl).marginRight); + var usableSpace = sizes.viewportOffsetWidth - sizes.leadingEdge * 2; + sizes.maxColumns = sizes.itemWidth ? Math.max(1, Math.floor(usableSpace / sizes.itemWidth)) : 1; + sizes.rowsPerPage = Math.min(this.maxRows, Math.ceil(itemCount / sizes.maxColumns)); + sizes.columnsPerPage = Math.min(sizes.maxColumns, itemCount); + sizes.pages = Math.ceil(itemCount / (sizes.columnsPerPage * sizes.rowsPerPage)); + sizes.trailingEdge = sizes.leadingEdge; + sizes.extraSpace = usableSpace - (sizes.columnsPerPage * sizes.itemWidth); + + this._scrollLength = sizes.viewportOffsetWidth * sizes.pages; + + this._keyboardBehavior.fixedSize = sizes.rowsPerPage; + this._keyboardBehavior.fixedDirection = _KeyboardBehavior._KeyboardBehavior.FixedDirection.height; + + this._surfaceEl.style.height = (sizes.itemHeight * sizes.rowsPerPage) + "px"; + this._surfaceEl.style.width = this._scrollLength + "px"; + } else { + this._scrollPosition = this._viewportEl.scrollTop; + + sizes.leadingEdge = 0; + sizes.rowsPerPage = itemCount; + sizes.columnsPerPage = 1; + sizes.pages = 1; + sizes.trailingEdge = 0; + + // Reminder there is margin collapsing so just use scrollHeight instead of itemHeight * itemCount + this._scrollLength = this._viewportEl.scrollHeight; + + this._keyboardBehavior.fixedSize = sizes.columnsPerPage; + this._keyboardBehavior.fixedDirection = _KeyboardBehavior._KeyboardBehavior.FixedDirection.width; + + this._surfaceEl.style.height = ""; + this._surfaceEl.style.width = ""; + } + + this._updateGridStyles(); + } else { + sizes.pages = 1; + this._hasPreviousContent = false; + this._hasNextContent = false; + this._surfaceEl.style.height = ""; + this._surfaceEl.style.width = ""; + } + + this._writeProfilerMark("measure,StopTM"); + } + }, + + _updateGridStyles: function NavBarContainer_updateGridStyles() { + var sizes = this._sizes; + var itemCount = this._surfaceEl.children.length; + + for (var index = 0; index < itemCount; index++) { + var itemEl = this._surfaceEl.children[index]; + + var marginRight; + var marginLeft; + var width = ""; + + if (this.layout === _UI.Orientation.horizontal) { + var column = Math.floor(index / sizes.rowsPerPage); + var isFirstColumnOnPage = column % sizes.columnsPerPage === 0; + var isLastColumnOnPage = column % sizes.columnsPerPage === sizes.columnsPerPage - 1; + + var extraTrailingMargin = sizes.trailingEdge; + if (this.fixedSize) { + extraTrailingMargin += sizes.extraSpace; + } else { + var spaceToDistribute = sizes.extraSpace - (sizes.maxColumns - sizes.columnsPerPage) * sizes.itemWidth; + width = (sizes.itemOffsetWidth + (spaceToDistribute / sizes.maxColumns)) + "px"; + } + + var extraMarginRight; + var extraMarginLeft; + + if (sizes.rtl) { + extraMarginRight = (isFirstColumnOnPage ? sizes.leadingEdge : 0); + extraMarginLeft = (isLastColumnOnPage ? extraTrailingMargin : 0); + } else { + extraMarginRight = (isLastColumnOnPage ? extraTrailingMargin : 0); + extraMarginLeft = (isFirstColumnOnPage ? sizes.leadingEdge : 0); + } + + marginRight = extraMarginRight + sizes.itemMarginRight + "px"; + marginLeft = extraMarginLeft + sizes.itemMarginLeft + "px"; + } else { + marginRight = ""; + marginLeft = ""; + } + + if (itemEl.style.marginRight !== marginRight) { + itemEl.style.marginRight = marginRight; + } + if (itemEl.style.marginLeft !== marginLeft) { + itemEl.style.marginLeft = marginLeft; + } + if (itemEl.style.width !== width) { + itemEl.style.width = width; + } + } + }, + + _updatePageUI: function NavBarContainer_updatePageUI() { + this._measure(); + var currentPage = this._currentPage; + + this._hasPreviousContent = (currentPage !== 0); + this._hasNextContent = (currentPage < this._sizes.pages - 1); + this._updateArrows(); + + // Always output the pagination indicators so they reserves up space. + if (this._indicatorCount !== this._sizes.pages) { + this._indicatorCount = this._sizes.pages; + this._pageindicatorsEl.innerHTML = new Array(this._sizes.pages + 1).join(''); + } + + for (var i = 0; i < this._pageindicatorsEl.children.length; i++) { + if (i === currentPage) { + _ElementUtilities.addClass(this._pageindicatorsEl.children[i], NavBarContainer._ClassName.currentindicator); + } else { + _ElementUtilities.removeClass(this._pageindicatorsEl.children[i], NavBarContainer._ClassName.currentindicator); + } + } + + if (this._sizes.pages > 1) { + this._viewportEl.style.overflowX = this._panningDisabled ? "hidden" : ""; + this._pageindicatorsEl.style.visibility = ""; + } else { + this._viewportEl.style.overflowX = "hidden"; + this._pageindicatorsEl.style.visibility = "hidden"; + } + + if (this._sizes.pages <= 1 || this._layout !== _UI.Orientation.horizontal) { + this._ariaStartMarker.removeAttribute("aria-flowto"); + this._ariaEndMarker.removeAttribute("x-ms-aria-flowfrom"); + } else { + var firstIndexOnCurrentPage = currentPage * this._sizes.rowsPerPage * this._sizes.columnsPerPage; + var firstItem = this._surfaceEl.children[firstIndexOnCurrentPage].winControl._buttonEl; + _ElementUtilities._ensureId(firstItem); + this._ariaStartMarker.setAttribute("aria-flowto", firstItem.id); + + var lastIndexOnCurrentPage = Math.min(this._surfaceEl.children.length - 1, (currentPage + 1) * this._sizes.rowsPerPage * this._sizes.columnsPerPage - 1); + var lastItem = this._surfaceEl.children[lastIndexOnCurrentPage].winControl._buttonEl; + _ElementUtilities._ensureId(lastItem); + this._ariaEndMarker.setAttribute("x-ms-aria-flowfrom", lastItem.id); + } + }, + + _closeSplitIfOpen: function NavBarContainer_closeSplitIfOpen() { + if (this._currentSplitNavItem) { + if (this._currentSplitNavItem.splitOpened) { + this._currentSplitNavItem._toggleSplit(); + } + this._currentSplitNavItem = null; + } + }, + + _updateArrows: function NavBarContainer_updateArrows() { + var hasLeftContent = this._sizes.rtl ? this._hasNextContent : this._hasPreviousContent; + var hasRightContent = this._sizes.rtl ? this._hasPreviousContent : this._hasNextContent; + + var that = this; + // Previous and next are the arrows, not states. On mouse hover the arrows fade in immediately. If you + // mouse out the arrows fade out after a delay. When you reach the last/first page, the corresponding + // arrow fades out immediately as well. + if ((this._mouseInViewport || this._panningDisabled) && hasLeftContent) { + this._leftArrowWaitingToFadeOut && this._leftArrowWaitingToFadeOut.cancel(); + this._leftArrowWaitingToFadeOut = null; + this._leftArrowFadeOut && this._leftArrowFadeOut.cancel(); + this._leftArrowFadeOut = null; + this._leftArrowEl.style.visibility = ''; + this._leftArrowFadeIn = this._leftArrowFadeIn || Animations.fadeIn(this._leftArrowEl); + } else { + if (hasLeftContent) { + // If we need a delayed fade out and we are already running a delayed fade out just use that one, don't extend it. + // Otherwise create a delayed fade out. + this._leftArrowWaitingToFadeOut = this._leftArrowWaitingToFadeOut || Promise.timeout(_TransitionAnimation._animationTimeAdjustment(buttonFadeDelay)); + } else { + // If we need a immediate fade out and already have a delayed fade out cancel that one and create an immediate one. + this._leftArrowWaitingToFadeOut && this._leftArrowWaitingToFadeOut.cancel(); + this._leftArrowWaitingToFadeOut = Promise.wrap(); + } + this._leftArrowWaitingToFadeOut.then(function () { + // After the delay cancel any fade in if running. If we already were fading out continue it otherwise start the fade out. + this._leftArrowFadeIn && this._leftArrowFadeIn.cancel(); + this._leftArrowFadeIn = null; + this._leftArrowFadeOut = this._leftArrowFadeOut || Animations.fadeOut(this._leftArrowEl).then(function () { + that._leftArrowEl.style.visibility = 'hidden'; + }); + }.bind(this)); + } + + // Same pattern for Next arrow. + if ((this._mouseInViewport || this._panningDisabled) && hasRightContent) { + this._rightArrowWaitingToFadeOut && this._rightArrowWaitingToFadeOut.cancel(); + this._rightArrowWaitingToFadeOut = null; + this._rightArrowFadeOut && this._rightArrowFadeOut.cancel(); + this._rightArrowFadeOut = null; + this._rightArrowEl.style.visibility = ''; + this._rightArrowFadeIn = this._rightArrowFadeIn || Animations.fadeIn(this._rightArrowEl); + } else { + if (hasRightContent) { + this._rightArrowWaitingToFadeOut = this._rightArrowWaitingToFadeOut || Promise.timeout(_TransitionAnimation._animationTimeAdjustment(buttonFadeDelay)); + } else { + this._rightArrowWaitingToFadeOut && this._rightArrowWaitingToFadeOut.cancel(); + this._rightArrowWaitingToFadeOut = Promise.wrap(); + } + this._rightArrowWaitingToFadeOut.then(function () { + this._rightArrowFadeIn && this._rightArrowFadeIn.cancel(); + this._rightArrowFadeIn = null; + this._rightArrowFadeOut = this._rightArrowFadeOut || Animations.fadeOut(this._rightArrowEl).then(function () { + that._rightArrowEl.style.visibility = 'hidden'; + }); + }.bind(this)); + } + }, + + _navbarCommandInvokedHandler: function NavBarContainer_navbarCommandInvokedHandler(ev) { + var srcElement = ev.target; + var index = -1; + while (srcElement) { + index++; + srcElement = srcElement.previousSibling; + } + + this._fireEvent(NavBarContainer._EventName.invoked, { + index: index, + navbarCommand: ev.target.winControl, + data: this._repeater ? this._repeater.data.getAt(index) : null + }); + }, + + _navbarCommandSplitToggleHandler: function NavBarContainer_navbarCommandSplitToggleHandler(ev) { + var srcElement = ev.target; + var index = -1; + while (srcElement) { + index++; + srcElement = srcElement.previousSibling; + } + + var navbarCommand = ev.target.winControl; + + this._closeSplitIfOpen(); + + if (navbarCommand.splitOpened) { + this._currentSplitNavItem = navbarCommand; + } + + this._fireEvent(NavBarContainer._EventName.splitToggle, { + opened: navbarCommand.splitOpened, + index: index, + navbarCommand: navbarCommand, + data: this._repeater ? this._repeater.data.getAt(index) : null + }); + }, + + _fireEvent: function NavBarContainer_fireEvent(type, detail) { + var event = _Global.document.createEvent("CustomEvent"); + event.initCustomEvent(type, true, false, detail); + this.element.dispatchEvent(event); + }, + + _writeProfilerMark: function NavBarContainer_writeProfilerMark(text) { + var message = "WinJS.UI.NavBarContainer:" + this._id + ":" + text; + _WriteProfilerMark(message); + _Log.log && _Log.log(message, null, "navbarcontainerprofiler"); + }, + + dispose: function NavBarContainer_dispose() { + /// + /// + /// Disposes this control. + /// + /// + /// + if (this._disposed) { + return; + } + this._disposed = true; + + if (this._appBarEl) { + this._appBarEl.removeEventListener('beforeopen', this._closeSplitAndResetBound); + this._appBarEl.removeEventListener('beforeopen', this._resizeImplBound); + } + + Navigation.removeEventListener('navigated', this._closeSplitAndResetBound); + + this._leftArrowWaitingToFadeOut && this._leftArrowWaitingToFadeOut.cancel(); + this._leftArrowFadeOut && this._leftArrowFadeOut.cancel(); + this._leftArrowFadeIn && this._leftArrowFadeIn.cancel(); + this._rightArrowWaitingToFadeOut && this._rightArrowWaitingToFadeOut.cancel(); + this._rightArrowFadeOut && this._rightArrowFadeOut.cancel(); + this._rightArrowFadeIn && this._rightArrowFadeIn.cancel(); + + _ElementUtilities._resizeNotifier.unsubscribe(this._element, this._boundResizeHandler); + + this._removeDataChangingEvents(); + this._removeDataChangedEvents(); + } + }, { + // Names of classes used by the NavBarContainer. + _ClassName: { + navbarcontainer: "win-navbarcontainer", + pageindicators: "win-navbarcontainer-pageindicator-box", + indicator: "win-navbarcontainer-pageindicator", + currentindicator: "win-navbarcontainer-pageindicator-current", + vertical: "win-navbarcontainer-vertical", + horizontal: "win-navbarcontainer-horizontal", + viewport: "win-navbarcontainer-viewport", + surface: "win-navbarcontainer-surface", + navarrow: "win-navbarcontainer-navarrow", + navleftarrow: "win-navbarcontainer-navleft", + navrightarrow: "win-navbarcontainer-navright" + }, + _EventName: { + invoked: eventNames.invoked, + splitToggle: eventNames.splittoggle + } + }); + _Base.Class.mix(NavBarContainer, _Control.DOMEventMixin); + return NavBarContainer; + }) + }); + +}); + + +define('require-style!less/styles-navbar',[],function(){}); + +define('require-style!less/colors-navbar',[],function(){}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('WinJS/Controls/NavBar',[ + '../Core/_Global', + '../Core/_WinRT', + '../Core/_Base', + '../Core/_BaseUtils', + '../Core/_Events', + '../Core/_WriteProfilerMark', + '../Promise', + '../Scheduler', + '../Utilities/_ElementUtilities', + '../Utilities/_Hoverable', + "../_Accents", + './_LegacyAppBar', + './NavBar/_Command', + './NavBar/_Container', + 'require-style!less/styles-navbar', + 'require-style!less/colors-navbar' +], function NavBarInit(_Global,_WinRT, _Base, _BaseUtils, _Events, _WriteProfilerMark, Promise, Scheduler, _ElementUtilities, _Hoverable, _Accents, _LegacyAppBar, _Command, _Container) { + "use strict"; + + _Accents.createAccentRule("html.win-hoverable .win-navbarcommand-splitbutton.win-navbarcommand-splitbutton-opened:hover", [{ name: "background-color", value: _Accents.ColorTypes.listSelectHover }]); + _Accents.createAccentRule("html.win-hoverable .win-navbarcommand-splitbutton.win-navbarcommand-splitbutton-opened:hover.win-pressed", [{ name: "background-color", value: _Accents.ColorTypes.listSelectPress }]); + _Accents.createAccentRule(".win-navbarcommand-splitbutton.win-navbarcommand-splitbutton-opened", [{ name: "background-color", value: _Accents.ColorTypes.listSelectRest }]); + _Accents.createAccentRule(".win-navbarcommand-splitbutton.win-navbarcommand-splitbutton-opened.win-pressed", [{ name: "background-color", value: _Accents.ColorTypes.listSelectPress }]); + + var customLayout = "custom"; + + _Base.Namespace.define("WinJS.UI", { + /// + /// + /// Displays navigation commands in a toolbar that the user can open or close. + /// + /// + /// + /// + /// + /// + ///
+ ///
+ ///
+ /// ]]>
+ /// Raised just before opening the NavBar. + /// Raised immediately after an NavBar is fully opened. + /// Raised just before closing the NavBar. + /// Raised immediately after the NavBar is fully closed. + /// Fired when children of NavBar control have been processed from a WinJS.UI.processAll call. + /// Styles the entire NavBar. + /// + /// + NavBar: _Base.Namespace._lazy(function () { + var childrenProcessedEventName = "childrenprocessed"; + var createEvent = _Events._createEventProperty; + + var NavBar = _Base.Class.derive(_LegacyAppBar._LegacyAppBar, function NavBar_ctor(element, options) { + /// + /// + /// Creates a new NavBar. + /// + /// + /// The DOM element that will host the new NavBar control. + /// + /// + /// An object that contains one or more property/value pairs to apply to the new control. Each property of the options object corresponds to one of the control's + /// properties or events. + /// + /// + /// The new NavBar control. + /// + /// + /// + + options = options || {}; + + // Shallow copy object so we can modify it. + options = _BaseUtils._shallowCopy(options); + + // Default to Placement = Top and Layout = Custom + options.placement = options.placement || "top"; + options.layout = customLayout; + options.closedDisplayMode = options.closedDisplayMode || "minimal"; + + _LegacyAppBar._LegacyAppBar.call(this, element, options); + + this._element.addEventListener("beforeopen", this._handleBeforeShow.bind(this)); + + _ElementUtilities.addClass(this.element, NavBar._ClassName.navbar); + + if (_WinRT.Windows.ApplicationModel.DesignMode.designModeEnabled) { + this._processChildren(); + } else { + Scheduler.schedule(this._processChildren.bind(this), Scheduler.Priority.idle, null, "WinJS.UI.NavBar.processChildren"); + } + }, { + + // Restrict values of closedDisplayMode to 'none' or 'minimal' + + /// + /// Gets/Sets how NavBar will display itself while hidden. Values are "none" and "minimal". + /// + closedDisplayMode: { + get: function () { + return this._closedDisplayMode; + }, + set: function (value) { + var newValue = (value === "none" ? "none" : "minimal"); + Object.getOwnPropertyDescriptor(_LegacyAppBar._LegacyAppBar.prototype, "closedDisplayMode").set.call(this, newValue); + this._closedDisplayMode = newValue; + }, + }, + + /// + /// Raised when children of NavBar control have been processed by a WinJS.UI.processAll call. + /// + /// + onchildrenprocessed: createEvent(childrenProcessedEventName), + + _processChildren: function NavBar_processChildren() { + // The NavBar control schedules processAll on its children at idle priority to avoid hurting startup + // performance. If the NavBar is shown before the scheduler gets to the idle job, the NavBar will + // immediately call processAll on its children. If your app needs the children to be processed before + // the scheduled job executes, you may call processChildren to force the processAll call. + if (!this._processed) { + this._processed = true; + + this._writeProfilerMark("processChildren,StartTM"); + var that = this; + var processed = Promise.as(); + if (this._processors) { + this._processors.forEach(function (processAll) { + for (var i = 0, len = that.element.children.length; i < len; i++) { + (function (child) { + processed = processed.then(function () { + processAll(child); + }); + }(that.element.children[i])); + } + }); + } + return processed.then( + function () { + that._writeProfilerMark("processChildren,StopTM"); + that._fireEvent(NavBar._EventName.childrenProcessed); + }, + function () { + that._writeProfilerMark("processChildren,StopTM"); + that._fireEvent(NavBar._EventName.childrenProcessed); + } + ); + } + return Promise.wrap(); + }, + + _show: function NavBar_show() { + // Override _show to call processChildren first. + // + if (this.disabled) { + return; + } + var that = this; + this._processChildren().then(function () { + _LegacyAppBar._LegacyAppBar.prototype._show.call(that); + }); + }, + + _handleBeforeShow: function NavBar_handleBeforeShow() { + // Navbar needs to ensure its elements to have their correct height and width after _LegacyAppBar changes display="none" + // to display="" and _LegacyAppBar needs the elements to have their final height before it measures its own element height + // to do the slide in animation over the correct amount of pixels. + if (this._disposed) { + return; + } + + var navbarcontainerEls = this.element.querySelectorAll('.win-navbarcontainer'); + for (var i = 0; i < navbarcontainerEls.length; i++) { + navbarcontainerEls[i].winControl.forceLayout(); + } + }, + + _fireEvent: function NavBar_fireEvent(type, detail) { + var event = _Global.document.createEvent("CustomEvent"); + event.initCustomEvent(type, true, false, detail || {}); + this.element.dispatchEvent(event); + }, + + _writeProfilerMark: function NavBar_writeProfilerMark(text) { + _WriteProfilerMark("WinJS.UI.NavBar:" + this._id + ":" + text); + } + }, { + _ClassName: { + navbar: "win-navbar" + }, + _EventName: { + childrenProcessed: childrenProcessedEventName + }, + isDeclarativeControlContainer: _BaseUtils.markSupportedForProcessing(function (navbar, callback) { + if (navbar._processed) { + for (var i = 0, len = navbar.element.children.length; i < len; i++) { + callback(navbar.element.children[i]); + } + } else { + navbar._processors = navbar._processors || []; + navbar._processors.push(callback); + } + }) + }); + + return NavBar; + }) + }); + +}); + +define('require-style!less/styles-viewbox',[],function(){}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +// ViewBox control +define('WinJS/Controls/ViewBox',[ + '../Core/_Global', + '../Core/_Base', + '../Core/_BaseUtils', + '../Core/_ErrorFromName', + '../Core/_Resources', + '../Scheduler', + '../Utilities/_Control', + '../Utilities/_Dispose', + '../Utilities/_ElementUtilities', + '../Utilities/_Hoverable', + 'require-style!less/styles-viewbox' + ], function viewboxInit(_Global, _Base, _BaseUtils, _ErrorFromName, _Resources, Scheduler, _Control, _Dispose, _ElementUtilities, _Hoverable) { + "use strict"; + + _Base.Namespace.define("WinJS.UI", { + /// + /// + /// Scales a single child element to fill the available space without + /// resizing it. This control reacts to changes in the size of the container as well as + /// changes in size of the child element. For example, a media query may result in + /// a change in aspect ratio. + /// + /// + /// View Box + /// + /// + ///
ViewBox
]]>
+ /// + /// + ViewBox: _Base.Namespace._lazy(function () { + + var strings = { + get invalidViewBoxChildren() { return "ViewBox expects to only have one child element"; }, + }; + + function onresize(control) { + if (control && !control._resizing) { + control._resizing = control._resizing || 0; + control._resizing++; + try { + control._updateLayout(); + } finally { + control._resizing--; + } + } + } + + function onresizeBox(ev) { + if (ev.target) { + onresize(ev.target.winControl); + } + } + + function onresizeSizer(ev) { + if (ev.target) { + onresize(ev.target.parentElement.winControl); + } + } + + var ViewBox = _Base.Class.define(function ViewBox_ctor(element) { + /// + /// Initializes a new instance of the ViewBox control + /// + /// The DOM element that functions as the scaling box. This element fills 100% of the width and height allotted to it. + /// + /// + /// The set of options to be applied initially to the ViewBox control. + /// + /// A constructed ViewBox control. + /// + this._disposed = false; + + this._element = element || _Global.document.createElement("div"); + var box = this.element; + box.winControl = this; + _ElementUtilities.addClass(box, "win-disposable"); + _ElementUtilities.addClass(box, "win-viewbox"); + this.forceLayout(); + }, { + _sizer: null, + _element: null, + + /// + element: { + get: function () { return this._element; } + }, + + _rtl: { + get: function () { + return _Global.getComputedStyle(this.element).direction === "rtl"; + } + }, + + _initialize: function () { + var box = this.element; + if (box.firstElementChild !== this._sizer) { + if (_BaseUtils.validation) { + if (box.childElementCount !== 1) { + throw new _ErrorFromName("WinJS.UI.ViewBox.InvalidChildren", strings.invalidViewBoxChildren); + } + } + if (this._sizer) { + this._sizer.onresize = null; + } + var sizer = box.firstElementChild; + this._sizer = sizer; + if (sizer) { + _ElementUtilities._resizeNotifier.subscribe(box, onresizeBox); + box.addEventListener("mselementresize", onresizeBox); + _ElementUtilities._resizeNotifier.subscribe(sizer, onresizeSizer); + sizer.addEventListener("mselementresize", onresizeSizer); + } + if (box.clientWidth === 0 && box.clientHeight === 0) { + var that = this; + // Wait for the viewbox to get added to the DOM. It should be added + // in the synchronous block in which _initialize was called. + Scheduler.schedule(function ViewBox_async_initialize() { + that._updateLayout(); + }, Scheduler.Priority.normal, null, "WinJS.UI.ViewBox._updateLayout"); + } + } + }, + _updateLayout: function () { + var sizer = this._sizer; + if (sizer) { + var box = this.element; + var w = sizer.clientWidth; + var h = sizer.clientHeight; + var bw = box.clientWidth; + var bh = box.clientHeight; + var wRatio = bw / w; + var hRatio = bh / h; + var mRatio = Math.min(wRatio, hRatio); + var transX = Math.abs(bw - (w * mRatio)) / 2; + var transY = Math.abs(bh - (h * mRatio)) / 2; + var rtl = this._rtl; + this._sizer.style[_BaseUtils._browserStyleEquivalents["transform"].scriptName] = "translate(" + (rtl ? "-" : "") + transX + "px," + transY + "px) scale(" + mRatio + ")"; + this._sizer.style[_BaseUtils._browserStyleEquivalents["transform-origin"].scriptName] = rtl ? "top right" : "top left"; + } + }, + + dispose: function () { + /// + /// + /// Disposes this ViewBox. + /// + /// + if (this._disposed) { + return; + } + + if (this.element) { + _ElementUtilities._resizeNotifier.unsubscribe(this.element, onresizeBox); + } + if (this._sizer) { + _ElementUtilities._resizeNotifier.unsubscribe(this._sizer, onresizeSizer); + } + + this._disposed = true; + _Dispose.disposeSubTree(this._element); + }, + + forceLayout: function () { + this._initialize(); + this._updateLayout(); + } + }); + _Base.Class.mix(ViewBox, _Control.DOMEventMixin); + return ViewBox; + }) + }); + +}); + + +define('require-style!less/styles-contentdialog',[],function(){}); + +define('require-style!less/colors-contentdialog',[],function(){}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('WinJS/Controls/ContentDialog',[ + '../Application', + '../Utilities/_Dispose', + '../_Accents', + '../Promise', + '../_Signal', + '../_LightDismissService', + '../Core/_BaseUtils', + '../Core/_Global', + '../Core/_WinRT', + '../Core/_Base', + '../Core/_Events', + '../Core/_ErrorFromName', + '../Core/_Resources', + '../Utilities/_Control', + '../Utilities/_ElementUtilities', + '../Utilities/_Hoverable', + '../Animations', + 'require-style!less/styles-contentdialog', + 'require-style!less/colors-contentdialog' +], function contentDialogInit(Application, _Dispose, _Accents, Promise, _Signal, _LightDismissService, _BaseUtils, _Global, _WinRT, _Base, _Events, _ErrorFromName, _Resources, _Control, _ElementUtilities, _Hoverable, _Animations) { + "use strict"; + + _Accents.createAccentRule(".win-contentdialog-dialog", [{ name: "outline-color", value: _Accents.ColorTypes.accent }]); + + _Base.Namespace.define("WinJS.UI", { + /// + /// + /// Displays a modal dialog which can display arbitrary HTML content. + /// + /// + /// + /// + /// ]]> + /// Raised just before showing a dialog. Call preventDefault on this event to stop the dialog from being shown. + /// Raised immediately after a dialog is fully shown. + /// Raised just before hiding a dialog. Call preventDefault on this event to stop the dialog from being hidden. + /// Raised immediately after a dialog is fully hidden. + /// The entire ContentDialog control. + /// The full screen element which dims the content that is behind the dialog. + /// The main element of the dialog which holds the dialog's title, content, and commands. + /// The element which displays the dialog's title. + /// The element which contains the dialog's custom content. + /// The element which contains the dialog's primary and secondary commands. + /// The dialog's primary button. + /// The dialog's secondary button. + /// + /// + ContentDialog: _Base.Namespace._lazy(function () { + var Strings = { + get duplicateConstruction() { return "Invalid argument: Controls may only be instantiated one time for each DOM element"; }, + get controlDisposed() { return "Cannot interact with the control after it has been disposed"; }, + get contentDialogAlreadyShowing() { return "Cannot show a ContentDialog if there is already a ContentDialog that is showing"; } + }; + var DismissalResult = { + /// + /// The dialog was dismissed without the user selecting any of the commands. The user may have + /// dismissed the dialog by hitting the escape key or pressing the hardware back button. + /// + none: "none", + /// + /// The user dismissed the dialog by pressing the primary command. + /// + primary: "primary", + /// + /// The user dismissed the dialog by pressing the secondary command. + /// + secondary: "secondary" + }; + var ClassNames = { + contentDialog: "win-contentdialog", + backgroundOverlay: "win-contentdialog-backgroundoverlay", + dialog: "win-contentdialog-dialog", + title: "win-contentdialog-title", + content: "win-contentdialog-content", + commands: "win-contentdialog-commands", + primaryCommand: "win-contentdialog-primarycommand", + secondaryCommand: "win-contentdialog-secondarycommand", + + _verticalAlignment: "win-contentdialog-verticalalignment", + _scroller: "win-contentdialog-scroller", + _column0or1: "win-contentdialog-column0or1", + _visible: "win-contentdialog-visible", + _tabStop: "win-contentdialog-tabstop", + _commandSpacer: "win-contentdialog-commandspacer" + }; + var EventNames = { + beforeShow: "beforeshow", + afterShow: "aftershow", + beforeHide: "beforehide", + afterHide: "afterhide", + }; + var minContentHeightWithInputPane = 96; + + // WinJS animation promises always complete successfully. This + // helper allows an animation promise to complete in the canceled state + // so that the success handler can be skipped when the animation is + // interrupted. + function cancelablePromise(animationPromise) { + return Promise._cancelBlocker(animationPromise, function () { + animationPromise.cancel(); + }); + } + + function onInputPaneShown(eventObject) { + /*jshint validthis: true */ + eventObject.ensuredFocusedElementInView = true; + this.dialog._renderForInputPane(eventObject.occludedRect.height); + } + + function onInputPaneHidden() { + /*jshint validthis: true */ + this.dialog._clearInputPaneRendering(); + } + + // Noop function, used in the various states to indicate that they don't support a given + // message. Named with the somewhat cute name '_' because it reads really well in the states. + + function _() { } + + // Implementing the control as a state machine helps us correctly handle: + // - re-entrancy while firing events + // - calls into the control during asynchronous operations (e.g. animations) + // + // Many of the states do their "enter" work within a promise chain. The idea is that if + // the state is interrupted and exits, the rest of its work can be skipped by canceling + // the promise chain. + // An interesting detail is that anytime the state may call into app code (e.g. due to + // firing an event), the current promise must end and a new promise must be chained off of it. + // This is necessary because the app code may interact with the ContentDialog and cause it to + // change states. If we didn't create a new promise, then the very next line of code that runs + // after calling into app code may not be valid because the state may have exited. Starting a + // new promise after each call into app code prevents us from having to worry about this + // problem. In this configuration, when a promise's success handler runs, it guarantees that + // the state hasn't exited. + // For similar reasons, each of the promise chains created in "enter" starts off with a _Signal + // which is completed at the end of the "enter" function (this boilerplate is abstracted away by + // the "interruptible" function). The reason is that we don't want any of the code in "enter" + // to run until the promise chain has been stored in a variable. If we didn't do this (e.g. instead, + // started the promise chain with Promise.wrap()), then the "enter" code could trigger the "exit" + // function (via app code) before the promise chain had been stored in a variable. Under these + // circumstances, the promise chain would be uncancelable and so the "enter" work would be + // unskippable. This wouldn't be good when we needed the state to exit early. + + // These two functions manage interruptible work promises (one creates them the other cancels + // them). They communicate with each other thru the _interruptibleWorkPromises property which + // "interruptible" creates on your object. + + function interruptible(object, workFn) { + object._interruptibleWorkPromises = object._interruptibleWorkPromises || []; + var workStoredSignal = new _Signal(); + object._interruptibleWorkPromises.push(workFn(object, workStoredSignal.promise)); + workStoredSignal.complete(); + } + + function cancelInterruptibles() { + /*jshint validthis: true */ + (this._interruptibleWorkPromises || []).forEach(function (workPromise) { + workPromise.cancel(); + }); + } + + // Transitions: + // When created, the control will take the following initialization transition: + // Init -> Hidden + // Following that, the life of the dialog will be dominated by the following 3 + // sequences of transitions. In geneneral, these sequences are uninterruptible. + // Hidden -> BeforeShow -> Hidden (when preventDefault is called on beforeshow event) + // Hidden -> BeforeShow -> Showing -> Shown + // Shown -> BeforeHide -> Hiding -> Hidden + // Shown -> BeforeHide -> Shown (when preventDefault is called on beforehide event) + // However, any state can be interrupted to go to the Disposed state: + // * -> Disposed + // + // interface IContentDialogState { + // // Debugging + // name: string; + // // State lifecycle + // enter(arg0); + // exit(); + // // ContentDialog's public API surface + // hidden: boolean; + // show(); + // hide(dismissalResult); + // // Events + // onCommandClicked(dismissalResult); + // onInputPaneShown(eventObject); + // onInputPaneHidden(); + // // Provided by _setState for use within the state + // dialog: WinJS.UI.ContentDialog; + // } + + var States = { + // Initial state. Initializes state on the dialog shared by the various states. + Init: _Base.Class.define(null, { + name: "Init", + hidden: true, + enter: function ContentDialog_InitState_enter() { + var dialog = this.dialog; + dialog._dismissable = new _LightDismissService.ModalElement({ + element: dialog._dom.root, + tabIndex: dialog._dom.root.hasAttribute("tabIndex") ? dialog._dom.root.tabIndex : -1, + onLightDismiss: function () { + dialog.hide(DismissalResult.none); + }, + onTakeFocus: function (useSetActive) { + dialog._dismissable.restoreFocus() || + _ElementUtilities._focusFirstFocusableElement(dialog._dom.content) || + _ElementUtilities._tryFocusOnAnyElement(dialog._dom.dialog, useSetActive); + } + }); + this.dialog._dismissedSignal = null; // The signal will be created on demand when show() is called + this.dialog._setState(States.Hidden, false); + }, + exit: _, + show: function ContentDialog_InitState_show() { + throw "It's illegal to call show on the Init state"; + }, + hide: _, + onCommandClicked: _, + onInputPaneShown: _, + onInputPaneHidden: _ + }), + // A rest state. The dialog is hidden and is waiting for the app to call show. + Hidden: _Base.Class.define(null, { + name: "Hidden", + hidden: true, + enter: function ContentDialog_HiddenState_enter(showIsPending) { + if (showIsPending) { + this.show(); + } + }, + exit: _, + show: function ContentDialog_HiddenState_show() { + var dismissedSignal = this.dialog._dismissedSignal = new _Signal(); // save the signal in case it changes when switching states + this.dialog._setState(States.BeforeShow); + return dismissedSignal.promise; + }, + hide: _, + onCommandClicked: _, + onInputPaneShown: _, + onInputPaneHidden: _ + }), + // An event state. The dialog fires the beforeshow event. + BeforeShow: _Base.Class.define(null, { + name: "BeforeShow", + hidden: true, + enter: function ContentDialog_BeforeShowState_enter() { + interruptible(this, function (that, ready) { + return ready.then(function () { + return that.dialog._fireBeforeShow(); // Give opportunity for chain to be canceled when calling into app code + }).then(function (shouldShow) { + if (!shouldShow) { + that.dialog._cancelDismissalPromise(null); // Give opportunity for chain to be canceled when calling into app code + } + return shouldShow; + }).then(function (shouldShow) { + if (shouldShow) { + that.dialog._setState(States.Showing); + } else { + that.dialog._setState(States.Hidden, false); + } + }); + }); + }, + exit: cancelInterruptibles, + show: function ContentDialog_BeforeShowState_show() { + return Promise.wrapError(new _ErrorFromName("WinJS.UI.ContentDialog.ContentDialogAlreadyShowing", Strings.contentDialogAlreadyShowing)); + }, + hide: _, + onCommandClicked: _, + onInputPaneShown: _, + onInputPaneHidden: _ + }), + // An animation/event state. The dialog plays its entrance animation and fires aftershow. + Showing: _Base.Class.define(null, { + name: "Showing", + hidden: { + get: function ContentDialog_ShowingState_hidden_get() { + return !!this._pendingHide; + } + }, + enter: function ContentDialog_ShowingState_enter() { + interruptible(this, function (that, ready) { + return ready.then(function () { + that._pendingHide = null; + _ElementUtilities.addClass(that.dialog._dom.root, ClassNames._visible); + that.dialog._addExternalListeners(); + if (_WinRT.Windows.UI.ViewManagement.InputPane) { + var inputPaneHeight = _WinRT.Windows.UI.ViewManagement.InputPane.getForCurrentView().occludedRect.height; + if (inputPaneHeight > 0) { + that.dialog._renderForInputPane(inputPaneHeight); + } + } + _LightDismissService.shown(that.dialog._dismissable); + return that.dialog._playEntranceAnimation(); + }).then(function () { + that.dialog._fireEvent(EventNames.afterShow); // Give opportunity for chain to be canceled when calling into app code + }).then(function () { + that.dialog._setState(States.Shown, that._pendingHide); + }); + }); + }, + exit: cancelInterruptibles, + show: function ContentDialog_ShowingState_show() { + if (this._pendingHide) { + var dismissalResult = this._pendingHide.dismissalResult; + this._pendingHide = null; + return this.dialog._resetDismissalPromise(dismissalResult, new _Signal()).promise; + } else { + return Promise.wrapError(new _ErrorFromName("WinJS.UI.ContentDialog.ContentDialogAlreadyShowing", Strings.contentDialogAlreadyShowing)); + } + }, + hide: function ContentDialog_ShowingState_hide(dismissalResult) { + this._pendingHide = { dismissalResult: dismissalResult }; + }, + onCommandClicked: _, + onInputPaneShown: onInputPaneShown, + onInputPaneHidden: onInputPaneHidden + }), + // A rest state. The dialog is shown and is waiting for the user or the app to trigger hide. + Shown: _Base.Class.define(null, { + name: "Shown", + hidden: false, + enter: function ContentDialog_ShownState_enter(pendingHide) { + if (pendingHide) { + this.hide(pendingHide.dismissalResult); + } + }, + exit: _, + show: function ContentDialog_ShownState_show() { + return Promise.wrapError(new _ErrorFromName("WinJS.UI.ContentDialog.ContentDialogAlreadyShowing", Strings.contentDialogAlreadyShowing)); + }, + hide: function ContentDialog_ShownState_hide(dismissalResult) { + this.dialog._setState(States.BeforeHide, dismissalResult); + }, + onCommandClicked: function ContentDialog_ShownState_onCommandClicked(dismissalResult) { + this.hide(dismissalResult); + }, + onInputPaneShown: onInputPaneShown, + onInputPaneHidden: onInputPaneHidden + }), + // An event state. The dialog fires the beforehide event. + BeforeHide: _Base.Class.define(null, { + name: "BeforeHide", + hidden: false, + enter: function ContentDialog_BeforeHideState_enter(dismissalResult) { + interruptible(this, function (that, ready) { + return ready.then(function () { + return that.dialog._fireBeforeHide(dismissalResult); // Give opportunity for chain to be canceled when calling into app code + }).then(function (shouldHide) { + if (shouldHide) { + that.dialog._setState(States.Hiding, dismissalResult); + } else { + that.dialog._setState(States.Shown, null); + } + }); + }); + }, + exit: cancelInterruptibles, + show: function ContentDialog_BeforeHideState_show() { + return Promise.wrapError(new _ErrorFromName("WinJS.UI.ContentDialog.ContentDialogAlreadyShowing", Strings.contentDialogAlreadyShowing)); + }, + hide: _, + onCommandClicked: _, + onInputPaneShown: onInputPaneShown, + onInputPaneHidden: onInputPaneHidden + }), + // An animation/event state. The dialog plays the exit animation and fires the afterhide event. + Hiding: _Base.Class.define(null, { + name: "Hiding", + hidden: { + get: function ContentDialog_HidingState_hidden_get() { + return !this._showIsPending; + } + }, + enter: function ContentDialog_HidingState_enter(dismissalResult) { + interruptible(this, function (that, ready) { + return ready.then(function () { + that._showIsPending = false; + that.dialog._resetDismissalPromise(dismissalResult, null); // Give opportunity for chain to be canceled when calling into app code + }).then(function () { + return that.dialog._playExitAnimation(); + }).then(function () { + that.dialog._removeExternalListeners(); + _LightDismissService.hidden(that.dialog._dismissable); + _ElementUtilities.removeClass(that.dialog._dom.root, ClassNames._visible); + that.dialog._clearInputPaneRendering(); + that.dialog._fireAfterHide(dismissalResult); // Give opportunity for chain to be canceled when calling into app code + }).then(function () { + that.dialog._setState(States.Hidden, that._showIsPending); + }); + }); + }, + exit: cancelInterruptibles, + show: function ContentDialog_HidingState_show() { + if (this._showIsPending) { + return Promise.wrapError(new _ErrorFromName("WinJS.UI.ContentDialog.ContentDialogAlreadyShowing", Strings.contentDialogAlreadyShowing)); + } else { + this._showIsPending = true; + this.dialog._dismissedSignal = new _Signal(); + return this.dialog._dismissedSignal.promise; + } + }, + hide: function ContentDialog_HidingState_hide(dismissalResult) { + if (this._showIsPending) { + this._showIsPending = false; + this.dialog._resetDismissalPromise(dismissalResult, null); + } + }, + onCommandClicked: _, + onInputPaneShown: _, + onInputPaneHidden: _ + }), + Disposed: _Base.Class.define(null, { + name: "Disposed", + hidden: true, + enter: function ContentDialog_DisposedState_enter() { + _LightDismissService.hidden(this.dialog._dismissable); + this.dialog._removeExternalListeners(); + if (this.dialog._dismissedSignal) { + this.dialog._dismissedSignal.error(new _ErrorFromName("WinJS.UI.ContentDialog.ControlDisposed", Strings.controlDisposed)); + } + }, + exit: _, + show: function ContentDialog_DisposedState_show() { + return Promise.wrapError(new _ErrorFromName("WinJS.UI.ContentDialog.ControlDisposed", Strings.controlDisposed)); + }, + hide: _, + onCommandClicked: _, + onInputPaneShown: _, + onInputPaneHidden: _ + }), + }; + + var ContentDialog = _Base.Class.define(function ContentDialog_ctor(element, options) { + /// + /// + /// Creates a new ContentDialog control. + /// + /// + /// The DOM element that hosts the ContentDialog control. + /// + /// + /// An object that contains one or more property/value pairs to apply to the new control. + /// Each property of the options object corresponds to one of the control's properties or events. + /// Event names must begin with "on". For example, to provide a handler for the beforehide event, + /// add a property named "onbeforehide" to the options object and set its value to the event handler. + /// + /// + /// The new ContentDialog. + /// + /// + + // Check to make sure we weren't duplicated + if (element && element.winControl) { + throw new _ErrorFromName("WinJS.UI.ContentDialog.DuplicateConstruction", Strings.duplicateConstruction); + } + options = options || {}; + + this._onInputPaneShownBound = this._onInputPaneShown.bind(this); + this._onInputPaneHiddenBound = this._onInputPaneHidden.bind(this); + + this._disposed = false; + this._resizedForInputPane = false; + this._currentFocus = null; + + this._initializeDom(element || _Global.document.createElement("div")); + this._setState(States.Init); + + this.title = ""; + this.primaryCommandText = ""; + this.primaryCommandDisabled = false; + this.secondaryCommandText = ""; + this.secondaryCommandDisabled = false; + + _Control.setOptions(this, options); + }, { + /// + element: { + get: function ContentDialog_element_get() { + return this._dom.root; + } + }, + + /// + /// The text displayed as the title of the dialog. + /// + title: { + get: function ContentDialog_title_get() { + return this._title; + }, + set: function ContentDialog_title_set(value) { + value = value || ""; + if (this._title !== value) { + this._title = value; + this._dom.title.textContent = value; + this._dom.title.style.display = value ? "" : "none"; + } + } + }, + + /// + /// The text displayed on the primary command's button. + /// + primaryCommandText: { + get: function ContentDialog_primaryCommandText_get() { + return this._primaryCommandText; + }, + set: function ContentDialog_primaryCommandText_set(value) { + value = value || ""; + if (this._primaryCommandText !== value) { + this._primaryCommandText = value; + this._dom.commands[0].textContent = value; + this._updateCommandsUI(); + } + } + }, + + /// + /// The text displayed on the secondary command's button. + /// + secondaryCommandText: { + get: function ContentDialog_secondaryCommandText_get() { + return this._secondaryCommandText; + }, + set: function ContentDialog_secondaryCommandText_set(value) { + value = value || ""; + if (this._secondaryCommandText !== value) { + this._secondaryCommandText = value; + this._dom.commands[1].textContent = value; + this._updateCommandsUI(); + } + } + }, + + /// + /// Indicates whether the button representing the primary command is currently disabled. + /// + primaryCommandDisabled: { + get: function ContentDialog_primaryCommandDisabled_get() { + return this._primaryCommandDisabled; + }, + set: function ContentDialog_primaryCommandDisabled_set(value) { + value = !!value; + if (this._primaryCommandDisabled !== value) { + this._primaryCommandDisabled = value; + this._dom.commands[0].disabled = value; + } + } + }, + + /// + /// Indicates whether the button representing the secondary command is currently disabled. + /// + secondaryCommandDisabled: { + get: function ContentDialog_secondaryCommandDisabled_get() { + return this._secondaryCommandDisabled; + }, + set: function ContentDialog_secondaryCommandDisabled_set(value) { + value = !!value; + if (this._secondaryCommandDisabled !== value) { + this._secondaryCommandDisabled = value; + this._dom.commands[1].disabled = value; + } + } + }, + + /// + hidden: { + get: function ContentDialog_hidden_get() { + return this._state.hidden; + }, + set: function ContentDialog_hidden_set(hidden) { + if (!hidden && this._state.hidden) { + var nop = function () { + }; + // Show returns a promise. If hidden is set while the ContentDialog is disposed, show will return a promise + // error which will be impossible to handle and it'll cause the app to terminate. We'll eat the promise returned by show + // to stop that from happening. + this.show().done(nop, nop); + } else if (hidden && !this._state.hidden) { + this.hide(DismissalResult.none); + } + } + }, + + dispose: function ContentDialog_dispose() { + /// + /// + /// Disposes this control. + /// + /// + if (this._disposed) { + return; + } + this._setState(States.Disposed); + this._disposed = true; + _Dispose._disposeElement(this._dom.content); + }, + + show: function ContentDialog_show() { + /// + /// + /// Shows the ContentDialog. Only one ContentDialog may be shown at a time. If another + /// ContentDialog is already shown, this ContentDialog will remain hidden. + /// + /// + /// A promise which is successfully fulfilled when the dialog is dismissed. The + /// completion value indicates the dialog's dismissal result. This may + /// be 'primary', 'secondary', 'none', or whatever custom value was passed to hide. + /// If this ContentDialog cannot be shown because a ContentDialog is already showing + /// or the ContentDialog is disposed, then the return value is a promise which is in + /// an error state. If preventDefault() is called on the beforeshow event, then this + /// promise will be canceled. + /// + /// + return this._state.show(); + }, + + hide: function ContentDialog_hide(result) { + /// + /// + /// Hides the ContentDialog. + /// + /// + /// A value indicating why the dialog is being hidden. The promise returned + /// by show will be fulfilled with this value. + /// + /// + this._state.hide(result === undefined ? DismissalResult.none : result); + }, + + _initializeDom: function ContentDialog_initializeDom(root) { + // Reparent the children of the root element into the content element. + var contentEl = _Global.document.createElement("div"); + contentEl.className = ClassNames.content; + _ElementUtilities._reparentChildren(root, contentEl); + + root.winControl = this; + _ElementUtilities.addClass(root, ClassNames.contentDialog); + _ElementUtilities.addClass(root, ClassNames._verticalAlignment); + _ElementUtilities.addClass(root, "win-disposable"); + root.innerHTML = + '
' + + '
' + + '' + + '
' + + '
'; + + var dom = {}; + dom.root = root; + dom.backgroundOverlay = dom.root.firstElementChild; + dom.startBodyTab = dom.backgroundOverlay.nextElementSibling; + dom.dialog = dom.startBodyTab.nextElementSibling; + dom.title = dom.dialog.firstElementChild; + dom.scroller = dom.title.nextElementSibling; + dom.commandContainer = dom.scroller.nextElementSibling; + dom.commandSpacer = dom.commandContainer.firstElementChild; + dom.commands = []; + dom.commands.push(dom.commandSpacer.nextElementSibling); + dom.commands.push(dom.commands[0].nextElementSibling); + dom.endBodyTab = dom.dialog.nextElementSibling; + dom.content = contentEl; + this._dom = dom; + + // Put the developer's content into the scroller + dom.scroller.appendChild(dom.content); + + _ElementUtilities._ensureId(dom.title); + _ElementUtilities._ensureId(dom.startBodyTab); + _ElementUtilities._ensureId(dom.endBodyTab); + dom.dialog.setAttribute("aria-labelledby", dom.title.id); + dom.startBodyTab.setAttribute("x-ms-aria-flowfrom", dom.endBodyTab.id); + dom.endBodyTab.setAttribute("aria-flowto", dom.startBodyTab.id); + this._updateTabIndices(); + + dom.root.addEventListener("keydown", this._onKeyDownEnteringElement.bind(this), true); + _ElementUtilities._addEventListener(dom.root, "pointerdown", this._onPointerDown.bind(this)); + _ElementUtilities._addEventListener(dom.root, "pointerup", this._onPointerUp.bind(this)); + dom.root.addEventListener("click", this._onClick.bind(this)); + _ElementUtilities._addEventListener(dom.startBodyTab, "focusin", this._onStartBodyTabFocusIn.bind(this)); + _ElementUtilities._addEventListener(dom.endBodyTab, "focusin", this._onEndBodyTabFocusIn.bind(this)); + dom.commands[0].addEventListener("click", this._onCommandClicked.bind(this, DismissalResult.primary)); + dom.commands[1].addEventListener("click", this._onCommandClicked.bind(this, DismissalResult.secondary)); + }, + + _updateCommandsUI: function ContentDialog_updateCommandsUI() { + this._dom.commands[0].style.display = this.primaryCommandText ? "" : "none"; + this._dom.commands[1].style.display = this.secondaryCommandText ? "" : "none"; + + // commandSpacer's purpose is to ensure that when only 1 button is shown, that button takes up half + // the width of the dialog and is right-aligned. It works by: + // - When only one command is shown: + // - Coming before the other command in the DOM (so the other command will look right-aligned) + // - Having the same flex-grow as the other command (so it occupies half of the space) + // - Having visibility: hidden (so it's invisible but it takes up space) + // - When both commands are shown: + // - Having display: none (so it doesn't occupy any space and the two shown commands each take up half the dialog) + // - When 0 commands are shown: + // - Having display: none (so the commands area takes up no space) + this._dom.commandSpacer.style.display = this.primaryCommandText && !this.secondaryCommandText || !this.primaryCommandText && this.secondaryCommandText ? "" : "none"; + }, + + // _updateTabIndices and _updateTabIndicesImpl are used in tests + _updateTabIndices: function ContentDialog_updateTabIndices() { + if (!this._updateTabIndicesThrottled) { + this._updateTabIndicesThrottled = _BaseUtils._throttledFunction(100, this._updateTabIndicesImpl.bind(this)); + } + this._updateTabIndicesThrottled(); + }, + _updateTabIndicesImpl: function ContentDialog_updateTabIndicesImpl() { + var tabIndex = _ElementUtilities._getHighAndLowTabIndices(this._dom.content); + this._dom.startBodyTab.tabIndex = tabIndex.lowest; + this._dom.commands[0].tabIndex = tabIndex.highest; + this._dom.commands[1].tabIndex = tabIndex.highest; + this._dom.endBodyTab.tabIndex = tabIndex.highest; + }, + + _elementInDialog: function ContentDialog_elementInDialog(element) { + return this._dom.dialog.contains(element) || element === this._dom.startBodyTab || element === this._dom.endBodyTab; + }, + + _onCommandClicked: function ContentDialog_onCommandClicked(dismissalResult) { + this._state.onCommandClicked(dismissalResult); + }, + + _onPointerDown: function ContentDialog_onPointerDown(eventObject) { + eventObject.stopPropagation(); + if (!this._elementInDialog(eventObject.target)) { + eventObject.preventDefault(); + } + }, + + _onPointerUp: function ContentDialog_onPointerUp(eventObject) { + eventObject.stopPropagation(); + if (!this._elementInDialog(eventObject.target)) { + eventObject.preventDefault(); + } + }, + + _onClick: function ContentDialog_onClick(eventObject) { + eventObject.stopPropagation(); + if (!this._elementInDialog(eventObject.target)) { + eventObject.preventDefault(); + } + }, + + _onKeyDownEnteringElement: function ContentDialog_onKeyDownEnteringElement(eventObject) { + if (eventObject.keyCode === _ElementUtilities.Key.tab) { + this._updateTabIndices(); + } + }, + + _onStartBodyTabFocusIn: function ContentDialog_onStartBodyTabFocusIn() { + _ElementUtilities._focusLastFocusableElement(this._dom.dialog); + }, + + _onEndBodyTabFocusIn: function ContentDialog_onEndBodyTabFocusIn() { + _ElementUtilities._focusFirstFocusableElement(this._dom.dialog); + }, + + _onInputPaneShown: function ContentDialog_onInputPaneShown(eventObject) { + this._state.onInputPaneShown(eventObject.detail.originalEvent); + }, + + _onInputPaneHidden: function ContentDialog_onInputPaneHidden() { + this._state.onInputPaneHidden(); + }, + + // + // Methods called by states + // + + _setState: function ContentDialog_setState(NewState, arg0) { + if (!this._disposed) { + this._state && this._state.exit(); + this._state = new NewState(); + this._state.dialog = this; + this._state.enter(arg0); + } + }, + + // Calls into arbitrary app code + _resetDismissalPromise: function ContentDialog_resetDismissalPromise(dismissalResult, newSignal) { + var dismissedSignal = this._dismissedSignal; + var newDismissedSignal = this._dismissedSignal = newSignal; + dismissedSignal.complete({ result: dismissalResult }); + return newDismissedSignal; + }, + + // Calls into arbitrary app code + _cancelDismissalPromise: function ContentDialog_cancelDismissalPromise(newSignal) { + var dismissedSignal = this._dismissedSignal; + var newDismissedSignal = this._dismissedSignal = newSignal; + dismissedSignal.cancel(); + return newDismissedSignal; + }, + + // Calls into arbitrary app code + _fireEvent: function ContentDialog_fireEvent(eventName, options) { + options = options || {}; + var detail = options.detail || null; + var cancelable = !!options.cancelable; + + var eventObject = _Global.document.createEvent("CustomEvent"); + eventObject.initCustomEvent(eventName, true, cancelable, detail); + return this._dom.root.dispatchEvent(eventObject); + }, + + // Calls into arbitrary app code + _fireBeforeShow: function ContentDialog_fireBeforeShow() { + return this._fireEvent(EventNames.beforeShow, { + cancelable: true + }); + }, + + // Calls into arbitrary app code + _fireBeforeHide: function ContentDialog_fireBeforeHide(dismissalResult) { + return this._fireEvent(EventNames.beforeHide, { + detail: { result: dismissalResult }, + cancelable: true + }); + }, + + // Calls into arbitrary app code + _fireAfterHide: function ContentDialog_fireAfterHide(dismissalResult) { + this._fireEvent(EventNames.afterHide, { + detail: { result: dismissalResult } + }); + }, + + _playEntranceAnimation: function ContentDialog_playEntranceAnimation() { + return cancelablePromise(_Animations.fadeIn(this._dom.root)); + }, + + _playExitAnimation: function ContentDialog_playExitAnimation() { + return cancelablePromise(_Animations.fadeOut(this._dom.root)); + }, + + _addExternalListeners: function ContentDialog_addExternalListeners() { + _ElementUtilities._inputPaneListener.addEventListener(this._dom.root, "showing", this._onInputPaneShownBound); + _ElementUtilities._inputPaneListener.addEventListener(this._dom.root, "hiding", this._onInputPaneShownBound); + }, + + _removeExternalListeners: function ContentDialog_removeExternalListeners() { + _ElementUtilities._inputPaneListener.removeEventListener(this._dom.root, "showing", this._onInputPaneShownBound); + _ElementUtilities._inputPaneListener.removeEventListener(this._dom.root, "hiding", this._onInputPaneShownBound); + }, + + _renderForInputPane: function ContentDialog_renderForInputPane(inputPaneHeight) { + this._clearInputPaneRendering(); + + var dialog = this._dom.dialog; + var style = dialog.style; + var left = dialog.offsetLeft; + var top = dialog.offsetTop; + var height = dialog.offsetHeight; + var bottom = top + height; + var visibleBottom = this._dom.root.offsetHeight - inputPaneHeight; + var titleHeight = _ElementUtilities.getTotalHeight(this._dom.title); + var commandsHeight = _ElementUtilities.getTotalHeight(this._dom.commandContainer); + + if (bottom > visibleBottom) { + var newHeight = height - (bottom - visibleBottom); + if (newHeight - titleHeight - commandsHeight < minContentHeightWithInputPane) { + // Put title into scroller so there's more screen real estate for the content + this._dom.scroller.insertBefore(this._dom.title, this._dom.content); + } + + this._dom.root.style.display = "block"; + style.height = newHeight + "px"; + style.position = "absolute"; + style.left = left + "px"; + style.top = top + "px"; + style.minHeight = 0; + + this._resizedForInputPane = true; + _Global.document.activeElement.focus(); // Ensure activeElement is scrolled into view + } + }, + + _clearInputPaneRendering: function ContentDialog_clearInputPaneRendering() { + if (this._resizedForInputPane) { + if (this._dom.title.parentNode !== this._dom.dialog) { + // Make sure the title isn't in the scroller + this._dom.dialog.insertBefore(this._dom.title, this._dom.scroller); + } + + var style = this._dom.dialog.style; + this._dom.root.style.display = ""; + style.height = ""; + style.position = ""; + style.left = ""; + style.top = ""; + style.minHeight = ""; + this._resizedForInputPane = false; + } + } + }, { + /// + /// Specifies the result of dismissing the ContentDialog. + /// + DismissalResult: DismissalResult, + + _ClassNames: ClassNames + }); + _Base.Class.mix(ContentDialog, _Events.createEventProperties( + "beforeshow", + "aftershow", + "beforehide", + "afterhide" + )); + _Base.Class.mix(ContentDialog, _Control.DOMEventMixin); + return ContentDialog; + }) + }); +}); + + +define('require-style!less/styles-splitview',[],function(){}); + +define('require-style!less/colors-splitview',[],function(){}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// +define('WinJS/Controls/SplitView/_SplitView',["require", "exports", '../../Animations', '../../Core/_Base', '../../Core/_BaseUtils', '../../Utilities/_Control', '../../Utilities/_Dispose', '../../Utilities/_ElementUtilities', '../../Core/_ErrorFromName', '../../Core/_Events', '../../Core/_Global', '../../_LightDismissService', '../../Utilities/_OpenCloseMachine'], function (require, exports, Animations, _Base, _BaseUtils, _Control, _Dispose, _ElementUtilities, _ErrorFromName, _Events, _Global, _LightDismissService, _OpenCloseMachine) { + require(["require-style!less/styles-splitview"]); + require(["require-style!less/colors-splitview"]); + "use strict"; + var transformNames = _BaseUtils._browserStyleEquivalents["transform"]; + var Strings = { + get duplicateConstruction() { + return "Invalid argument: Controls may only be instantiated one time for each DOM element"; + } + }; + var ClassNames = { + splitView: "win-splitview", + pane: "win-splitview-pane", + content: "win-splitview-content", + // closed/opened + paneClosed: "win-splitview-pane-closed", + paneOpened: "win-splitview-pane-opened", + _panePlaceholder: "win-splitview-paneplaceholder", + _paneWrapper: "win-splitview-panewrapper", + _contentWrapper: "win-splitview-contentwrapper", + // placement + _placementLeft: "win-splitview-placementleft", + _placementRight: "win-splitview-placementright", + _placementTop: "win-splitview-placementtop", + _placementBottom: "win-splitview-placementbottom", + // closed display mode + _closedDisplayNone: "win-splitview-closeddisplaynone", + _closedDisplayInline: "win-splitview-closeddisplayinline", + // opened display mode + _openedDisplayInline: "win-splitview-openeddisplayinline", + _openedDisplayOverlay: "win-splitview-openeddisplayoverlay" + }; + var EventNames = { + beforeOpen: "beforeopen", + afterOpen: "afteropen", + beforeClose: "beforeclose", + afterClose: "afterclose" + }; + var Dimension = { + width: "width", + height: "height" + }; + var ClosedDisplayMode = { + /// + /// When the pane is closed, it is not visible and doesn't take up any space. + /// + none: "none", + /// + /// When the pane is closed, it occupies space leaving less room for the SplitView's content. + /// + inline: "inline" + }; + var OpenedDisplayMode = { + /// + /// When the pane is open, it occupies space leaving less room for the SplitView's content. + /// + inline: "inline", + /// + /// When the pane is open, it doesn't take up any space and it is light dismissable. + /// + overlay: "overlay" + }; + var PanePlacement = { + /// + /// Pane is positioned left of the SplitView's content. + /// + left: "left", + /// + /// Pane is positioned right of the SplitView's content. + /// + right: "right", + /// + /// Pane is positioned above the SplitView's content. + /// + top: "top", + /// + /// Pane is positioned below the SplitView's content. + /// + bottom: "bottom" + }; + var closedDisplayModeClassMap = {}; + closedDisplayModeClassMap[ClosedDisplayMode.none] = ClassNames._closedDisplayNone; + closedDisplayModeClassMap[ClosedDisplayMode.inline] = ClassNames._closedDisplayInline; + var openedDisplayModeClassMap = {}; + openedDisplayModeClassMap[OpenedDisplayMode.overlay] = ClassNames._openedDisplayOverlay; + openedDisplayModeClassMap[OpenedDisplayMode.inline] = ClassNames._openedDisplayInline; + var panePlacementClassMap = {}; + panePlacementClassMap[PanePlacement.left] = ClassNames._placementLeft; + panePlacementClassMap[PanePlacement.right] = ClassNames._placementRight; + panePlacementClassMap[PanePlacement.top] = ClassNames._placementTop; + panePlacementClassMap[PanePlacement.bottom] = ClassNames._placementBottom; + // Versions of add/removeClass that are no ops when called with falsy class names. + function addClass(element, className) { + className && _ElementUtilities.addClass(element, className); + } + function removeClass(element, className) { + className && _ElementUtilities.removeClass(element, className); + } + function rectToThickness(rect, dimension) { + return (dimension === Dimension.width) ? { + content: rect.contentWidth, + total: rect.totalWidth + } : { + content: rect.contentHeight, + total: rect.totalHeight + }; + } + /// + /// + /// Displays a SplitView which renders a collapsable pane next to arbitrary HTML content. + /// + /// + /// + /// + /// ]]> + /// Raised just before opening the pane. Call preventDefault on this event to stop the pane from opening. + /// Raised immediately after the pane is fully opened. + /// Raised just before closing the pane. Call preventDefault on this event to stop the pane from closing. + /// Raised immediately after the pane is fully closed. + /// The entire SplitView control. + /// The element which hosts the SplitView's pane. + /// The element which hosts the SplitView's content. + /// + /// + var SplitView = (function () { + function SplitView(element, options) { + /// + /// + /// Creates a new SplitView control. + /// + /// + /// The DOM element that hosts the SplitView control. + /// + /// + /// An object that contains one or more property/value pairs to apply to the new control. + /// Each property of the options object corresponds to one of the control's properties or events. + /// Event names must begin with "on". For example, to provide a handler for the beforeclose event, + /// add a property named "onbeforeclose" to the options object and set its value to the event handler. + /// + /// + /// The new SplitView. + /// + /// + var _this = this; + if (options === void 0) { options = {}; } + // State private to _updateDomImpl. No other method should make use of it. + // + // Nothing has been rendered yet so these are all initialized to undefined. Because + // they are undefined, the first time _updateDomImpl is called, they will all be + // rendered. + this._updateDomImpl_rendered = { + paneIsFirst: undefined, + isOpenedMode: undefined, + closedDisplayMode: undefined, + openedDisplayMode: undefined, + panePlacement: undefined, + panePlaceholderWidth: undefined, + panePlaceholderHeight: undefined, + isOverlayShown: undefined + }; + // Check to make sure we weren't duplicated + if (element && element["winControl"]) { + throw new _ErrorFromName("WinJS.UI.SplitView.DuplicateConstruction", Strings.duplicateConstruction); + } + this._initializeDom(element || _Global.document.createElement("div")); + this._machine = new _OpenCloseMachine.OpenCloseMachine({ + eventElement: this._dom.root, + onOpen: function () { + _this._cachedHiddenPaneThickness = null; + var hiddenPaneThickness = _this._getHiddenPaneThickness(); + _this._isOpenedMode = true; + _this._updateDomImpl(); + return _this._playShowAnimation(hiddenPaneThickness); + }, + onClose: function () { + return _this._playHideAnimation(_this._getHiddenPaneThickness()).then(function () { + _this._isOpenedMode = false; + _this._updateDomImpl(); + }); + }, + onUpdateDom: function () { + _this._updateDomImpl(); + }, + onUpdateDomWithIsOpened: function (isOpened) { + _this._isOpenedMode = isOpened; + _this._updateDomImpl(); + } + }); + // Initialize private state. + this._disposed = false; + this._dismissable = new _LightDismissService.LightDismissableElement({ + element: this._dom.paneWrapper, + tabIndex: -1, + onLightDismiss: function () { + _this.closePane(); + }, + onTakeFocus: function (useSetActive) { + _this._dismissable.restoreFocus() || _ElementUtilities._tryFocusOnAnyElement(_this._dom.pane, useSetActive); + } + }); + this._cachedHiddenPaneThickness = null; + // Initialize public properties. + this.paneOpened = false; + this.closedDisplayMode = ClosedDisplayMode.inline; + this.openedDisplayMode = OpenedDisplayMode.overlay; + this.panePlacement = PanePlacement.left; + _Control.setOptions(this, options); + // Exit the Init state. + _ElementUtilities._inDom(this._dom.root).then(function () { + _this._rtl = _Global.getComputedStyle(_this._dom.root).direction === 'rtl'; + _this._machine.exitInit(); + }); + } + Object.defineProperty(SplitView.prototype, "element", { + /// + get: function () { + return this._dom.root; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SplitView.prototype, "paneElement", { + /// + get: function () { + return this._dom.pane; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SplitView.prototype, "contentElement", { + /// + get: function () { + return this._dom.content; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SplitView.prototype, "closedDisplayMode", { + /// + /// Gets or sets the display mode of the SplitView's pane when it is hidden. + /// + get: function () { + return this._closedDisplayMode; + }, + set: function (value) { + if (ClosedDisplayMode[value] && this._closedDisplayMode !== value) { + this._closedDisplayMode = value; + this._cachedHiddenPaneThickness = null; + this._machine.updateDom(); + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SplitView.prototype, "openedDisplayMode", { + /// + /// Gets or sets the display mode of the SplitView's pane when it is open. + /// + get: function () { + return this._openedDisplayMode; + }, + set: function (value) { + if (OpenedDisplayMode[value] && this._openedDisplayMode !== value) { + this._openedDisplayMode = value; + this._cachedHiddenPaneThickness = null; + this._machine.updateDom(); + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SplitView.prototype, "panePlacement", { + /// + /// Gets or sets the placement of the SplitView's pane. + /// + get: function () { + return this._panePlacement; + }, + set: function (value) { + if (PanePlacement[value] && this._panePlacement !== value) { + this._panePlacement = value; + this._cachedHiddenPaneThickness = null; + this._machine.updateDom(); + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SplitView.prototype, "paneOpened", { + /// + get: function () { + return this._machine.opened; + }, + set: function (value) { + this._machine.opened = value; + }, + enumerable: true, + configurable: true + }); + SplitView.prototype.dispose = function () { + /// + /// + /// Disposes this control. + /// + /// + if (this._disposed) { + return; + } + this._disposed = true; + this._machine.dispose(); + _LightDismissService.hidden(this._dismissable); + _Dispose._disposeElement(this._dom.pane); + _Dispose._disposeElement(this._dom.content); + }; + SplitView.prototype.openPane = function () { + /// + /// + /// Opens the SplitView's pane. + /// + /// + this._machine.open(); + }; + SplitView.prototype.closePane = function () { + /// + /// + /// Closes the SplitView's pane. + /// + /// + this._machine.close(); + }; + SplitView.prototype._initializeDom = function (root) { + // The first child is the pane + var paneEl = root.firstElementChild || _Global.document.createElement("div"); + _ElementUtilities.addClass(paneEl, ClassNames.pane); + if (!paneEl.hasAttribute("tabIndex")) { + paneEl.tabIndex = -1; + } + // All other children are members of the content + var contentEl = _Global.document.createElement("div"); + _ElementUtilities.addClass(contentEl, ClassNames.content); + var child = paneEl.nextSibling; + while (child) { + var sibling = child.nextSibling; + contentEl.appendChild(child); + child = sibling; + } + // paneWrapper's purpose is to clip the pane during the pane resize animation + var paneWrapperEl = _Global.document.createElement("div"); + paneWrapperEl.className = ClassNames._paneWrapper; + paneWrapperEl.appendChild(paneEl); + var panePlaceholderEl = _Global.document.createElement("div"); + panePlaceholderEl.className = ClassNames._panePlaceholder; + // contentWrapper is an extra element we need to allow heights to be specified as percentages (e.g. height: 100%) + // for elements within the content area. It works around this Chrome bug: + // Issue 428049: 100% height doesn't work on child of a definite-flex-basis flex item (in vertical flex container) + // https://code.google.com/p/chromium/issues/detail?id=428049 + // The workaround is that putting a position: absolute element (_dom.content) within the flex item (_dom.contentWrapper) + // allows percentage heights to work within the absolutely positioned element (_dom.content). + var contentWrapperEl = _Global.document.createElement("div"); + contentWrapperEl.className = ClassNames._contentWrapper; + contentWrapperEl.appendChild(contentEl); + root["winControl"] = this; + _ElementUtilities.addClass(root, ClassNames.splitView); + _ElementUtilities.addClass(root, "win-disposable"); + this._dom = { + root: root, + pane: paneEl, + paneWrapper: paneWrapperEl, + panePlaceholder: panePlaceholderEl, + content: contentEl, + contentWrapper: contentWrapperEl + }; + }; + SplitView.prototype._measureElement = function (element) { + var style = getComputedStyle(element); + var position = _ElementUtilities._getPositionRelativeTo(element, this._dom.root); + var marginLeft = parseInt(style.marginLeft, 10); + var marginTop = parseInt(style.marginTop, 10); + return { + left: position.left - marginLeft, + top: position.top - marginTop, + contentWidth: _ElementUtilities.getContentWidth(element), + contentHeight: _ElementUtilities.getContentHeight(element), + totalWidth: _ElementUtilities.getTotalWidth(element), + totalHeight: _ElementUtilities.getTotalHeight(element) + }; + }; + SplitView.prototype._setContentRect = function (contentRect) { + var contentWrapperStyle = this._dom.contentWrapper.style; + contentWrapperStyle.left = contentRect.left + "px"; + contentWrapperStyle.top = contentRect.top + "px"; + contentWrapperStyle.height = contentRect.contentHeight + "px"; + contentWrapperStyle.width = contentRect.contentWidth + "px"; + }; + // Overridden by tests. + SplitView.prototype._prepareAnimation = function (paneRect, contentRect) { + var paneWrapperStyle = this._dom.paneWrapper.style; + paneWrapperStyle.position = "absolute"; + paneWrapperStyle.left = paneRect.left + "px"; + paneWrapperStyle.top = paneRect.top + "px"; + paneWrapperStyle.height = paneRect.totalHeight + "px"; + paneWrapperStyle.width = paneRect.totalWidth + "px"; + var contentWrapperStyle = this._dom.contentWrapper.style; + contentWrapperStyle.position = "absolute"; + this._setContentRect(contentRect); + }; + // Overridden by tests. + SplitView.prototype._clearAnimation = function () { + var paneWrapperStyle = this._dom.paneWrapper.style; + paneWrapperStyle.position = ""; + paneWrapperStyle.left = ""; + paneWrapperStyle.top = ""; + paneWrapperStyle.height = ""; + paneWrapperStyle.width = ""; + paneWrapperStyle[transformNames.scriptName] = ""; + var contentWrapperStyle = this._dom.contentWrapper.style; + contentWrapperStyle.position = ""; + contentWrapperStyle.left = ""; + contentWrapperStyle.top = ""; + contentWrapperStyle.height = ""; + contentWrapperStyle.width = ""; + contentWrapperStyle[transformNames.scriptName] = ""; + var paneStyle = this._dom.pane.style; + paneStyle.height = ""; + paneStyle.width = ""; + paneStyle[transformNames.scriptName] = ""; + }; + SplitView.prototype._getHiddenContentRect = function (shownContentRect, hiddenPaneThickness, shownPaneThickness) { + if (this.openedDisplayMode === OpenedDisplayMode.overlay) { + return shownContentRect; + } + else { + var placementRight = this._rtl ? PanePlacement.left : PanePlacement.right; + var multiplier = this.panePlacement === placementRight || this.panePlacement === PanePlacement.bottom ? 0 : 1; + var paneDiff = { + content: shownPaneThickness.content - hiddenPaneThickness.content, + total: shownPaneThickness.total - hiddenPaneThickness.total + }; + return this._horizontal ? { + left: shownContentRect.left - multiplier * paneDiff.total, + top: shownContentRect.top, + contentWidth: shownContentRect.contentWidth + paneDiff.content, + contentHeight: shownContentRect.contentHeight, + totalWidth: shownContentRect.totalWidth + paneDiff.total, + totalHeight: shownContentRect.totalHeight + } : { + left: shownContentRect.left, + top: shownContentRect.top - multiplier * paneDiff.total, + contentWidth: shownContentRect.contentWidth, + contentHeight: shownContentRect.contentHeight + paneDiff.content, + totalWidth: shownContentRect.totalWidth, + totalHeight: shownContentRect.totalHeight + paneDiff.total + }; + } + }; + Object.defineProperty(SplitView.prototype, "_horizontal", { + get: function () { + return this.panePlacement === PanePlacement.left || this.panePlacement === PanePlacement.right; + }, + enumerable: true, + configurable: true + }); + SplitView.prototype._getHiddenPaneThickness = function () { + if (this._cachedHiddenPaneThickness === null) { + if (this._closedDisplayMode === ClosedDisplayMode.none) { + this._cachedHiddenPaneThickness = { content: 0, total: 0 }; + } + else { + if (this._isOpenedMode) { + _ElementUtilities.removeClass(this._dom.root, ClassNames.paneOpened); + _ElementUtilities.addClass(this._dom.root, ClassNames.paneClosed); + } + var size = this._measureElement(this._dom.pane); + this._cachedHiddenPaneThickness = rectToThickness(size, this._horizontal ? Dimension.width : Dimension.height); + if (this._isOpenedMode) { + _ElementUtilities.removeClass(this._dom.root, ClassNames.paneClosed); + _ElementUtilities.addClass(this._dom.root, ClassNames.paneOpened); + } + } + } + return this._cachedHiddenPaneThickness; + }; + // Should be called while SplitView is rendered in its opened mode + // Overridden by tests. + SplitView.prototype._playShowAnimation = function (hiddenPaneThickness) { + var _this = this; + var dim = this._horizontal ? Dimension.width : Dimension.height; + var shownPaneRect = this._measureElement(this._dom.pane); + var shownContentRect = this._measureElement(this._dom.content); + var shownPaneThickness = rectToThickness(shownPaneRect, dim); + var hiddenContentRect = this._getHiddenContentRect(shownContentRect, hiddenPaneThickness, shownPaneThickness); + this._prepareAnimation(shownPaneRect, hiddenContentRect); + var playPaneAnimation = function () { + var placementRight = _this._rtl ? PanePlacement.left : PanePlacement.right; + // What percentage of the size change should be skipped? (e.g. let's do the first + // 30% of the size change instantly and then animate the other 70%) + var animationOffsetFactor = 0.3; + var from = hiddenPaneThickness.total + animationOffsetFactor * (shownPaneThickness.total - hiddenPaneThickness.total); + return Animations._resizeTransition(_this._dom.paneWrapper, _this._dom.pane, { + from: from, + to: shownPaneThickness.total, + actualSize: shownPaneThickness.total, + dimension: dim, + anchorTrailingEdge: _this.panePlacement === placementRight || _this.panePlacement === PanePlacement.bottom + }); + }; + var playShowAnimation = function () { + if (_this.openedDisplayMode === OpenedDisplayMode.inline) { + _this._setContentRect(shownContentRect); + } + return playPaneAnimation(); + }; + return playShowAnimation().then(function () { + _this._clearAnimation(); + }); + }; + // Should be called while SplitView is rendered in its opened mode + // Overridden by tests. + SplitView.prototype._playHideAnimation = function (hiddenPaneThickness) { + var _this = this; + var dim = this._horizontal ? Dimension.width : Dimension.height; + var shownPaneRect = this._measureElement(this._dom.pane); + var shownContentRect = this._measureElement(this._dom.content); + var shownPaneThickness = rectToThickness(shownPaneRect, dim); + var hiddenContentRect = this._getHiddenContentRect(shownContentRect, hiddenPaneThickness, shownPaneThickness); + this._prepareAnimation(shownPaneRect, shownContentRect); + var playPaneAnimation = function () { + var placementRight = _this._rtl ? PanePlacement.left : PanePlacement.right; + // What percentage of the size change should be skipped? (e.g. let's do the first + // 30% of the size change instantly and then animate the other 70%) + var animationOffsetFactor = 0.3; + var from = shownPaneThickness.total - animationOffsetFactor * (shownPaneThickness.total - hiddenPaneThickness.total); + return Animations._resizeTransition(_this._dom.paneWrapper, _this._dom.pane, { + from: from, + to: hiddenPaneThickness.total, + actualSize: shownPaneThickness.total, + dimension: dim, + anchorTrailingEdge: _this.panePlacement === placementRight || _this.panePlacement === PanePlacement.bottom + }); + }; + var playHideAnimation = function () { + if (_this.openedDisplayMode === OpenedDisplayMode.inline) { + _this._setContentRect(hiddenContentRect); + } + return playPaneAnimation(); + }; + return playHideAnimation().then(function () { + _this._clearAnimation(); + }); + }; + SplitView.prototype._updateDomImpl = function () { + var rendered = this._updateDomImpl_rendered; + var paneShouldBeFirst = this.panePlacement === PanePlacement.left || this.panePlacement === PanePlacement.top; + if (paneShouldBeFirst !== rendered.paneIsFirst) { + // TODO: restore focus + if (paneShouldBeFirst) { + this._dom.root.appendChild(this._dom.panePlaceholder); + this._dom.root.appendChild(this._dom.paneWrapper); + this._dom.root.appendChild(this._dom.contentWrapper); + } + else { + this._dom.root.appendChild(this._dom.contentWrapper); + this._dom.root.appendChild(this._dom.paneWrapper); + this._dom.root.appendChild(this._dom.panePlaceholder); + } + } + rendered.paneIsFirst = paneShouldBeFirst; + if (rendered.isOpenedMode !== this._isOpenedMode) { + if (this._isOpenedMode) { + _ElementUtilities.removeClass(this._dom.root, ClassNames.paneClosed); + _ElementUtilities.addClass(this._dom.root, ClassNames.paneOpened); + } + else { + _ElementUtilities.removeClass(this._dom.root, ClassNames.paneOpened); + _ElementUtilities.addClass(this._dom.root, ClassNames.paneClosed); + } + } + rendered.isOpenedMode = this._isOpenedMode; + if (rendered.panePlacement !== this.panePlacement) { + removeClass(this._dom.root, panePlacementClassMap[rendered.panePlacement]); + addClass(this._dom.root, panePlacementClassMap[this.panePlacement]); + rendered.panePlacement = this.panePlacement; + } + if (rendered.closedDisplayMode !== this.closedDisplayMode) { + removeClass(this._dom.root, closedDisplayModeClassMap[rendered.closedDisplayMode]); + addClass(this._dom.root, closedDisplayModeClassMap[this.closedDisplayMode]); + rendered.closedDisplayMode = this.closedDisplayMode; + } + if (rendered.openedDisplayMode !== this.openedDisplayMode) { + removeClass(this._dom.root, openedDisplayModeClassMap[rendered.openedDisplayMode]); + addClass(this._dom.root, openedDisplayModeClassMap[this.openedDisplayMode]); + rendered.openedDisplayMode = this.openedDisplayMode; + } + var isOverlayShown = this._isOpenedMode && this.openedDisplayMode === OpenedDisplayMode.overlay; + // panePlaceholder's purpose is to take up the amount of space occupied by the + // hidden pane while the pane is shown in overlay mode. Without this, the content + // would shift as the pane shows and hides in overlay mode. + var width, height; + if (isOverlayShown) { + var hiddenPaneThickness = this._getHiddenPaneThickness(); + if (this._horizontal) { + width = hiddenPaneThickness.total + "px"; + height = ""; + } + else { + width = ""; + height = hiddenPaneThickness.total + "px"; + } + } + else { + width = ""; + height = ""; + } + if (rendered.panePlaceholderWidth !== width || rendered.panePlaceholderHeight !== height) { + var style = this._dom.panePlaceholder.style; + style.width = width; + style.height = height; + rendered.panePlaceholderWidth = width; + rendered.panePlaceholderHeight = height; + } + if (rendered.isOverlayShown !== isOverlayShown) { + if (isOverlayShown) { + _LightDismissService.shown(this._dismissable); + } + else { + _LightDismissService.hidden(this._dismissable); + } + rendered.isOverlayShown = isOverlayShown; + } + }; + /// + /// Display options for a SplitView's pane when it is closed. + /// + SplitView.ClosedDisplayMode = ClosedDisplayMode; + /// + /// Display options for a SplitView's pane when it is open. + /// + SplitView.OpenedDisplayMode = OpenedDisplayMode; + /// + /// Placement options for a SplitView's pane. + /// + SplitView.PanePlacement = PanePlacement; + SplitView.supportedForProcessing = true; + SplitView._ClassNames = ClassNames; + return SplitView; + })(); + exports.SplitView = SplitView; + _Base.Class.mix(SplitView, _Events.createEventProperties(EventNames.beforeOpen, EventNames.afterOpen, EventNames.beforeClose, EventNames.afterClose)); + _Base.Class.mix(SplitView, _Control.DOMEventMixin); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// +define('WinJS/Controls/SplitView',["require", "exports", '../Core/_Base'], function (require, exports, _Base) { + var module = null; + _Base.Namespace.define("WinJS.UI", { + SplitView: { + get: function () { + if (!module) { + require(["./SplitView/_SplitView"], function (m) { + module = m; + }); + } + return module.SplitView; + } + } + }); +}); + + +define('require-style!less/styles-splitviewpanetoggle',[],function(){}); + +define('require-style!less/colors-splitviewpanetoggle',[],function(){}); +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// +define('WinJS/Controls/SplitViewPaneToggle/_SplitViewPaneToggle',["require", "exports", '../../Core/_Base', '../../Utilities/_Control', '../../Utilities/_ElementUtilities', '../../Core/_ErrorFromName', '../../Core/_Events', '../../Core/_Global', '../../Utilities/_KeyboardBehavior', '../../Utilities/_Hoverable'], function (require, exports, _Base, _Control, _ElementUtilities, _ErrorFromName, _Events, _Global, _KeyboardBehavior, _Hoverable) { + _Hoverable.isHoverable; // Force dependency on the hoverable module + require(["require-style!less/styles-splitviewpanetoggle"]); + require(["require-style!less/colors-splitviewpanetoggle"]); + "use strict"; + // This control has 2 modes depending on whether or not the app has provided a SplitView: + // - SplitView not provided + // SplitViewPaneToggle provides button visuals and fires the invoked event. The app + // intends to do everything else: + // - Handle the invoked event + // - Handle the SplitView opening and closing + // - Handle aria-expanded being mutated by UIA (i.e. screen readers) + // - Keep the aria-controls attribute, aria-expanded attribute, and SplitView in sync + // - SplitView is provided via splitView property + // SplitViewPaneToggle keeps the SplitView, the aria-controls attribute, and the + // aria-expands attribute in sync. In this use case, apps typically won't listen + // to the invoked event (but it's still fired). + var ClassNames = { + splitViewPaneToggle: "win-splitviewpanetoggle" + }; + var EventNames = { + // Fires when the user invokes the button with mouse/keyboard/touch. Does not + // fire if the SplitViewPaneToggle's state changes due to UIA (i.e. aria-expanded + // being set) or due to the SplitView pane opening/closing. + invoked: "invoked" + }; + var Strings = { + get duplicateConstruction() { + return "Invalid argument: Controls may only be instantiated one time for each DOM element"; + }, + get badButtonElement() { + return "Invalid argument: The SplitViewPaneToggle's element must be a button element"; + } + }; + // The splitViewElement may not have a winControl associated with it yet in the case + // that the SplitViewPaneToggle was constructed before the SplitView. This may happen + // when WinJS.UI.processAll is used to construct the controls because the order of construction + // depends on the order in which the SplitView and SplitViewPaneToggle appear in the DOM. + function getSplitViewControl(splitViewElement) { + return (splitViewElement && splitViewElement["winControl"]); + } + function getPaneOpened(splitViewElement) { + var splitViewControl = getSplitViewControl(splitViewElement); + return splitViewControl ? splitViewControl.paneOpened : false; + } + /// + /// + /// Displays a button which is used for opening and closing a SplitView's pane. + /// + /// + /// + /// + /// ]]> + /// The SplitViewPaneToggle control itself. + /// + /// + var SplitViewPaneToggle = (function () { + function SplitViewPaneToggle(element, options) { + /// + /// + /// Creates a new SplitViewPaneToggle control. + /// + /// + /// The DOM element that hosts the SplitViewPaneToggle control. + /// + /// + /// An object that contains one or more property/value pairs to apply to the new control. + /// Each property of the options object corresponds to one of the control's properties or events. + /// Event names must begin with "on". For example, to provide a handler for the invoked event, + /// add a property named "oninvoked" to the options object and set its value to the event handler. + /// + /// + /// The new SplitViewPaneToggle. + /// + /// + if (options === void 0) { options = {}; } + // State private to _updateDom. No other method should make use of it. + // + // Nothing has been rendered yet so these are all initialized to undefined. Because + // they are undefined, the first time _updateDom is called, they will all be + // rendered. + this._updateDom_rendered = { + splitView: undefined + }; + // Check to make sure we weren't duplicated + if (element && element["winControl"]) { + throw new _ErrorFromName("WinJS.UI.SplitViewPaneToggle.DuplicateConstruction", Strings.duplicateConstruction); + } + this._onPaneStateSettledBound = this._onPaneStateSettled.bind(this); + this._ariaExpandedMutationObserver = new _ElementUtilities._MutationObserver(this._onAriaExpandedPropertyChanged.bind(this)); + this._initializeDom(element || _Global.document.createElement("button")); + // Private state + this._disposed = false; + // Default values + this.splitView = null; + _Control.setOptions(this, options); + this._initialized = true; + this._updateDom(); + } + Object.defineProperty(SplitViewPaneToggle.prototype, "element", { + /// + get: function () { + return this._dom.root; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SplitViewPaneToggle.prototype, "splitView", { + /// + get: function () { + return this._splitView; + }, + set: function (splitView) { + this._splitView = splitView; + if (splitView) { + this._opened = getPaneOpened(splitView); + } + this._updateDom(); + }, + enumerable: true, + configurable: true + }); + SplitViewPaneToggle.prototype.dispose = function () { + /// + /// + /// Disposes this control. + /// + /// + if (this._disposed) { + return; + } + this._disposed = true; + this._splitView && this._removeListeners(this._splitView); + }; + SplitViewPaneToggle.prototype._initializeDom = function (root) { + if (root.tagName !== "BUTTON") { + throw new _ErrorFromName("WinJS.UI.SplitViewPaneToggle.BadButtonElement", Strings.badButtonElement); + } + root["winControl"] = this; + _ElementUtilities.addClass(root, ClassNames.splitViewPaneToggle); + _ElementUtilities.addClass(root, "win-disposable"); + if (!root.hasAttribute("type")) { + root.type = "button"; + } + new _KeyboardBehavior._WinKeyboard(root); + root.addEventListener("click", this._onClick.bind(this)); + this._dom = { + root: root + }; + }; + SplitViewPaneToggle.prototype._updateDom = function () { + if (!this._initialized || this._disposed) { + return; + } + var rendered = this._updateDom_rendered; + if (this._splitView !== rendered.splitView) { + if (rendered.splitView) { + this._dom.root.removeAttribute("aria-controls"); + this._removeListeners(rendered.splitView); + } + if (this._splitView) { + _ElementUtilities._ensureId(this._splitView); + this._dom.root.setAttribute("aria-controls", this._splitView.id); + this._addListeners(this._splitView); + } + rendered.splitView = this._splitView; + } + // When no SplitView is provided, it's up to the app to manage aria-expanded. + if (this._splitView) { + // Always update aria-expanded and don't cache its most recently rendered value + // in _updateDom_rendered. The reason is that we're not the only ones that update + // aria-expanded. aria-expanded may be changed thru UIA APIs. Consequently, if we + // cached the last value we set in _updateDom_rendered, it may not reflect the current + // value in the DOM. + var expanded = this._opened ? "true" : "false"; + _ElementUtilities._setAttribute(this._dom.root, "aria-expanded", expanded); + // The splitView element may not have a winControl associated with it yet in the case + // that the SplitViewPaneToggle was constructed before the SplitView. This may happen + // when WinJS.UI.processAll is used to construct the controls because the order of construction + // depends on the order in which the SplitView and SplitViewPaneToggle appear in the DOM. + var splitViewControl = getSplitViewControl(this._splitView); + if (splitViewControl) { + splitViewControl.paneOpened = this._opened; + } + } + }; + SplitViewPaneToggle.prototype._addListeners = function (splitViewElement) { + splitViewElement.addEventListener("_openCloseStateSettled", this._onPaneStateSettledBound); + this._ariaExpandedMutationObserver.observe(this._dom.root, { + attributes: true, + attributeFilter: ["aria-expanded"] + }); + }; + SplitViewPaneToggle.prototype._removeListeners = function (splitViewElement) { + splitViewElement.removeEventListener("_openCloseStateSettled", this._onPaneStateSettledBound); + this._ariaExpandedMutationObserver.disconnect(); + }; + SplitViewPaneToggle.prototype._fireEvent = function (eventName) { + var eventObject = _Global.document.createEvent("CustomEvent"); + eventObject.initCustomEvent(eventName, true, false, null); + return this._dom.root.dispatchEvent(eventObject); + }; + // Inputs that change the SplitViewPaneToggle's state + // + SplitViewPaneToggle.prototype._onPaneStateSettled = function (eventObject) { + if (eventObject.target === this._splitView) { + this._opened = getPaneOpened(this._splitView); + this._updateDom(); + } + }; + // Called by tests. + SplitViewPaneToggle.prototype._onAriaExpandedPropertyChanged = function (mutations) { + var ariaExpanded = this._dom.root.getAttribute("aria-expanded") === "true"; + this._opened = ariaExpanded; + this._updateDom(); + }; + SplitViewPaneToggle.prototype._onClick = function (eventObject) { + this._invoked(); + }; + // Called by tests. + SplitViewPaneToggle.prototype._invoked = function () { + if (this._disposed) { + return; + } + if (this._splitView) { + this._opened = !this._opened; + this._updateDom(); + } + this._fireEvent(EventNames.invoked); + }; + SplitViewPaneToggle._ClassNames = ClassNames; + SplitViewPaneToggle.supportedForProcessing = true; + return SplitViewPaneToggle; + })(); + exports.SplitViewPaneToggle = SplitViewPaneToggle; + _Base.Class.mix(SplitViewPaneToggle, _Events.createEventProperties(EventNames.invoked)); + _Base.Class.mix(SplitViewPaneToggle, _Control.DOMEventMixin); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// +define('WinJS/Controls/SplitViewPaneToggle',["require", "exports", '../Core/_Base'], function (require, exports, _Base) { + var module = null; + _Base.Namespace.define("WinJS.UI", { + SplitViewPaneToggle: { + get: function () { + if (!module) { + require(["./SplitViewPaneToggle/_SplitViewPaneToggle"], function (m) { + module = m; + }); + } + return module.SplitViewPaneToggle; + } + } + }); +}); + +define('WinJS/Controls/AppBar/_Constants',["require", "exports", "../CommandingSurface/_Constants"], function (require, exports, _CommandingSurfaceConstants) { + // appbar class names + exports.ClassNames = { + controlCssClass: "win-appbar", + disposableCssClass: "win-disposable", + actionAreaCssClass: "win-appbar-actionarea", + overflowButtonCssClass: "win-appbar-overflowbutton", + spacerCssClass: "win-appbar-spacer", + ellipsisCssClass: "win-appbar-ellipsis", + overflowAreaCssClass: "win-appbar-overflowarea", + contentFlyoutCssClass: "win-appbar-contentflyout", + emptyappbarCssClass: "win-appbar-empty", + menuCssClass: "win-menu", + menuContainsToggleCommandClass: "win-menu-containstogglecommand", + openedClass: "win-appbar-opened", + closedClass: "win-appbar-closed", + noneClass: "win-appbar-closeddisplaynone", + minimalClass: "win-appbar-closeddisplayminimal", + compactClass: "win-appbar-closeddisplaycompact", + fullClass: "win-appbar-closeddisplayfull", + placementTopClass: "win-appbar-top", + placementBottomClass: "win-appbar-bottom", + }; + exports.EventNames = { + // AppBar + beforeOpen: "beforeopen", + afterOpen: "afteropen", + beforeClose: "beforeclose", + afterClose: "afterclose", + // AppBarCommand + commandPropertyMutated: "_commandpropertymutated", + }; + exports.controlMinWidth = _CommandingSurfaceConstants.controlMinWidth; + exports.defaultClosedDisplayMode = "compact"; + exports.defaultOpened = false; + exports.defaultPlacement = "bottom"; + // Constants for commands + exports.typeSeparator = "separator"; + exports.typeContent = "content"; + exports.typeButton = "button"; + exports.typeToggle = "toggle"; + exports.typeFlyout = "flyout"; + exports.commandSelector = ".win-command"; + exports.primaryCommandSection = "primary"; + exports.secondaryCommandSection = "secondary"; +}); + + +define('require-style!less/styles-appbar',[],function(){}); +define('WinJS/Controls/AppBar/_AppBar',["require", "exports", "../../Core/_Base", "../AppBar/_Constants", "../CommandingSurface", "../../Utilities/_Control", "../../Utilities/_Dispose", "../../Utilities/_ElementUtilities", "../../Core/_ErrorFromName", '../../Core/_Events', "../../Core/_Global", '../../Utilities/_KeyboardInfo', '../../_LightDismissService', '../../Promise', "../../Core/_Resources", '../../Utilities/_OpenCloseMachine', "../../Core/_WriteProfilerMark"], function (require, exports, _Base, _Constants, _CommandingSurface, _Control, _Dispose, _ElementUtilities, _ErrorFromName, _Events, _Global, _KeyboardInfo, _LightDismissService, Promise, _Resources, _OpenCloseMachine, _WriteProfilerMark) { + require(["require-style!less/styles-appbar"]); + "use strict"; + var keyboardInfo = _KeyboardInfo._KeyboardInfo; + var strings = { + get ariaLabel() { + return _Resources._getWinJSString("ui/appBarAriaLabel").value; + }, + get overflowButtonAriaLabel() { + return _Resources._getWinJSString("ui/appBarOverflowButtonAriaLabel").value; + }, + get mustContainCommands() { + return "The AppBar can only contain WinJS.UI.Command or WinJS.UI.AppBarCommand controls"; + }, + get duplicateConstruction() { + return "Invalid argument: Controls may only be instantiated one time for each DOM element"; + } + }; + var ClosedDisplayMode = { + /// + /// When the AppBar is closed, it is not visible and doesn't take up any space. + /// + none: "none", + /// + /// When the AppBar is closed, its height is reduced to the minimal height required to display only its overflowbutton. All other content in the AppBar is not displayed. + /// + minimal: "minimal", + /// + /// When the AppBar is closed, its height is reduced such that button commands are still visible, but their labels are hidden. + /// + compact: "compact", + /// + /// When the AppBar is closed, its height is always sized to content. + /// + full: "full", + }; + var closedDisplayModeClassMap = {}; + closedDisplayModeClassMap[ClosedDisplayMode.none] = _Constants.ClassNames.noneClass; + closedDisplayModeClassMap[ClosedDisplayMode.minimal] = _Constants.ClassNames.minimalClass; + closedDisplayModeClassMap[ClosedDisplayMode.compact] = _Constants.ClassNames.compactClass; + closedDisplayModeClassMap[ClosedDisplayMode.full] = _Constants.ClassNames.fullClass; + var Placement = { + /// + /// The AppBar appears at the top of the main view + /// + top: "top", + /// + /// The AppBar appears at the bottom of the main view + /// + bottom: "bottom", + }; + var placementClassMap = {}; + placementClassMap[Placement.top] = _Constants.ClassNames.placementTopClass; + placementClassMap[Placement.bottom] = _Constants.ClassNames.placementBottomClass; + // Versions of add/removeClass that are no ops when called with falsy class names. + function addClass(element, className) { + className && _ElementUtilities.addClass(element, className); + } + function removeClass(element, className) { + className && _ElementUtilities.removeClass(element, className); + } + /// + /// + /// Represents an appbar for displaying commands. + /// + /// + /// + /// + /// + /// + /// ]]> + /// The entire AppBar control. + /// The appbar overflow button. + /// The container for appbar commands that overflow. + /// + /// + var AppBar = (function () { + function AppBar(element, options) { + /// + /// + /// Creates a new AppBar control. + /// + /// + /// The DOM element that will host the control. + /// + /// + /// The set of properties and values to apply to the new AppBar control. + /// + /// + /// The new AppBar control. + /// + /// + var _this = this; + if (options === void 0) { options = {}; } + // State private to the _updateDomImpl family of method. No other methods should make use of it. + // + // Nothing has been rendered yet so these are all initialized to undefined. Because + // they are undefined, the first time _updateDomImpl is called, they will all be + // rendered. + this._updateDomImpl_renderedState = { + isOpenedMode: undefined, + placement: undefined, + closedDisplayMode: undefined, + adjustedOffsets: { top: undefined, bottom: undefined }, + }; + this._writeProfilerMark("constructor,StartTM"); + // Check to make sure we weren't duplicated + if (element && element["winControl"]) { + throw new _ErrorFromName("WinJS.UI.AppBar.DuplicateConstruction", strings.duplicateConstruction); + } + this._initializeDom(element || _Global.document.createElement("div")); + var stateMachine = new _OpenCloseMachine.OpenCloseMachine({ + eventElement: this.element, + onOpen: function () { + var openAnimation = _this._commandingSurface.createOpenAnimation(_this._getClosedHeight()); + // We're temporarily setting the AppBar's style from position=-ms-device-fixed to fixed to work around an animations bug in IE, + // where two AppBars will end up being rendered when animating instead of one. + // We need to recalculate our offsets relative to the top and bottom of the visible document because position fixed elements use layout viewport coordinates + // while position -ms-device-fixed use visual viewport coordinates.This difference in coordinate systems is especially pronounced if the IHM has caused the visual viewport to resize. + _this.element.style.position = "fixed"; + if (_this._placement === AppBar.Placement.top) { + _this.element.style.top = _KeyboardInfo._KeyboardInfo._layoutViewportCoords.visibleDocTop + "px"; + } + else { + _this.element.style.bottom = _KeyboardInfo._KeyboardInfo._layoutViewportCoords.visibleDocBottom + "px"; + } + _this._synchronousOpen(); + return openAnimation.execute().then(function () { + _this.element.style.position = ""; + _this.element.style.top = _this._adjustedOffsets.top; + _this.element.style.bottom = _this._adjustedOffsets.bottom; + }); + }, + onClose: function () { + var closeAnimation = _this._commandingSurface.createCloseAnimation(_this._getClosedHeight()); + // We're temporarily setting the AppBar's style from position=-ms-device-fixed to fixed to work around an animations bug in IE, + // where two AppBars will end up being rendered when animating instead of one. + // We need to recalculate our offsets relative to the top and bottom of the visible document because position fixed elements use layout viewport coordinates + // while position -ms-device-fixed use visual viewport coordinates.This difference in coordinate systems is especially pronounced if the IHM has caused the visual viewport to resize. + _this.element.style.position = "fixed"; + if (_this._placement === AppBar.Placement.top) { + _this.element.style.top = _KeyboardInfo._KeyboardInfo._layoutViewportCoords.visibleDocTop + "px"; + } + else { + _this.element.style.bottom = _KeyboardInfo._KeyboardInfo._layoutViewportCoords.visibleDocBottom + "px"; + } + return closeAnimation.execute().then(function () { + _this._synchronousClose(); + _this.element.style.position = ""; + _this.element.style.top = _this._adjustedOffsets.top; + _this.element.style.bottom = _this._adjustedOffsets.bottom; + }); + }, + onUpdateDom: function () { + _this._updateDomImpl(); + }, + onUpdateDomWithIsOpened: function (isOpened) { + _this._isOpenedMode = isOpened; + _this._updateDomImpl(); + } + }); + // Events + this._handleShowingKeyboardBound = this._handleShowingKeyboard.bind(this); + this._handleHidingKeyboardBound = this._handleHidingKeyboard.bind(this); + _ElementUtilities._inputPaneListener.addEventListener(this._dom.root, "showing", this._handleShowingKeyboardBound); + _ElementUtilities._inputPaneListener.addEventListener(this._dom.root, "hiding", this._handleHidingKeyboardBound); + // Initialize private state. + this._disposed = false; + this._cachedClosedHeight = null; + this._commandingSurface = new _CommandingSurface._CommandingSurface(this._dom.commandingSurfaceEl, { openCloseMachine: stateMachine }); + addClass(this._dom.commandingSurfaceEl.querySelector(".win-commandingsurface-actionarea"), _Constants.ClassNames.actionAreaCssClass); + addClass(this._dom.commandingSurfaceEl.querySelector(".win-commandingsurface-overflowarea"), _Constants.ClassNames.overflowAreaCssClass); + addClass(this._dom.commandingSurfaceEl.querySelector(".win-commandingsurface-overflowbutton"), _Constants.ClassNames.overflowButtonCssClass); + addClass(this._dom.commandingSurfaceEl.querySelector(".win-commandingsurface-ellipsis"), _Constants.ClassNames.ellipsisCssClass); + this._isOpenedMode = _Constants.defaultOpened; + this._dismissable = new _LightDismissService.LightDismissableElement({ + element: this._dom.root, + tabIndex: this._dom.root.hasAttribute("tabIndex") ? this._dom.root.tabIndex : -1, + onLightDismiss: function () { + _this.close(); + } + }); + // Initialize public properties. + this.closedDisplayMode = _Constants.defaultClosedDisplayMode; + this.placement = _Constants.defaultPlacement; + this.opened = this._isOpenedMode; + _Control.setOptions(this, options); + // Exit the Init state. + _ElementUtilities._inDom(this.element).then(function () { + return _this._commandingSurface.initialized; + }).then(function () { + stateMachine.exitInit(); + _this._writeProfilerMark("constructor,StopTM"); + }); + } + Object.defineProperty(AppBar.prototype, "element", { + /// + get: function () { + return this._dom.root; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(AppBar.prototype, "data", { + /// + /// Gets or sets the Binding List of WinJS.UI.Command for the AppBar. + /// + get: function () { + return this._commandingSurface.data; + }, + set: function (value) { + this._commandingSurface.data = value; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(AppBar.prototype, "closedDisplayMode", { + /// + /// Gets or sets the closedDisplayMode for the AppBar. Values are "none", "minimal", "compact" and "full". + /// + get: function () { + return this._commandingSurface.closedDisplayMode; + }, + set: function (value) { + if (ClosedDisplayMode[value]) { + this._commandingSurface.closedDisplayMode = value; + this._cachedClosedHeight = null; + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(AppBar.prototype, "placement", { + /// + get: function () { + return this._placement; + }, + set: function (value) { + if (Placement[value] && this._placement !== value) { + this._placement = value; + switch (value) { + case Placement.top: + this._commandingSurface.overflowDirection = "bottom"; + break; + case Placement.bottom: + this._commandingSurface.overflowDirection = "top"; + break; + } + this._adjustedOffsets = this._computeAdjustedOffsets(); + this._commandingSurface.deferredDomUpate(); + } + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(AppBar.prototype, "opened", { + /// + get: function () { + return this._commandingSurface.opened; + }, + set: function (value) { + this._commandingSurface.opened = value; + }, + enumerable: true, + configurable: true + }); + AppBar.prototype.open = function () { + /// + /// + /// Opens the AppBar + /// + /// + this._commandingSurface.open(); + }; + AppBar.prototype.close = function () { + /// + /// + /// Closes the AppBar + /// + /// + this._commandingSurface.close(); + }; + AppBar.prototype.dispose = function () { + /// + /// + /// Disposes this AppBar. + /// + /// + if (this._disposed) { + return; + } + this._disposed = true; + _LightDismissService.hidden(this._dismissable); + // Disposing the _commandingSurface will trigger dispose on its OpenCloseMachine + // and synchronously complete any animations that might have been running. + this._commandingSurface.dispose(); + _ElementUtilities._inputPaneListener.removeEventListener(this._dom.root, "showing", this._handleShowingKeyboardBound); + _ElementUtilities._inputPaneListener.removeEventListener(this._dom.root, "hiding", this._handleHidingKeyboardBound); + _Dispose.disposeSubTree(this.element); + }; + AppBar.prototype.forceLayout = function () { + /// + /// + /// Forces the AppBar to update its layout. Use this function when the window did not change size, but the container of the AppBar changed size. + /// + /// + this._commandingSurface.forceLayout(); + }; + AppBar.prototype.getCommandById = function (id) { + /// + /// + /// Retrieves the command with the specified ID from this AppBar. + /// If more than one command is found, this method returns the first command found. + /// + /// Id of the command to return. + /// + /// The command found, or null if no command is found. + /// + /// + return this._commandingSurface.getCommandById(id); + }; + AppBar.prototype.showOnlyCommands = function (commands) { + /// + /// + /// Show the specified commands, hiding all of the others in the AppBar. + /// + /// + /// An array of the commands to show. The array elements may be Command objects, or the string identifiers (IDs) of commands. + /// + /// + return this._commandingSurface.showOnlyCommands(commands); + }; + AppBar.prototype._writeProfilerMark = function (text) { + _WriteProfilerMark("WinJS.UI.AppBar:" + this._id + ":" + text); + }; + AppBar.prototype._initializeDom = function (root) { + this._writeProfilerMark("_intializeDom,info"); + // Attaching JS control to DOM element + root["winControl"] = this; + this._id = root.id || _ElementUtilities._uniqueID(root); + _ElementUtilities.addClass(root, _Constants.ClassNames.controlCssClass); + _ElementUtilities.addClass(root, _Constants.ClassNames.disposableCssClass); + // Make sure we have an ARIA role + var role = root.getAttribute("role"); + if (!role) { + root.setAttribute("role", "menubar"); + } + var label = root.getAttribute("aria-label"); + if (!label) { + root.setAttribute("aria-label", strings.ariaLabel); + } + // Create element for commandingSurface and reparent any declarative Commands. + // commandingSurface will parse child elements as AppBarCommands. + var commandingSurfaceEl = document.createElement("DIV"); + _ElementUtilities._reparentChildren(root, commandingSurfaceEl); + root.appendChild(commandingSurfaceEl); + this._dom = { + root: root, + commandingSurfaceEl: commandingSurfaceEl, + }; + }; + AppBar.prototype._handleShowingKeyboard = function (event) { + // If the IHM resized the window, we can rely on -ms-device-fixed positioning to remain visible. + // If the IHM does not resize the window we will need to adjust our offsets to avoid being occluded + // The IHM does not cause a window resize to happen right away, set a timeout to check if the viewport + // has been resized after enough time has passed for both the IHM animation, and scroll-into-view, to + // complete. + var _this = this; + // If focus is in the AppBar, tell the platform we will move ourselves. + if (this._dom.root.contains(_Global.document.activeElement)) { + var inputPaneEvent = event.detail.originalEvent; + inputPaneEvent.ensuredFocusedElementInView = true; + } + var duration = keyboardInfo._animationShowLength + keyboardInfo._scrollTimeout; + // Returns a promise for unit tests to verify the correct behavior after the timeout. + return Promise.timeout(duration).then(function () { + if (_this._shouldAdjustForShowingKeyboard() && !_this._disposed) { + _this._adjustedOffsets = _this._computeAdjustedOffsets(); + _this._commandingSurface.deferredDomUpate(); + } + }); + }; + AppBar.prototype._shouldAdjustForShowingKeyboard = function () { + // Overwriteable for unit tests + // Determines if an AppBar needs to adjust its position to move in response to a shown IHM, or if it can + // just ride the bottom of the visual viewport to remain visible. The latter requires that the IHM has + // caused the viewport to resize. + return keyboardInfo._visible && !keyboardInfo._isResized; + }; + AppBar.prototype._handleHidingKeyboard = function () { + // Make sure AppBar has the correct offsets since it could have been displaced by the IHM. + this._adjustedOffsets = this._computeAdjustedOffsets(); + this._commandingSurface.deferredDomUpate(); + }; + AppBar.prototype._computeAdjustedOffsets = function () { + // Position the AppBar element relative to the top or bottom edge of the visible + // document. + var offsets = { top: "", bottom: "" }; + if (this._placement === Placement.bottom) { + // If the IHM is open, the bottom of the visual viewport may or may not be occluded + offsets.bottom = keyboardInfo._visibleDocBottomOffset + "px"; + } + else if (this._placement === Placement.top) { + offsets.top = keyboardInfo._visibleDocTop + "px"; + } + return offsets; + }; + AppBar.prototype._synchronousOpen = function () { + this._isOpenedMode = true; + this._updateDomImpl(); + }; + AppBar.prototype._synchronousClose = function () { + this._isOpenedMode = false; + this._updateDomImpl(); + }; + AppBar.prototype._updateDomImpl = function () { + var rendered = this._updateDomImpl_renderedState; + if (rendered.isOpenedMode !== this._isOpenedMode) { + if (this._isOpenedMode) { + this._updateDomImpl_renderOpened(); + } + else { + this._updateDomImpl_renderClosed(); + } + rendered.isOpenedMode = this._isOpenedMode; + } + if (rendered.placement !== this.placement) { + removeClass(this._dom.root, placementClassMap[rendered.placement]); + addClass(this._dom.root, placementClassMap[this.placement]); + rendered.placement = this.placement; + } + if (rendered.closedDisplayMode !== this.closedDisplayMode) { + removeClass(this._dom.root, closedDisplayModeClassMap[rendered.closedDisplayMode]); + addClass(this._dom.root, closedDisplayModeClassMap[this.closedDisplayMode]); + rendered.closedDisplayMode = this.closedDisplayMode; + } + if (rendered.adjustedOffsets.top !== this._adjustedOffsets.top) { + this._dom.root.style.top = this._adjustedOffsets.top; + rendered.adjustedOffsets.top = this._adjustedOffsets.top; + } + if (rendered.adjustedOffsets.bottom !== this._adjustedOffsets.bottom) { + this._dom.root.style.bottom = this._adjustedOffsets.bottom; + rendered.adjustedOffsets.bottom = this._adjustedOffsets.bottom; + } + this._commandingSurface.updateDomImpl(); + }; + AppBar.prototype._getClosedHeight = function () { + if (this._cachedClosedHeight === null) { + var wasOpen = this._isOpenedMode; + if (this._isOpenedMode) { + this._synchronousClose(); + } + this._cachedClosedHeight = this._commandingSurface.getBoundingRects().commandingSurface.height; + if (wasOpen) { + this._synchronousOpen(); + } + } + return this._cachedClosedHeight; + }; + AppBar.prototype._updateDomImpl_renderOpened = function () { + addClass(this._dom.root, _Constants.ClassNames.openedClass); + removeClass(this._dom.root, _Constants.ClassNames.closedClass); + this._commandingSurface.synchronousOpen(); + _LightDismissService.shown(this._dismissable); // Call at the start of the open animation + }; + AppBar.prototype._updateDomImpl_renderClosed = function () { + addClass(this._dom.root, _Constants.ClassNames.closedClass); + removeClass(this._dom.root, _Constants.ClassNames.openedClass); + this._commandingSurface.synchronousClose(); + _LightDismissService.hidden(this._dismissable); // Call after the close animation + }; + /// + /// Display options for the AppBar when closed. + /// + AppBar.ClosedDisplayMode = ClosedDisplayMode; + /// + /// Display options for AppBar placement in relation to the main view. + /// + AppBar.Placement = Placement; + AppBar.supportedForProcessing = true; + return AppBar; + })(); + exports.AppBar = AppBar; + _Base.Class.mix(AppBar, _Events.createEventProperties(_Constants.EventNames.beforeOpen, _Constants.EventNames.afterOpen, _Constants.EventNames.beforeClose, _Constants.EventNames.afterClose)); + // addEventListener, removeEventListener, dispatchEvent + _Base.Class.mix(AppBar, _Control.DOMEventMixin); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +/// +define('WinJS/Controls/AppBar',["require", "exports", '../Core/_Base'], function (require, exports, _Base) { + var module = null; + _Base.Namespace.define("WinJS.UI", { + AppBar: { + get: function () { + if (!module) { + require(["./AppBar/_AppBar"], function (m) { + module = m; + }); + } + return module.AppBar; + } + } + }); +}); + +// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. +define('ui',[ + 'WinJS/Core/_WinJS', + 'WinJS/VirtualizedDataSource', + 'WinJS/Controls/IntrinsicControls', + 'WinJS/Controls/ListView', + 'WinJS/Controls/FlipView', + 'WinJS/Controls/ItemContainer', + 'WinJS/Controls/Repeater', + 'WinJS/Controls/DatePicker', + 'WinJS/Controls/TimePicker', + 'WinJS/Controls/BackButton', + 'WinJS/Controls/Rating', + 'WinJS/Controls/ToggleSwitch', + 'WinJS/Controls/SemanticZoom', + 'WinJS/Controls/Pivot', + 'WinJS/Controls/Hub', + 'WinJS/Controls/Flyout', + 'WinJS/Controls/_LegacyAppBar', + 'WinJS/Controls/Menu', + 'WinJS/Controls/SearchBox', + 'WinJS/Controls/SettingsFlyout', + 'WinJS/Controls/NavBar', + 'WinJS/Controls/Tooltip', + 'WinJS/Controls/ViewBox', + 'WinJS/Controls/ContentDialog', + 'WinJS/Controls/SplitView', + 'WinJS/Controls/SplitViewPaneToggle', + 'WinJS/Controls/ToolBar', + 'WinJS/Controls/AppBar', + ], function (_WinJS) { + "use strict"; + + return _WinJS; +}); + + require(['WinJS/Core/_WinJS', 'ui'], function (_WinJS) { + // WinJS always publishes itself to global + globalObject.WinJS = _WinJS; + if (typeof module !== 'undefined') { + // This is a CommonJS context so publish to exports + module.exports = _WinJS; + } + }); + return globalObject.WinJS; + })); +}()); + diff --git a/UnitsNet.TestApps.Uwp.WinJS/package.appxmanifest b/UnitsNet.TestApps.Uwp.WinJS/package.appxmanifest new file mode 100644 index 0000000000..8243891ea8 --- /dev/null +++ b/UnitsNet.TestApps.Uwp.WinJS/package.appxmanifest @@ -0,0 +1,52 @@ + + + + + + + + + UnitsNet.TestApps.Uwp.WinJS + Andreas + images\storelogo.png + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/UnitsNet.TestApps.Uwp.WinJS/project.json b/UnitsNet.TestApps.Uwp.WinJS/project.json new file mode 100644 index 0000000000..be4e8d0829 --- /dev/null +++ b/UnitsNet.TestApps.Uwp.WinJS/project.json @@ -0,0 +1,17 @@ +{ + "dependencies": { + "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0", + "UnitsNet.WindowsRuntimeComponent": "3.30.0-alpha7" + }, + "frameworks": { + "uap10.0": {} + }, + "runtimes": { + "win10-arm": {}, + "win10-arm-aot": {}, + "win10-x86": {}, + "win10-x86-aot": {}, + "win10-x64": {}, + "win10-x64-aot": {} + } +} \ No newline at end of file From c72fd9bb3cfaf1c17dfc0046fa4fbe9797b98d93 Mon Sep 17 00:00:00 2001 From: Andreas Gullberg Larsen Date: Sat, 9 Apr 2016 23:12:25 +0200 Subject: [PATCH 13/17] Add solution file for Unitsnet.WindowsRuntimeComponent --- UnitsNet.WindowsRuntimeComponent.sln | 124 ++++++++++++++++++ ...et.WindowsRuntimeComponent.sln.DotSettings | 26 ++++ .../AssemblyInfo.WindowsRuntimeComponent.cs | 59 +++++++++ 3 files changed, 209 insertions(+) create mode 100644 UnitsNet.WindowsRuntimeComponent.sln create mode 100644 UnitsNet.WindowsRuntimeComponent.sln.DotSettings create mode 100644 UnitsNet/Properties/AssemblyInfo.WindowsRuntimeComponent.cs diff --git a/UnitsNet.WindowsRuntimeComponent.sln b/UnitsNet.WindowsRuntimeComponent.sln new file mode 100644 index 0000000000..08168a11bd --- /dev/null +++ b/UnitsNet.WindowsRuntimeComponent.sln @@ -0,0 +1,124 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25123.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{9BEB42C6-EC3A-49B8-A065-0D01DDFF16B2}" + ProjectSection(SolutionItems) = preProject + Build\UnitsNet.nuspec = Build\UnitsNet.nuspec + Build\UnitsNet.Serialization.JsonNet.nuspec = Build\UnitsNet.Serialization.JsonNet.nuspec + Build\UnitsNet.WindowsRuntimeComponent.nuspec = Build\UnitsNet.WindowsRuntimeComponent.nuspec + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitsNet.TestApps.Uwp.Csharp", "UnitsNet.TestApps.Uwp.Csharp\UnitsNet.TestApps.Uwp.Csharp.csproj", "{76255CC9-A854-441F-AF5C-2606509D3C5E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitsNet.WindowsRuntimeComponent", "UnitsNet\UnitsNet.WindowsRuntimeComponent.csproj", "{2DA428CA-BFE1-43FA-86D2-7CB42289D596}" +EndProject +Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "UnitsNet.TestApps.Uwp.JavaScript", "UnitsNet.TestApps.Uwp.JavaScript\UnitsNet.TestApps.Uwp.JavaScript.jsproj", "{FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}" +EndProject +Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "UnitsNet.TestApps.Uwp.WinJS", "UnitsNet.TestApps.Uwp.WinJS\UnitsNet.TestApps.Uwp.WinJS.jsproj", "{B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|ARM = Debug|ARM + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|ARM = Release|ARM + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Debug|Any CPU.ActiveCfg = Debug|x86 + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Debug|Any CPU.Build.0 = Debug|x86 + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Debug|Any CPU.Deploy.0 = Debug|x86 + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Debug|ARM.ActiveCfg = Debug|ARM + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Debug|ARM.Build.0 = Debug|ARM + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Debug|ARM.Deploy.0 = Debug|ARM + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Debug|x64.ActiveCfg = Debug|x64 + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Debug|x64.Build.0 = Debug|x64 + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Debug|x64.Deploy.0 = Debug|x64 + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Debug|x86.ActiveCfg = Debug|x86 + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Debug|x86.Build.0 = Debug|x86 + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Debug|x86.Deploy.0 = Debug|x86 + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Release|Any CPU.ActiveCfg = Release|x86 + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Release|Any CPU.Build.0 = Release|x86 + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Release|Any CPU.Deploy.0 = Release|x86 + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Release|ARM.ActiveCfg = Release|ARM + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Release|ARM.Build.0 = Release|ARM + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Release|ARM.Deploy.0 = Release|ARM + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Release|x64.ActiveCfg = Release|x64 + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Release|x64.Build.0 = Release|x64 + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Release|x64.Deploy.0 = Release|x64 + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Release|x86.ActiveCfg = Release|x86 + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Release|x86.Build.0 = Release|x86 + {76255CC9-A854-441F-AF5C-2606509D3C5E}.Release|x86.Deploy.0 = Release|x86 + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|ARM.ActiveCfg = Debug|ARM + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|ARM.Build.0 = Debug|ARM + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|x64.ActiveCfg = Debug|x64 + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|x64.Build.0 = Debug|x64 + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|x86.ActiveCfg = Debug|x86 + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|x86.Build.0 = Debug|x86 + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|Any CPU.Build.0 = Release|Any CPU + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|ARM.ActiveCfg = Release|ARM + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|ARM.Build.0 = Release|ARM + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|x64.ActiveCfg = Release|x64 + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|x64.Build.0 = Release|x64 + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|x86.ActiveCfg = Release|x86 + {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|x86.Build.0 = Release|x86 + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Debug|ARM.ActiveCfg = Debug|ARM + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Debug|ARM.Build.0 = Debug|ARM + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Debug|ARM.Deploy.0 = Debug|ARM + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Debug|x64.ActiveCfg = Debug|x64 + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Debug|x64.Build.0 = Debug|x64 + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Debug|x64.Deploy.0 = Debug|x64 + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Debug|x86.ActiveCfg = Debug|x86 + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Debug|x86.Build.0 = Debug|x86 + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Debug|x86.Deploy.0 = Debug|x86 + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Release|Any CPU.Build.0 = Release|Any CPU + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Release|Any CPU.Deploy.0 = Release|Any CPU + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Release|ARM.ActiveCfg = Release|ARM + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Release|ARM.Build.0 = Release|ARM + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Release|ARM.Deploy.0 = Release|ARM + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Release|x64.ActiveCfg = Release|x64 + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Release|x64.Build.0 = Release|x64 + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Release|x64.Deploy.0 = Release|x64 + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Release|x86.ActiveCfg = Release|x86 + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Release|x86.Build.0 = Release|x86 + {FCE9C341-D288-4517-9D2D-5C4BDF5D8F20}.Release|x86.Deploy.0 = Release|x86 + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Debug|ARM.ActiveCfg = Debug|ARM + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Debug|ARM.Build.0 = Debug|ARM + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Debug|ARM.Deploy.0 = Debug|ARM + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Debug|x64.ActiveCfg = Debug|x64 + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Debug|x64.Build.0 = Debug|x64 + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Debug|x64.Deploy.0 = Debug|x64 + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Debug|x86.ActiveCfg = Debug|x86 + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Debug|x86.Build.0 = Debug|x86 + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Debug|x86.Deploy.0 = Debug|x86 + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Release|Any CPU.Build.0 = Release|Any CPU + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Release|Any CPU.Deploy.0 = Release|Any CPU + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Release|ARM.ActiveCfg = Release|ARM + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Release|ARM.Build.0 = Release|ARM + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Release|ARM.Deploy.0 = Release|ARM + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Release|x64.ActiveCfg = Release|x64 + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Release|x64.Build.0 = Release|x64 + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Release|x64.Deploy.0 = Release|x64 + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Release|x86.ActiveCfg = Release|x86 + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Release|x86.Build.0 = Release|x86 + {B87E6239-F2CA-4B18-85AE-C8296D3C5E3B}.Release|x86.Deploy.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/UnitsNet.WindowsRuntimeComponent.sln.DotSettings b/UnitsNet.WindowsRuntimeComponent.sln.DotSettings new file mode 100644 index 0000000000..8cd476110a --- /dev/null +++ b/UnitsNet.WindowsRuntimeComponent.sln.DotSettings @@ -0,0 +1,26 @@ + + True + <?xml version="1.0" encoding="utf-16"?><Profile name="Full"><CSUseVar><BehavourStyle>CAN_CHANGE_BOTH</BehavourStyle><LocalVariableStyle>IMPLICIT_WHEN_INITIALIZER_HAS_TYPE</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSUpdateFileHeader>True</CSUpdateFileHeader><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSharpFormatDocComments>True</CSharpFormatDocComments><CSReorderTypeMembers>True</CSReorderTypeMembers><CSRemoveCodeRedundancies>True</CSRemoveCodeRedundancies><AspOptimizeRegisterDirectives>True</AspOptimizeRegisterDirectives><HtmlReformatCode>True</HtmlReformatCode><CSArrangeThisQualifier>True</CSArrangeThisQualifier><RemoveCodeRedundancies>True</RemoveCodeRedundancies><CSUseAutoProperty>True</CSUseAutoProperty><CSMakeFieldReadonly>True</CSMakeFieldReadonly><JsInsertSemicolon>True</JsInsertSemicolon><JsReformatCode>True</JsReformatCode><JsFormatDocComments>True</JsFormatDocComments><CssAlphabetizeProperties>True</CssAlphabetizeProperties><CssReformatCode>True</CssReformatCode><XMLReformatCode>True</XMLReformatCode><VBOptimizeImports>True</VBOptimizeImports><VBShortenReferences>True</VBShortenReferences><VBReformatCode>True</VBReformatCode><VBFormatDocComments>True</VBFormatDocComments></Profile> + UseVarWhenEvident + UseVarWhenEvident + UseVarWhenEvident + Copyright(c) 2007 Andreas Gullberg Larsen +https://github.com/anjdreas/UnitsNet + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/UnitsNet/Properties/AssemblyInfo.WindowsRuntimeComponent.cs b/UnitsNet/Properties/AssemblyInfo.WindowsRuntimeComponent.cs new file mode 100644 index 0000000000..8e478c864d --- /dev/null +++ b/UnitsNet/Properties/AssemblyInfo.WindowsRuntimeComponent.cs @@ -0,0 +1,59 @@ +// Copyright(c) 2007 Andreas Gullberg Larsen +// https://github.com/anjdreas/UnitsNet +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; + +#if WINDOWS_UWP +using System.Runtime.InteropServices; +[assembly: ComVisible(false)] +#endif + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("Units.NET")] +[assembly: AssemblyDescription("Units.NET gives you all the common units of measurement and the conversions between them. It is light-weight, unit tested and supports PCL.")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Andreas Gullberg Larsen")] +[assembly: AssemblyProduct("Units.NET")] +[assembly: AssemblyCopyright("Copyright © 2007 Andreas Gullberg Larsen")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: NeutralResourcesLanguage("")] +[assembly: CLSCompliant(true)] +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// + +// Give access to internal members for testing +[assembly: InternalsVisibleTo("UnitsNet.Tests")] +[assembly: InternalsVisibleTo("UnitsNet.WindowsRuntimeComponent.Tests")] + +[assembly: AssemblyVersion("3.30.0")] +[assembly: AssemblyFileVersion("3.30.0")] From e3901f07215f34274f7b276c35b9eaff55032ee3 Mon Sep 17 00:00:00 2001 From: Andreas Gullberg Larsen Date: Sat, 9 Apr 2016 23:13:58 +0200 Subject: [PATCH 14/17] Add tests for WindowsRuntimeComponent * Add .NET 4.5 project with same compile flags as WRC, to run tests on * Fix compile errors due to reusing test code on WRC code paths * Distinguish the two packages.config files for test projects * Exclude WindowsRuntimeComponent specific code from the .NET projects --- UnitsNet.Tests/UnitSystemTests.cs | 29 +++++-- UnitsNet.Tests/UnitsNet.Tests.csproj | 11 ++- ...tsNet.WindowsRuntimeComponent.Tests.csproj | 79 +++++++++++++++++++ ....config => packages.UnitsNet.Tests.config} | 0 ...tsNet.WindowsRuntimeComponent.Tests.config | 5 ++ UnitsNet.sln | 66 +++++++++------- UnitsNet/UnitsNet.Net35.csproj | 4 +- UnitsNet/UnitsNet.Portable40.csproj | 4 +- ...tsNet.WindowsRuntimeComponent-Net45.csproj | 75 ++++++++++++++++++ ...tsNet.WindowsRuntimeComponent-Net45.config | 4 + 10 files changed, 234 insertions(+), 43 deletions(-) create mode 100644 UnitsNet.Tests/UnitsNet.WindowsRuntimeComponent.Tests.csproj rename UnitsNet.Tests/{packages.config => packages.UnitsNet.Tests.config} (100%) create mode 100644 UnitsNet.Tests/packages.UnitsNet.WindowsRuntimeComponent.Tests.config create mode 100644 UnitsNet/UnitsNet.WindowsRuntimeComponent-Net45.csproj create mode 100644 UnitsNet/packages.UnitsNet.WindowsRuntimeComponent-Net45.config diff --git a/UnitsNet.Tests/UnitSystemTests.cs b/UnitsNet.Tests/UnitSystemTests.cs index c42e0ea07d..547f4f225e 100644 --- a/UnitsNet.Tests/UnitSystemTests.cs +++ b/UnitsNet.Tests/UnitSystemTests.cs @@ -27,6 +27,12 @@ using NUnit.Framework; using UnitsNet.Units; +#if WINDOWS_UWP +using Culture=System.String; +#else +using Culture=System.IFormatProvider; +#endif + namespace UnitsNet.Tests { [TestFixture] @@ -112,7 +118,7 @@ private static IEnumerable GetUnitTypesWithMissingAbbreviations(s [TestCase("it-IT")] public void CommaRadixPointCultureFormatting(string culture) { - Assert.AreEqual("0,12 m", Length.FromMeters(0.12).ToString(LengthUnit.Meter, new CultureInfo(culture))); + Assert.AreEqual("0,12 m", Length.FromMeters(0.12).ToString(LengthUnit.Meter, GetCulture(culture))); } // These cultures all use a decimal point for the radix point @@ -123,7 +129,7 @@ public void CommaRadixPointCultureFormatting(string culture) [TestCase("es-MX")] public void DecimalRadixPointCultureFormatting(string culture) { - Assert.AreEqual("0.12 m", Length.FromMeters(0.12).ToString(LengthUnit.Meter, new CultureInfo(culture))); + Assert.AreEqual("0.12 m", Length.FromMeters(0.12).ToString(LengthUnit.Meter, GetCulture(culture))); } // These cultures all use a comma in digit grouping @@ -134,7 +140,7 @@ public void DecimalRadixPointCultureFormatting(string culture) [TestCase("es-MX")] public void CommaDigitGroupingCultureFormatting(string culture) { - Assert.AreEqual("1,111 m", Length.FromMeters(1111).ToString(LengthUnit.Meter, new CultureInfo(culture))); + Assert.AreEqual("1,111 m", Length.FromMeters(1111).ToString(LengthUnit.Meter, GetCulture(culture))); // Feet/Inch and Stone/Pound combinations are only used (customarily) in the US, UK and maybe Ireland - all English speaking countries. // FeetInches returns a whole number of feet, with the remainder expressed (rounded) in inches. Same for SonePounds. @@ -150,7 +156,7 @@ public void CommaDigitGroupingCultureFormatting(string culture) public void SpaceDigitGroupingCultureFormatting(string culture) { // Note: the space used in digit groupings is actually a "thin space" Unicode character U+2009 - Assert.AreEqual("1 111 m", Length.FromMeters(1111).ToString(LengthUnit.Meter, new CultureInfo(culture))); + Assert.AreEqual("1 111 m", Length.FromMeters(1111).ToString(LengthUnit.Meter, GetCulture(culture))); } // Switzerland uses an apostrophe for digit grouping @@ -169,7 +175,7 @@ public void SpaceDigitGroupingCultureFormatting(string culture) [TestCase("it-IT")] public void DecimalPointDigitGroupingCultureFormatting(string culture) { - Assert.AreEqual("1.111 m", Length.FromMeters(1111).ToString(LengthUnit.Meter, new CultureInfo(culture))); + Assert.AreEqual("1.111 m", Length.FromMeters(1111).ToString(LengthUnit.Meter, GetCulture(culture))); } [TestCase("m^2", Result = AreaUnit.SquareMeter)] @@ -419,5 +425,18 @@ public void PositiveInfinityFormatting() Assert.That(Length.FromMeters(double.PositiveInfinity).ToString(), Is.EqualTo("Infinity m")); } + + /// + /// Convenience method to use the proper culture parameter type. + /// The UWP lib uses culture name string instead of CultureInfo. + /// + private static Culture GetCulture(string cultureName) + { +#if WINDOWS_UWP + return cultureName; +#else + return new CultureInfo(cultureName); +#endif + } } } \ No newline at end of file diff --git a/UnitsNet.Tests/UnitsNet.Tests.csproj b/UnitsNet.Tests/UnitsNet.Tests.csproj index 1ce64867da..88b93eb192 100644 --- a/UnitsNet.Tests/UnitsNet.Tests.csproj +++ b/UnitsNet.Tests/UnitsNet.Tests.csproj @@ -52,9 +52,6 @@ - - - @@ -65,8 +62,14 @@ UnitsNet.Net35 + + + + packages.UnitsNet.Tests.config + + - + \ No newline at end of file diff --git a/UnitsNet.Tests/packages.config b/UnitsNet.Tests/packages.UnitsNet.Tests.config similarity index 100% rename from UnitsNet.Tests/packages.config rename to UnitsNet.Tests/packages.UnitsNet.Tests.config diff --git a/UnitsNet.Tests/packages.UnitsNet.WindowsRuntimeComponent.Tests.config b/UnitsNet.Tests/packages.UnitsNet.WindowsRuntimeComponent.Tests.config new file mode 100644 index 0000000000..087bf13f0e --- /dev/null +++ b/UnitsNet.Tests/packages.UnitsNet.WindowsRuntimeComponent.Tests.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/UnitsNet.sln b/UnitsNet.sln index 3f10bb910f..fcd4a6df57 100644 --- a/UnitsNet.sln +++ b/UnitsNet.sln @@ -18,11 +18,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{9BEB42C6 ProjectSection(SolutionItems) = preProject Build\UnitsNet.nuspec = Build\UnitsNet.nuspec Build\UnitsNet.Serialization.JsonNet.nuspec = Build\UnitsNet.Serialization.JsonNet.nuspec + Build\UnitsNet.WindowsRuntimeComponent.nuspec = Build\UnitsNet.WindowsRuntimeComponent.nuspec EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestApps", "TestApps", "{222FA466-52B9-4C04-916E-6D36B99559B4}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitsNet.WindowsRuntimeComponent.Tests", "UnitsNet.Tests\UnitsNet.WindowsRuntimeComponent.Tests.csproj", "{30DD3384-A1F9-459A-A90F-E004EBD748E8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitsNet.Uap", "UnitsNet\UnitsNet.Uap.csproj", "{2DA428CA-BFE1-43FA-86D2-7CB42289D596}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitsNet.WindowsRuntimeComponent-Net45", "UnitsNet\UnitsNet.WindowsRuntimeComponent-Net45.csproj", "{6A476F62-CA62-4A90-A866-1094BEC1D23B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -69,51 +70,55 @@ Global {2EF845D1-8177-4DF3-AEA9-5231E53CB30E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2EF845D1-8177-4DF3-AEA9-5231E53CB30E}.Debug|Any CPU.Build.0 = Debug|Any CPU {2EF845D1-8177-4DF3-AEA9-5231E53CB30E}.Debug|ARM.ActiveCfg = Debug|Any CPU - {2EF845D1-8177-4DF3-AEA9-5231E53CB30E}.Debug|ARM.Build.0 = Debug|Any CPU {2EF845D1-8177-4DF3-AEA9-5231E53CB30E}.Debug|x64.ActiveCfg = Debug|Any CPU - {2EF845D1-8177-4DF3-AEA9-5231E53CB30E}.Debug|x64.Build.0 = Debug|Any CPU {2EF845D1-8177-4DF3-AEA9-5231E53CB30E}.Debug|x86.ActiveCfg = Debug|Any CPU - {2EF845D1-8177-4DF3-AEA9-5231E53CB30E}.Debug|x86.Build.0 = Debug|Any CPU {2EF845D1-8177-4DF3-AEA9-5231E53CB30E}.Release|Any CPU.ActiveCfg = Release|Any CPU {2EF845D1-8177-4DF3-AEA9-5231E53CB30E}.Release|Any CPU.Build.0 = Release|Any CPU {2EF845D1-8177-4DF3-AEA9-5231E53CB30E}.Release|ARM.ActiveCfg = Release|Any CPU - {2EF845D1-8177-4DF3-AEA9-5231E53CB30E}.Release|ARM.Build.0 = Release|Any CPU {2EF845D1-8177-4DF3-AEA9-5231E53CB30E}.Release|x64.ActiveCfg = Release|Any CPU - {2EF845D1-8177-4DF3-AEA9-5231E53CB30E}.Release|x64.Build.0 = Release|Any CPU {2EF845D1-8177-4DF3-AEA9-5231E53CB30E}.Release|x86.ActiveCfg = Release|Any CPU - {2EF845D1-8177-4DF3-AEA9-5231E53CB30E}.Release|x86.Build.0 = Release|Any CPU {2A76FC53-E331-4CFA-83C0-93A212FD8F6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2A76FC53-E331-4CFA-83C0-93A212FD8F6E}.Debug|Any CPU.Build.0 = Debug|Any CPU {2A76FC53-E331-4CFA-83C0-93A212FD8F6E}.Debug|ARM.ActiveCfg = Debug|Any CPU - {2A76FC53-E331-4CFA-83C0-93A212FD8F6E}.Debug|ARM.Build.0 = Debug|Any CPU {2A76FC53-E331-4CFA-83C0-93A212FD8F6E}.Debug|x64.ActiveCfg = Debug|Any CPU - {2A76FC53-E331-4CFA-83C0-93A212FD8F6E}.Debug|x64.Build.0 = Debug|Any CPU {2A76FC53-E331-4CFA-83C0-93A212FD8F6E}.Debug|x86.ActiveCfg = Debug|Any CPU - {2A76FC53-E331-4CFA-83C0-93A212FD8F6E}.Debug|x86.Build.0 = Debug|Any CPU {2A76FC53-E331-4CFA-83C0-93A212FD8F6E}.Release|Any CPU.ActiveCfg = Release|Any CPU {2A76FC53-E331-4CFA-83C0-93A212FD8F6E}.Release|Any CPU.Build.0 = Release|Any CPU {2A76FC53-E331-4CFA-83C0-93A212FD8F6E}.Release|ARM.ActiveCfg = Release|Any CPU - {2A76FC53-E331-4CFA-83C0-93A212FD8F6E}.Release|ARM.Build.0 = Release|Any CPU {2A76FC53-E331-4CFA-83C0-93A212FD8F6E}.Release|x64.ActiveCfg = Release|Any CPU - {2A76FC53-E331-4CFA-83C0-93A212FD8F6E}.Release|x64.Build.0 = Release|Any CPU {2A76FC53-E331-4CFA-83C0-93A212FD8F6E}.Release|x86.ActiveCfg = Release|Any CPU - {2A76FC53-E331-4CFA-83C0-93A212FD8F6E}.Release|x86.Build.0 = Release|Any CPU - {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|ARM.ActiveCfg = Debug|ARM - {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|ARM.Build.0 = Debug|ARM - {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|x64.ActiveCfg = Debug|x64 - {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|x64.Build.0 = Debug|x64 - {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|x86.ActiveCfg = Debug|x86 - {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Debug|x86.Build.0 = Debug|x86 - {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|Any CPU.Build.0 = Release|Any CPU - {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|ARM.ActiveCfg = Release|ARM - {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|ARM.Build.0 = Release|ARM - {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|x64.ActiveCfg = Release|x64 - {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|x64.Build.0 = Release|x64 - {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|x86.ActiveCfg = Release|x86 - {2DA428CA-BFE1-43FA-86D2-7CB42289D596}.Release|x86.Build.0 = Release|x86 + {30DD3384-A1F9-459A-A90F-E004EBD748E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {30DD3384-A1F9-459A-A90F-E004EBD748E8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {30DD3384-A1F9-459A-A90F-E004EBD748E8}.Debug|ARM.ActiveCfg = Debug|Any CPU + {30DD3384-A1F9-459A-A90F-E004EBD748E8}.Debug|ARM.Build.0 = Debug|Any CPU + {30DD3384-A1F9-459A-A90F-E004EBD748E8}.Debug|x64.ActiveCfg = Debug|Any CPU + {30DD3384-A1F9-459A-A90F-E004EBD748E8}.Debug|x64.Build.0 = Debug|Any CPU + {30DD3384-A1F9-459A-A90F-E004EBD748E8}.Debug|x86.ActiveCfg = Debug|Any CPU + {30DD3384-A1F9-459A-A90F-E004EBD748E8}.Debug|x86.Build.0 = Debug|Any CPU + {30DD3384-A1F9-459A-A90F-E004EBD748E8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {30DD3384-A1F9-459A-A90F-E004EBD748E8}.Release|Any CPU.Build.0 = Release|Any CPU + {30DD3384-A1F9-459A-A90F-E004EBD748E8}.Release|ARM.ActiveCfg = Release|Any CPU + {30DD3384-A1F9-459A-A90F-E004EBD748E8}.Release|ARM.Build.0 = Release|Any CPU + {30DD3384-A1F9-459A-A90F-E004EBD748E8}.Release|x64.ActiveCfg = Release|Any CPU + {30DD3384-A1F9-459A-A90F-E004EBD748E8}.Release|x64.Build.0 = Release|Any CPU + {30DD3384-A1F9-459A-A90F-E004EBD748E8}.Release|x86.ActiveCfg = Release|Any CPU + {30DD3384-A1F9-459A-A90F-E004EBD748E8}.Release|x86.Build.0 = Release|Any CPU + {6A476F62-CA62-4A90-A866-1094BEC1D23B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6A476F62-CA62-4A90-A866-1094BEC1D23B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6A476F62-CA62-4A90-A866-1094BEC1D23B}.Debug|ARM.ActiveCfg = Debug|Any CPU + {6A476F62-CA62-4A90-A866-1094BEC1D23B}.Debug|ARM.Build.0 = Debug|Any CPU + {6A476F62-CA62-4A90-A866-1094BEC1D23B}.Debug|x64.ActiveCfg = Debug|Any CPU + {6A476F62-CA62-4A90-A866-1094BEC1D23B}.Debug|x64.Build.0 = Debug|Any CPU + {6A476F62-CA62-4A90-A866-1094BEC1D23B}.Debug|x86.ActiveCfg = Debug|Any CPU + {6A476F62-CA62-4A90-A866-1094BEC1D23B}.Debug|x86.Build.0 = Debug|Any CPU + {6A476F62-CA62-4A90-A866-1094BEC1D23B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6A476F62-CA62-4A90-A866-1094BEC1D23B}.Release|Any CPU.Build.0 = Release|Any CPU + {6A476F62-CA62-4A90-A866-1094BEC1D23B}.Release|ARM.ActiveCfg = Release|Any CPU + {6A476F62-CA62-4A90-A866-1094BEC1D23B}.Release|ARM.Build.0 = Release|Any CPU + {6A476F62-CA62-4A90-A866-1094BEC1D23B}.Release|x64.ActiveCfg = Release|Any CPU + {6A476F62-CA62-4A90-A866-1094BEC1D23B}.Release|x64.Build.0 = Release|Any CPU + {6A476F62-CA62-4A90-A866-1094BEC1D23B}.Release|x86.ActiveCfg = Release|Any CPU + {6A476F62-CA62-4A90-A866-1094BEC1D23B}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -121,5 +126,6 @@ Global GlobalSection(NestedProjects) = preSolution {6D74103A-9393-42E8-83A8-9E01F806E29D} = {4DC016EB-1ED1-4EAA-8537-E47278281BDC} {2A76FC53-E331-4CFA-83C0-93A212FD8F6E} = {4DC016EB-1ED1-4EAA-8537-E47278281BDC} + {30DD3384-A1F9-459A-A90F-E004EBD748E8} = {4DC016EB-1ED1-4EAA-8537-E47278281BDC} EndGlobalSection EndGlobal diff --git a/UnitsNet/UnitsNet.Net35.csproj b/UnitsNet/UnitsNet.Net35.csproj index fd10a5f7d1..7286487197 100644 --- a/UnitsNet/UnitsNet.Net35.csproj +++ b/UnitsNet/UnitsNet.Net35.csproj @@ -44,7 +44,7 @@ - + @@ -52,7 +52,7 @@ - + + + + Debug + AnyCPU + {6A476F62-CA62-4A90-A866-1094BEC1D23B} + Library + Properties + UnitsNet + UnitsNet.WindowsRuntimeComponent-Net45 + v4.5 + 512 + + + ..\Artifacts\Bin\Src\$(Platform)_$(Configuration)\net35\ + obj\Net45\ + ..\ + WINDOWS_UWP + + + true + full + false + TRACE;DEBUG;WINDOWS_UWP + prompt + 4 + false + + + pdbonly + true + TRACE;WINDOWS_UWP + prompt + 4 + false + + + + ..\packages\JetBrains.Annotations.10.0.0\lib\net20\JetBrains.Annotations.dll + True + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UnitsNet/packages.UnitsNet.WindowsRuntimeComponent-Net45.config b/UnitsNet/packages.UnitsNet.WindowsRuntimeComponent-Net45.config new file mode 100644 index 0000000000..c6a28e3cef --- /dev/null +++ b/UnitsNet/packages.UnitsNet.WindowsRuntimeComponent-Net45.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file From 80aaafdcc0b161717e2b6cb8c894af92de27b5c5 Mon Sep 17 00:00:00 2001 From: Andreas Gullberg Larsen Date: Sat, 9 Apr 2016 23:16:13 +0200 Subject: [PATCH 15/17] Add nuspec for UnitsNet.WindowsRuntimeComponent --- Build/UnitsNet.WindowsRuntimeComponent.nuspec | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 Build/UnitsNet.WindowsRuntimeComponent.nuspec diff --git a/Build/UnitsNet.WindowsRuntimeComponent.nuspec b/Build/UnitsNet.WindowsRuntimeComponent.nuspec new file mode 100644 index 0000000000..48c3c5ed72 --- /dev/null +++ b/Build/UnitsNet.WindowsRuntimeComponent.nuspec @@ -0,0 +1,27 @@ + + + + + UnitsNet.WindowsRuntimeComponent + 3.30.0-alpha7 + Units.NET - Windows Runtime Component + Andreas Gullberg Larsen + Andreas Gullberg Larsen + https://github.com/anjdreas/UnitsNet/blob/master/LICENSE + https://github.com/anjdreas/UnitsNet + false + For C#/VB Universal Windows code (UWP), use UnitsNet instead. This is a Windows Runtime Component with reduced functionality to support all UWP languages, such as JavaScript and C++, and other runtime components. + For C#/VB Universal Windows code (UWP), use UnitsNet instead. + https://raw.githubusercontent.com/anjdreas/UnitsNet/ce85185429be345d77eb2ce09c99d59cc9ab8aed/Docs/Images/logo-32.png + +* Add nuget with Windows Runtime Component for Universal Windows apps (UWP) + + Copyright © 2015 Andreas Gullberg Larsen + en-US + unit units measurement si metric imperial abbreviation abbreviations convert conversion parse c# .net immutable uwp uap winrt win10 windows runtime component + + + + + + From 87a68ff48576c8e81151443454c9f556a2401dfc Mon Sep 17 00:00:00 2001 From: Andreas Gullberg Larsen Date: Sat, 9 Apr 2016 23:17:05 +0200 Subject: [PATCH 16/17] build: Include UnitsNet.WindowsRuntimeComponent project --- Build/UpdateAssemblyInfo.ps1 | 21 +++++++++++---------- Build/nuget-restore.bat | 7 +++++-- Build/pack-nuget.bat | 13 ++++++++----- Build/run-tests.bat | 7 +++++-- Build/src.msbuild | 1 + Build/tests.msbuild | 1 + 6 files changed, 31 insertions(+), 19 deletions(-) diff --git a/Build/UpdateAssemblyInfo.ps1 b/Build/UpdateAssemblyInfo.ps1 index a4996b4202..101a7eaae3 100644 --- a/Build/UpdateAssemblyInfo.ps1 +++ b/Build/UpdateAssemblyInfo.ps1 @@ -6,7 +6,7 @@ .EXAMPLE Set new version. powershell UpdateAssemblyInfo.ps1 1.2.3.4 - + .NOTES Author: Andreas Gullberg Larsen Date: May 2, 2014 @@ -40,37 +40,38 @@ function Get-VersionFromNuspec ([string] $nuspecFilePath) { } #------------------------------------------------------------------------------- -# Description: Sets the AssemblyVersion and AssemblyFileVersion of +# Description: Sets the AssemblyVersion and AssemblyFileVersion of # AssemblyInfo.cs files. # # Author: Andreas Larsen # Version: 1.0 #------------------------------------------------------------------------------- -function Update-AssemblyInfoFiles ([string] $libName) { +function Update-AssemblyInfoFiles ([string] $nuspecFilePath, [string] $assemblyInfoFilePath) { - [Version]$version = Get-VersionFromNuspec "$root\Build\$libName.nuspec" + [Version]$version = Get-VersionFromNuspec "$root\$nuspecFilePath" $assemblyVersionPattern = 'AssemblyVersion\("[0-9]+(\.([0-9]+|\*)){1,3}"\)' $fileVersionPattern = 'AssemblyFileVersion\("[0-9]+(\.([0-9]+|\*)){1,3}"\)' $assemblyVersion = 'AssemblyVersion("' + $version + '")'; $fileVersion = 'AssemblyFileVersion("' + $version + '")'; - - Get-ChildItem "$root\$libName\Properties" | Where { $_.PSChildName -match "^AssemblyInfo\.cs$"} | ForEach-Object { + + Get-ChildItem "$root\$assemblyInfoFilePath" | ForEach-Object { $filename = $_.Directory.ToString() + '\' + $_.Name $filename + ' -> ' + $version - + (Get-Content $filename -Encoding UTF8) | ForEach-Object { % {$_ -replace $assemblyVersionPattern, $assemblyVersion } | % {$_ -replace $fileVersionPattern, $fileVersion } } | Set-Content $filename -Encoding UTF8 - } + } } try { "Updating assembly info to version: $setVersion" "" - Update-AssemblyInfoFiles "UnitsNet" - Update-AssemblyInfoFiles "UnitsNet.Serialization.JsonNet" + Update-AssemblyInfoFiles "Build\UnitsNet.nuspec" "UnitsNet\Properties\AssemblyInfo.cs" + Update-AssemblyInfoFiles "Build\UnitsNet.WindowsRuntimeComponent.nuspec" "UnitsNet\Properties\AssemblyInfo.WindowsRuntimeComponent.cs" + Update-AssemblyInfoFiles "Build\UnitsNet.Serialization.JsonNet.nuspec" "UnitsNet.Serialization.JsonNet\Properties\AssemblyInfo.cs" } catch { $myError = $_.Exception.ToString() diff --git a/Build/nuget-restore.bat b/Build/nuget-restore.bat index f0b2fd9bbf..9ad2a7d023 100644 --- a/Build/nuget-restore.bat +++ b/Build/nuget-restore.bat @@ -1,6 +1,9 @@ @echo off SET ROOT=%~dp0.. SET NuGetExe=%ROOT%\Tools\NuGet.exe -SET SolutionFile=%ROOT%\UnitsNet.sln -%NuGetExe% restore %SolutionFile% + +%NuGetExe% restore %ROOT%\UnitsNet.sln +if %errorlevel% neq 0 exit /b %errorlevel% + +%NuGetExe% restore %ROOT%\UnitsNet.WindowsRuntimeComponent.sln if %errorlevel% neq 0 exit /b %errorlevel% \ No newline at end of file diff --git a/Build/pack-nuget.bat b/Build/pack-nuget.bat index 3cb9149b28..4a1926a869 100644 --- a/Build/pack-nuget.bat +++ b/Build/pack-nuget.bat @@ -1,13 +1,16 @@ @echo off SET ROOT=%~dp0.. -SET MainLibNuspec=%ROOT%\Build\UnitsNet.nuspec -SET SerializationLibNuspec=%ROOT%\Build\UnitsNet.Serialization.JsonNet.nuspec +SET MainNuspec=%ROOT%\Build\UnitsNet.nuspec +SET UwpNuspec=%ROOT%\Build\UnitsNet.WindowsRuntimeComponent.nuspec +SET SerializationNuspec=%ROOT%\Build\UnitsNet.Serialization.JsonNet.nuspec SET NuGetExe=%ROOT%\Tools\NuGet.exe SET NuGetOutDir=%ROOT%\Artifacts\NuGet mkdir "%NuGetOutDir%" -%NuGetExe% pack %MainLibNuspec% -Verbosity detailed -OutputDirectory "%NuGetOutDir%" -BasePath "%ROOT%" -Symbols +%NuGetExe% pack %MainNuspec% -Verbosity detailed -OutputDirectory "%NuGetOutDir%" -BasePath "%ROOT%" -Symbols +if %errorlevel% neq 0 exit /b %errorlevel% +%NuGetExe% pack %UwpNuspec% -Verbosity detailed -OutputDirectory "%NuGetOutDir%" -BasePath "%ROOT%" -Symbols +if %errorlevel% neq 0 exit /b %errorlevel% +%NuGetExe% pack %SerializationNuspec% -Verbosity detailed -OutputDirectory "%NuGetOutDir%" -BasePath "%ROOT%" -Symbols if %errorlevel% neq 0 exit /b %errorlevel% -%NuGetExe% pack %SerializationLibNuspec% -Verbosity detailed -OutputDirectory "%NuGetOutDir%" -BasePath "%ROOT%" -Symbols -if %errorlevel% neq 0 exit /b %errorlevel% \ No newline at end of file diff --git a/Build/run-tests.bat b/Build/run-tests.bat index 03f87a3084..752889151e 100644 --- a/Build/run-tests.bat +++ b/Build/run-tests.bat @@ -4,8 +4,11 @@ set LogDir=%ROOT%\Artifacts\Logs set TestsBinDir=%ROOT%\Artifacts\Bin\Tests\AnyCPU_Release mkdir %LogDir% -%ROOT%\Tools\NUnit\nunit-console.exe "%TestsBinDir%\UnitsNet.Tests.dll" /framework="net-4.0" /xml:%LogDir%\UnitsNet.Tests.xml +%ROOT%\Tools\NUnit\nunit-console.exe "%TestsBinDir%\UnitsNet.Tests.dll" /framework="net-4.5" /xml:%LogDir%\UnitsNet.Tests.xml if %errorlevel% neq 0 exit /b %errorlevel% -%ROOT%\Tools\NUnit\nunit-console.exe "%TestsBinDir%\UnitsNet.Serialization.JsonNet.Tests.dll" /framework="net-3.5" /xml:%LogDir%\UnitsNet.Serialization.JsonNet.Tests.xml +%ROOT%\Tools\NUnit\nunit-console.exe "%TestsBinDir%\UnitsNet.WindowsRuntimeComponent.Tests.dll" /framework="net-4.5" /xml:%LogDir%\UnitsNet.WindowsRuntimeComponent.Tests.xml +if %errorlevel% neq 0 exit /b %errorlevel% + +%ROOT%\Tools\NUnit\nunit-console.exe "%TestsBinDir%\UnitsNet.Serialization.JsonNet.Tests.dll" /framework="net-4.5" /xml:%LogDir%\UnitsNet.Serialization.JsonNet.Tests.xml if %errorlevel% neq 0 exit /b %errorlevel% \ No newline at end of file diff --git a/Build/src.msbuild b/Build/src.msbuild index c4c6528d40..221054dd16 100644 --- a/Build/src.msbuild +++ b/Build/src.msbuild @@ -20,6 +20,7 @@ diff --git a/Build/tests.msbuild b/Build/tests.msbuild index 68d5c4eb1a..9c61397fe5 100644 --- a/Build/tests.msbuild +++ b/Build/tests.msbuild @@ -19,6 +19,7 @@ From 50defd2fb221656797e4c3db221398951590304e Mon Sep 17 00:00:00 2001 From: Andreas Gullberg Larsen Date: Wed, 20 Apr 2016 22:13:29 +0200 Subject: [PATCH 17/17] WindowsRuntimeComponent: 3.33.0 Match core lib version and remove prerelease suffix Remove release notes, add to tag instead --- Build/UnitsNet.WindowsRuntimeComponent.nuspec | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Build/UnitsNet.WindowsRuntimeComponent.nuspec b/Build/UnitsNet.WindowsRuntimeComponent.nuspec index 48c3c5ed72..542ffc4bbf 100644 --- a/Build/UnitsNet.WindowsRuntimeComponent.nuspec +++ b/Build/UnitsNet.WindowsRuntimeComponent.nuspec @@ -3,7 +3,7 @@ UnitsNet.WindowsRuntimeComponent - 3.30.0-alpha7 + 3.33.0 Units.NET - Windows Runtime Component Andreas Gullberg Larsen Andreas Gullberg Larsen @@ -13,9 +13,7 @@ For C#/VB Universal Windows code (UWP), use UnitsNet instead. This is a Windows Runtime Component with reduced functionality to support all UWP languages, such as JavaScript and C++, and other runtime components. For C#/VB Universal Windows code (UWP), use UnitsNet instead. https://raw.githubusercontent.com/anjdreas/UnitsNet/ce85185429be345d77eb2ce09c99d59cc9ab8aed/Docs/Images/logo-32.png - -* Add nuget with Windows Runtime Component for Universal Windows apps (UWP) - + Copyright © 2015 Andreas Gullberg Larsen en-US unit units measurement si metric imperial abbreviation abbreviations convert conversion parse c# .net immutable uwp uap winrt win10 windows runtime component