├── .gitattributes ├── .gitignore ├── CODE_OF_CONDUCT.md ├── Demos ├── 01-create-app │ ├── README.md │ ├── graph-tutorial.sln │ └── graph-tutorial │ │ ├── App_Start │ │ ├── BundleConfig.cs │ │ ├── FilterConfig.cs │ │ └── RouteConfig.cs │ │ ├── Content │ │ ├── Site.css │ │ ├── bootstrap-grid.css │ │ ├── bootstrap-grid.css.map │ │ ├── bootstrap-grid.min.css │ │ ├── bootstrap-grid.min.css.map │ │ ├── bootstrap-reboot.css │ │ ├── bootstrap-reboot.css.map │ │ ├── bootstrap-reboot.min.css │ │ ├── bootstrap-reboot.min.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ │ ├── Controllers │ │ ├── BaseController.cs │ │ └── HomeController.cs │ │ ├── Global.asax │ │ ├── Global.asax.cs │ │ ├── Models │ │ └── Alert.cs │ │ ├── Properties │ │ └── AssemblyInfo.cs │ │ ├── Scripts │ │ ├── README.md │ │ ├── bootstrap.bundle.js │ │ ├── bootstrap.bundle.js.map │ │ ├── bootstrap.bundle.min.js │ │ ├── bootstrap.bundle.min.js.map │ │ ├── bootstrap.js │ │ ├── bootstrap.js.map │ │ ├── bootstrap.min.js │ │ ├── bootstrap.min.js.map │ │ ├── esm │ │ │ ├── popper-utils.js │ │ │ ├── popper-utils.js.map │ │ │ ├── popper-utils.min.js │ │ │ ├── popper-utils.min.js.map │ │ │ ├── popper.js │ │ │ ├── popper.js.map │ │ │ ├── popper.min.js │ │ │ └── popper.min.js.map │ │ ├── index.d.ts │ │ ├── index.js.flow │ │ ├── jquery-3.4.1.intellisense.js │ │ ├── jquery-3.4.1.js │ │ ├── jquery-3.4.1.min.js │ │ ├── jquery-3.4.1.min.map │ │ ├── jquery-3.4.1.slim.js │ │ ├── jquery-3.4.1.slim.min.js │ │ ├── jquery-3.4.1.slim.min.map │ │ ├── jquery.validate-vsdoc.js │ │ ├── jquery.validate.js │ │ ├── jquery.validate.min.js │ │ ├── jquery.validate.unobtrusive.js │ │ ├── jquery.validate.unobtrusive.min.js │ │ ├── modernizr-2.8.3.js │ │ ├── popper-utils.js │ │ ├── popper-utils.js.map │ │ ├── popper-utils.min.js │ │ ├── popper-utils.min.js.map │ │ ├── popper.js │ │ ├── popper.js.map │ │ ├── popper.min.js │ │ ├── popper.min.js.map │ │ ├── src │ │ │ ├── index.js │ │ │ ├── methods │ │ │ │ ├── defaults.js │ │ │ │ ├── destroy.js │ │ │ │ ├── disableEventListeners.js │ │ │ │ ├── enableEventListeners.js │ │ │ │ ├── placements.js │ │ │ │ └── update.js │ │ │ ├── modifiers │ │ │ │ ├── applyStyle.js │ │ │ │ ├── arrow.js │ │ │ │ ├── computeStyle.js │ │ │ │ ├── flip.js │ │ │ │ ├── hide.js │ │ │ │ ├── index.js │ │ │ │ ├── inner.js │ │ │ │ ├── keepTogether.js │ │ │ │ ├── offset.js │ │ │ │ ├── preventOverflow.js │ │ │ │ └── shift.js │ │ │ └── utils │ │ │ │ ├── clockwise.js │ │ │ │ ├── computeAutoPlacement.js │ │ │ │ ├── debounce.js │ │ │ │ ├── find.js │ │ │ │ ├── findCommonOffsetParent.js │ │ │ │ ├── findIndex.js │ │ │ │ ├── getBordersSize.js │ │ │ │ ├── getBoundaries.js │ │ │ │ ├── getBoundingClientRect.js │ │ │ │ ├── getClientRect.js │ │ │ │ ├── getFixedPositionOffsetParent.js │ │ │ │ ├── getOffsetParent.js │ │ │ │ ├── getOffsetRect.js │ │ │ │ ├── getOffsetRectRelativeToArbitraryNode.js │ │ │ │ ├── getOppositePlacement.js │ │ │ │ ├── getOppositeVariation.js │ │ │ │ ├── getOuterSizes.js │ │ │ │ ├── getParentNode.js │ │ │ │ ├── getPopperOffsets.js │ │ │ │ ├── getReferenceNode.js │ │ │ │ ├── getReferenceOffsets.js │ │ │ │ ├── getRoot.js │ │ │ │ ├── getRoundedOffsets.js │ │ │ │ ├── getScroll.js │ │ │ │ ├── getScrollParent.js │ │ │ │ ├── getStyleComputedProperty.js │ │ │ │ ├── getSupportedPropertyName.js │ │ │ │ ├── getViewportOffsetRectRelativeToArtbitraryNode.js │ │ │ │ ├── getWindow.js │ │ │ │ ├── getWindowSizes.js │ │ │ │ ├── includeScroll.js │ │ │ │ ├── index.js │ │ │ │ ├── isBrowser.js │ │ │ │ ├── isFixed.js │ │ │ │ ├── isFunction.js │ │ │ │ ├── isIE.js │ │ │ │ ├── isModifierEnabled.js │ │ │ │ ├── isModifierRequired.js │ │ │ │ ├── isNumeric.js │ │ │ │ ├── isOffsetContainer.js │ │ │ │ ├── removeEventListeners.js │ │ │ │ ├── runModifiers.js │ │ │ │ ├── setAttributes.js │ │ │ │ ├── setStyles.js │ │ │ │ └── setupEventListeners.js │ │ └── umd │ │ │ ├── popper-utils.js │ │ │ ├── popper-utils.js.map │ │ │ ├── popper-utils.min.js │ │ │ ├── popper-utils.min.js.map │ │ │ ├── popper.js │ │ │ ├── popper.js.flow │ │ │ ├── popper.js.map │ │ │ ├── popper.min.js │ │ │ └── popper.min.js.map │ │ ├── Startup.cs │ │ ├── Views │ │ ├── Home │ │ │ ├── About.cshtml │ │ │ ├── Contact.cshtml │ │ │ └── Index.cshtml │ │ ├── Shared │ │ │ ├── Error.cshtml │ │ │ └── _Layout.cshtml │ │ ├── Web.config │ │ └── _ViewStart.cshtml │ │ ├── Web.Debug.config │ │ ├── Web.Release.config │ │ ├── Web.config │ │ ├── favicon.ico │ │ ├── graph-tutorial.csproj │ │ └── packages.config ├── 02-add-aad-auth │ ├── README.md │ ├── graph-tutorial.sln │ └── graph-tutorial │ │ ├── App_Start │ │ ├── BundleConfig.cs │ │ ├── FilterConfig.cs │ │ ├── RouteConfig.cs │ │ └── Startup.Auth.cs │ │ ├── Content │ │ ├── Site.css │ │ ├── bootstrap-grid.css │ │ ├── bootstrap-grid.css.map │ │ ├── bootstrap-grid.min.css │ │ ├── bootstrap-grid.min.css.map │ │ ├── bootstrap-reboot.css │ │ ├── bootstrap-reboot.css.map │ │ ├── bootstrap-reboot.min.css │ │ ├── bootstrap-reboot.min.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ │ ├── Controllers │ │ ├── AccountController.cs │ │ ├── BaseController.cs │ │ └── HomeController.cs │ │ ├── Global.asax │ │ ├── Global.asax.cs │ │ ├── Helpers │ │ └── GraphHelper.cs │ │ ├── Models │ │ ├── Alert.cs │ │ └── CachedUser.cs │ │ ├── Properties │ │ └── AssemblyInfo.cs │ │ ├── Scripts │ │ ├── README.md │ │ ├── bootstrap.bundle.js │ │ ├── bootstrap.bundle.js.map │ │ ├── bootstrap.bundle.min.js │ │ ├── bootstrap.bundle.min.js.map │ │ ├── bootstrap.js │ │ ├── bootstrap.js.map │ │ ├── bootstrap.min.js │ │ ├── bootstrap.min.js.map │ │ ├── esm │ │ │ ├── popper-utils.js │ │ │ ├── popper-utils.js.map │ │ │ ├── popper-utils.min.js │ │ │ ├── popper-utils.min.js.map │ │ │ ├── popper.js │ │ │ ├── popper.js.map │ │ │ ├── popper.min.js │ │ │ └── popper.min.js.map │ │ ├── index.d.ts │ │ ├── index.js.flow │ │ ├── jquery-3.4.1.intellisense.js │ │ ├── jquery-3.4.1.js │ │ ├── jquery-3.4.1.min.js │ │ ├── jquery-3.4.1.min.map │ │ ├── jquery-3.4.1.slim.js │ │ ├── jquery-3.4.1.slim.min.js │ │ ├── jquery-3.4.1.slim.min.map │ │ ├── jquery.validate-vsdoc.js │ │ ├── jquery.validate.js │ │ ├── jquery.validate.min.js │ │ ├── jquery.validate.unobtrusive.js │ │ ├── jquery.validate.unobtrusive.min.js │ │ ├── modernizr-2.8.3.js │ │ ├── popper-utils.js │ │ ├── popper-utils.js.map │ │ ├── popper-utils.min.js │ │ ├── popper-utils.min.js.map │ │ ├── popper.js │ │ ├── popper.js.map │ │ ├── popper.min.js │ │ ├── popper.min.js.map │ │ ├── src │ │ │ ├── index.js │ │ │ ├── methods │ │ │ │ ├── defaults.js │ │ │ │ ├── destroy.js │ │ │ │ ├── disableEventListeners.js │ │ │ │ ├── enableEventListeners.js │ │ │ │ ├── placements.js │ │ │ │ └── update.js │ │ │ ├── modifiers │ │ │ │ ├── applyStyle.js │ │ │ │ ├── arrow.js │ │ │ │ ├── computeStyle.js │ │ │ │ ├── flip.js │ │ │ │ ├── hide.js │ │ │ │ ├── index.js │ │ │ │ ├── inner.js │ │ │ │ ├── keepTogether.js │ │ │ │ ├── offset.js │ │ │ │ ├── preventOverflow.js │ │ │ │ └── shift.js │ │ │ └── utils │ │ │ │ ├── clockwise.js │ │ │ │ ├── computeAutoPlacement.js │ │ │ │ ├── debounce.js │ │ │ │ ├── find.js │ │ │ │ ├── findCommonOffsetParent.js │ │ │ │ ├── findIndex.js │ │ │ │ ├── getBordersSize.js │ │ │ │ ├── getBoundaries.js │ │ │ │ ├── getBoundingClientRect.js │ │ │ │ ├── getClientRect.js │ │ │ │ ├── getFixedPositionOffsetParent.js │ │ │ │ ├── getOffsetParent.js │ │ │ │ ├── getOffsetRect.js │ │ │ │ ├── getOffsetRectRelativeToArbitraryNode.js │ │ │ │ ├── getOppositePlacement.js │ │ │ │ ├── getOppositeVariation.js │ │ │ │ ├── getOuterSizes.js │ │ │ │ ├── getParentNode.js │ │ │ │ ├── getPopperOffsets.js │ │ │ │ ├── getReferenceNode.js │ │ │ │ ├── getReferenceOffsets.js │ │ │ │ ├── getRoot.js │ │ │ │ ├── getRoundedOffsets.js │ │ │ │ ├── getScroll.js │ │ │ │ ├── getScrollParent.js │ │ │ │ ├── getStyleComputedProperty.js │ │ │ │ ├── getSupportedPropertyName.js │ │ │ │ ├── getViewportOffsetRectRelativeToArtbitraryNode.js │ │ │ │ ├── getWindow.js │ │ │ │ ├── getWindowSizes.js │ │ │ │ ├── includeScroll.js │ │ │ │ ├── index.js │ │ │ │ ├── isBrowser.js │ │ │ │ ├── isFixed.js │ │ │ │ ├── isFunction.js │ │ │ │ ├── isIE.js │ │ │ │ ├── isModifierEnabled.js │ │ │ │ ├── isModifierRequired.js │ │ │ │ ├── isNumeric.js │ │ │ │ ├── isOffsetContainer.js │ │ │ │ ├── removeEventListeners.js │ │ │ │ ├── runModifiers.js │ │ │ │ ├── setAttributes.js │ │ │ │ ├── setStyles.js │ │ │ │ └── setupEventListeners.js │ │ └── umd │ │ │ ├── popper-utils.js │ │ │ ├── popper-utils.js.map │ │ │ ├── popper-utils.min.js │ │ │ ├── popper-utils.min.js.map │ │ │ ├── popper.js │ │ │ ├── popper.js.flow │ │ │ ├── popper.js.map │ │ │ ├── popper.min.js │ │ │ └── popper.min.js.map │ │ ├── Startup.cs │ │ ├── TokenStorage │ │ └── SessionTokenStore.cs │ │ ├── Views │ │ ├── Home │ │ │ ├── About.cshtml │ │ │ ├── Contact.cshtml │ │ │ └── Index.cshtml │ │ ├── Shared │ │ │ ├── Error.cshtml │ │ │ └── _Layout.cshtml │ │ ├── Web.config │ │ └── _ViewStart.cshtml │ │ ├── Web.Debug.config │ │ ├── Web.Release.config │ │ ├── Web.config │ │ ├── favicon.ico │ │ ├── graph-tutorial.csproj │ │ └── packages.config └── 03-add-msgraph │ ├── README.md │ ├── graph-tutorial.sln │ ├── graph-tutorial │ ├── App_Start │ │ ├── BundleConfig.cs │ │ ├── FilterConfig.cs │ │ ├── RouteConfig.cs │ │ └── Startup.Auth.cs │ ├── Content │ │ ├── Site.css │ │ ├── bootstrap-grid.css │ │ ├── bootstrap-grid.css.map │ │ ├── bootstrap-grid.min.css │ │ ├── bootstrap-grid.min.css.map │ │ ├── bootstrap-reboot.css │ │ ├── bootstrap-reboot.css.map │ │ ├── bootstrap-reboot.min.css │ │ ├── bootstrap-reboot.min.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ ├── Controllers │ │ ├── AccountController.cs │ │ ├── BaseController.cs │ │ ├── CalendarController.cs │ │ └── HomeController.cs │ ├── Global.asax │ ├── Global.asax.cs │ ├── Helpers │ │ └── GraphHelper.cs │ ├── Models │ │ ├── Alert.cs │ │ └── CachedUser.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Scripts │ │ ├── README.md │ │ ├── bootstrap.bundle.js │ │ ├── bootstrap.bundle.js.map │ │ ├── bootstrap.bundle.min.js │ │ ├── bootstrap.bundle.min.js.map │ │ ├── bootstrap.js │ │ ├── bootstrap.js.map │ │ ├── bootstrap.min.js │ │ ├── bootstrap.min.js.map │ │ ├── esm │ │ │ ├── popper-utils.js │ │ │ ├── popper-utils.js.map │ │ │ ├── popper-utils.min.js │ │ │ ├── popper-utils.min.js.map │ │ │ ├── popper.js │ │ │ ├── popper.js.map │ │ │ ├── popper.min.js │ │ │ └── popper.min.js.map │ │ ├── index.d.ts │ │ ├── index.js.flow │ │ ├── jquery-3.4.1.intellisense.js │ │ ├── jquery-3.4.1.js │ │ ├── jquery-3.4.1.min.js │ │ ├── jquery-3.4.1.min.map │ │ ├── jquery-3.4.1.slim.js │ │ ├── jquery-3.4.1.slim.min.js │ │ ├── jquery-3.4.1.slim.min.map │ │ ├── jquery.validate-vsdoc.js │ │ ├── jquery.validate.js │ │ ├── jquery.validate.min.js │ │ ├── jquery.validate.unobtrusive.js │ │ ├── jquery.validate.unobtrusive.min.js │ │ ├── modernizr-2.8.3.js │ │ ├── popper-utils.js │ │ ├── popper-utils.js.map │ │ ├── popper-utils.min.js │ │ ├── popper-utils.min.js.map │ │ ├── popper.js │ │ ├── popper.js.map │ │ ├── popper.min.js │ │ ├── popper.min.js.map │ │ ├── src │ │ │ ├── index.js │ │ │ ├── methods │ │ │ │ ├── defaults.js │ │ │ │ ├── destroy.js │ │ │ │ ├── disableEventListeners.js │ │ │ │ ├── enableEventListeners.js │ │ │ │ ├── placements.js │ │ │ │ └── update.js │ │ │ ├── modifiers │ │ │ │ ├── applyStyle.js │ │ │ │ ├── arrow.js │ │ │ │ ├── computeStyle.js │ │ │ │ ├── flip.js │ │ │ │ ├── hide.js │ │ │ │ ├── index.js │ │ │ │ ├── inner.js │ │ │ │ ├── keepTogether.js │ │ │ │ ├── offset.js │ │ │ │ ├── preventOverflow.js │ │ │ │ └── shift.js │ │ │ └── utils │ │ │ │ ├── clockwise.js │ │ │ │ ├── computeAutoPlacement.js │ │ │ │ ├── debounce.js │ │ │ │ ├── find.js │ │ │ │ ├── findCommonOffsetParent.js │ │ │ │ ├── findIndex.js │ │ │ │ ├── getBordersSize.js │ │ │ │ ├── getBoundaries.js │ │ │ │ ├── getBoundingClientRect.js │ │ │ │ ├── getClientRect.js │ │ │ │ ├── getFixedPositionOffsetParent.js │ │ │ │ ├── getOffsetParent.js │ │ │ │ ├── getOffsetRect.js │ │ │ │ ├── getOffsetRectRelativeToArbitraryNode.js │ │ │ │ ├── getOppositePlacement.js │ │ │ │ ├── getOppositeVariation.js │ │ │ │ ├── getOuterSizes.js │ │ │ │ ├── getParentNode.js │ │ │ │ ├── getPopperOffsets.js │ │ │ │ ├── getReferenceNode.js │ │ │ │ ├── getReferenceOffsets.js │ │ │ │ ├── getRoot.js │ │ │ │ ├── getRoundedOffsets.js │ │ │ │ ├── getScroll.js │ │ │ │ ├── getScrollParent.js │ │ │ │ ├── getStyleComputedProperty.js │ │ │ │ ├── getSupportedPropertyName.js │ │ │ │ ├── getViewportOffsetRectRelativeToArtbitraryNode.js │ │ │ │ ├── getWindow.js │ │ │ │ ├── getWindowSizes.js │ │ │ │ ├── includeScroll.js │ │ │ │ ├── index.js │ │ │ │ ├── isBrowser.js │ │ │ │ ├── isFixed.js │ │ │ │ ├── isFunction.js │ │ │ │ ├── isIE.js │ │ │ │ ├── isModifierEnabled.js │ │ │ │ ├── isModifierRequired.js │ │ │ │ ├── isNumeric.js │ │ │ │ ├── isOffsetContainer.js │ │ │ │ ├── removeEventListeners.js │ │ │ │ ├── runModifiers.js │ │ │ │ ├── setAttributes.js │ │ │ │ ├── setStyles.js │ │ │ │ └── setupEventListeners.js │ │ └── umd │ │ │ ├── popper-utils.js │ │ │ ├── popper-utils.js.map │ │ │ ├── popper-utils.min.js │ │ │ ├── popper-utils.min.js.map │ │ │ ├── popper.js │ │ │ ├── popper.js.flow │ │ │ ├── popper.js.map │ │ │ ├── popper.min.js │ │ │ └── popper.min.js.map │ ├── Startup.cs │ ├── TokenStorage │ │ └── SessionTokenStore.cs │ ├── Views │ │ ├── Calendar │ │ │ └── Index.cshtml │ │ ├── Home │ │ │ ├── About.cshtml │ │ │ ├── Contact.cshtml │ │ │ └── Index.cshtml │ │ ├── Shared │ │ │ ├── Error.cshtml │ │ │ └── _Layout.cshtml │ │ ├── Web.config │ │ └── _ViewStart.cshtml │ ├── Web.Debug.config │ ├── Web.Release.config │ ├── Web.config │ ├── favicon.ico │ ├── graph-tutorial.csproj │ └── packages.config │ └── version ├── LICENSE ├── README.md ├── SECURITY.md ├── qs.json └── slides.pptx /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | - Employees can reach out at [aka.ms/opensource/moderation-support](https://aka.ms/opensource/moderation-support) 11 | -------------------------------------------------------------------------------- /Demos/01-create-app/README.md: -------------------------------------------------------------------------------- 1 | # Demo: Create an ASP.NET MVC web app 2 | 3 | This completed project is the result of the lab exercise **Create an ASP.NET MVC web app** that is referenced in the [README](../../README.md) in this repo. 4 | 5 | ## Prerequisites 6 | 7 | - [Microsoft 365 tenant](https://developer.microsoft.com/office/dev-program?ocid=MSlearn) 8 | - [.NET Framework 4.8](https://dotnet.microsoft.com/download/dotnet-framework) 9 | - [Visual Studio 2022](https://visualstudio.microsoft.com/vs/) 10 | 11 | ## Run this Completed Project 12 | 13 | - Create an Azure AD application by following the instructions in the lab exercise associated with this demo. In this step, you are instructed to collect these data elements: 14 | - Application ID 15 | - Client secret 16 | - Build and run the application by following the instructions in the lab exercise associated with this demo. 17 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.2.32505.173 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "graph-tutorial", "graph-tutorial\graph-tutorial.csproj", "{3839C133-E2D0-466C-ABB3-E92ABCDB6388}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3839C133-E2D0-466C-ABB3-E92ABCDB6388}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {3839C133-E2D0-466C-ABB3-E92ABCDB6388}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {3839C133-E2D0-466C-ABB3-E92ABCDB6388}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {3839C133-E2D0-466C-ABB3-E92ABCDB6388}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {5D8392F3-02AC-499D-9495-D6ED8CE615C5} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/App_Start/BundleConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Optimization; 3 | 4 | namespace graph_tutorial 5 | { 6 | public class BundleConfig 7 | { 8 | // For more information on bundling, visit https://go.microsoft.com/fwlink/?LinkId=301862 9 | public static void RegisterBundles(BundleCollection bundles) 10 | { 11 | bundles.Add(new ScriptBundle("~/bundles/jquery").Include( 12 | "~/Scripts/jquery-{version}.js")); 13 | 14 | bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include( 15 | "~/Scripts/jquery.validate*")); 16 | 17 | // Use the development version of Modernizr to develop with and learn from. Then, when you're 18 | // ready for production, use the build tool at https://modernizr.com to pick only the tests you need. 19 | bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( 20 | "~/Scripts/modernizr-*")); 21 | 22 | bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include( 23 | "~/Scripts/bootstrap.js")); 24 | 25 | bundles.Add(new StyleBundle("~/Content/css").Include( 26 | "~/Content/bootstrap.css", 27 | "~/Content/site.css")); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/App_Start/FilterConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Mvc; 3 | 4 | namespace graph_tutorial 5 | { 6 | public class FilterConfig 7 | { 8 | public static void RegisterGlobalFilters(GlobalFilterCollection filters) 9 | { 10 | filters.Add(new HandleErrorAttribute()); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace graph_tutorial 9 | { 10 | public class RouteConfig 11 | { 12 | public static void RegisterRoutes(RouteCollection routes) 13 | { 14 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 15 | 16 | routes.MapRoute( 17 | name: "Default", 18 | url: "{controller}/{action}/{id}", 19 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 20 | ); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Content/Site.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | body { 7 | padding-top: 4.5rem; 8 | } 9 | 10 | .alert-pre { 11 | word-wrap: break-word; 12 | word-break: break-all; 13 | white-space: pre-wrap; 14 | } -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Controllers/BaseController.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | using graph_tutorial.Models; 5 | using System.Collections.Generic; 6 | using System.Web.Mvc; 7 | 8 | namespace graph_tutorial.Controllers 9 | { 10 | public abstract class BaseController : Controller 11 | { 12 | protected void Flash(string message, string debug = null) 13 | { 14 | var alerts = TempData.ContainsKey(Alert.AlertKey) ? 15 | (List)TempData[Alert.AlertKey] : 16 | new List(); 17 | 18 | alerts.Add(new Alert 19 | { 20 | Message = message, 21 | Debug = debug 22 | }); 23 | 24 | TempData[Alert.AlertKey] = alerts; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Web; 8 | using System.Web.Mvc; 9 | 10 | namespace graph_tutorial.Controllers 11 | { 12 | public class HomeController : BaseController 13 | { 14 | public ActionResult Index() 15 | { 16 | return View(); 17 | } 18 | 19 | public ActionResult About() 20 | { 21 | ViewBag.Message = "Your application description page."; 22 | 23 | return View(); 24 | } 25 | 26 | public ActionResult Contact() 27 | { 28 | ViewBag.Message = "Your contact page."; 29 | 30 | return View(); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="graph_tutorial.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Optimization; 7 | using System.Web.Routing; 8 | 9 | namespace graph_tutorial 10 | { 11 | public class MvcApplication : System.Web.HttpApplication 12 | { 13 | protected void Application_Start() 14 | { 15 | AreaRegistration.RegisterAllAreas(); 16 | FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 17 | RouteConfig.RegisterRoutes(RouteTable.Routes); 18 | BundleConfig.RegisterBundles(BundleTable.Bundles); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Models/Alert.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | namespace graph_tutorial.Models 5 | { 6 | // Used to flash error messages in the app's views. 7 | public class Alert 8 | { 9 | public const string AlertKey = "TempDataAlerts"; 10 | public string Message { get; set; } 11 | public string Debug { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("graph_tutorial")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("graph_tutorial")] 13 | [assembly: AssemblyCopyright("Copyright © 2022")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("78062d3f-74c7-42ac-8885-7fe5f61a094c")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/methods/destroy.js: -------------------------------------------------------------------------------- 1 | import isModifierEnabled from '../utils/isModifierEnabled'; 2 | import getSupportedPropertyName from '../utils/getSupportedPropertyName'; 3 | 4 | /** 5 | * Destroys the popper. 6 | * @method 7 | * @memberof Popper 8 | */ 9 | export default function destroy() { 10 | this.state.isDestroyed = true; 11 | 12 | // touch DOM only if `applyStyle` modifier is enabled 13 | if (isModifierEnabled(this.modifiers, 'applyStyle')) { 14 | this.popper.removeAttribute('x-placement'); 15 | this.popper.style.position = ''; 16 | this.popper.style.top = ''; 17 | this.popper.style.left = ''; 18 | this.popper.style.right = ''; 19 | this.popper.style.bottom = ''; 20 | this.popper.style.willChange = ''; 21 | this.popper.style[getSupportedPropertyName('transform')] = ''; 22 | } 23 | 24 | this.disableEventListeners(); 25 | 26 | // remove the popper if user explicitly asked for the deletion on destroy 27 | // do not use `remove` because IE11 doesn't support it 28 | if (this.options.removeOnDestroy) { 29 | this.popper.parentNode.removeChild(this.popper); 30 | } 31 | return this; 32 | } 33 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/methods/disableEventListeners.js: -------------------------------------------------------------------------------- 1 | import removeEventListeners from '../utils/removeEventListeners'; 2 | 3 | /** 4 | * It will remove resize/scroll events and won't recalculate popper position 5 | * when they are triggered. It also won't trigger `onUpdate` callback anymore, 6 | * unless you call `update` method manually. 7 | * @method 8 | * @memberof Popper 9 | */ 10 | export default function disableEventListeners() { 11 | if (this.state.eventsEnabled) { 12 | cancelAnimationFrame(this.scheduleUpdate); 13 | this.state = removeEventListeners(this.reference, this.state); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/methods/enableEventListeners.js: -------------------------------------------------------------------------------- 1 | import setupEventListeners from '../utils/setupEventListeners'; 2 | 3 | /** 4 | * It will add resize/scroll events and start recalculating 5 | * position of the popper element when they are triggered. 6 | * @method 7 | * @memberof Popper 8 | */ 9 | export default function enableEventListeners() { 10 | if (!this.state.eventsEnabled) { 11 | this.state = setupEventListeners( 12 | this.reference, 13 | this.options, 14 | this.state, 15 | this.scheduleUpdate 16 | ); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/methods/placements.js: -------------------------------------------------------------------------------- 1 | /** 2 | * List of accepted placements to use as values of the `placement` option.
3 | * Valid placements are: 4 | * - `auto` 5 | * - `top` 6 | * - `right` 7 | * - `bottom` 8 | * - `left` 9 | * 10 | * Each placement can have a variation from this list: 11 | * - `-start` 12 | * - `-end` 13 | * 14 | * Variations are interpreted easily if you think of them as the left to right 15 | * written languages. Horizontally (`top` and `bottom`), `start` is left and `end` 16 | * is right.
17 | * Vertically (`left` and `right`), `start` is top and `end` is bottom. 18 | * 19 | * Some valid examples are: 20 | * - `top-end` (on top of reference, right aligned) 21 | * - `right-start` (on right of reference, top aligned) 22 | * - `bottom` (on bottom, centered) 23 | * - `auto-end` (on the side with more space available, alignment depends by placement) 24 | * 25 | * @static 26 | * @type {Array} 27 | * @enum {String} 28 | * @readonly 29 | * @method placements 30 | * @memberof Popper 31 | */ 32 | export default [ 33 | 'auto-start', 34 | 'auto', 35 | 'auto-end', 36 | 'top-start', 37 | 'top', 38 | 'top-end', 39 | 'right-start', 40 | 'right', 41 | 'right-end', 42 | 'bottom-end', 43 | 'bottom', 44 | 'bottom-start', 45 | 'left-end', 46 | 'left', 47 | 'left-start', 48 | ]; 49 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/modifiers/hide.js: -------------------------------------------------------------------------------- 1 | import isModifierRequired from '../utils/isModifierRequired'; 2 | import find from '../utils/find'; 3 | 4 | /** 5 | * @function 6 | * @memberof Modifiers 7 | * @argument {Object} data - The data object generated by update method 8 | * @argument {Object} options - Modifiers configuration and options 9 | * @returns {Object} The data object, properly modified 10 | */ 11 | export default function hide(data) { 12 | if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) { 13 | return data; 14 | } 15 | 16 | const refRect = data.offsets.reference; 17 | const bound = find( 18 | data.instance.modifiers, 19 | modifier => modifier.name === 'preventOverflow' 20 | ).boundaries; 21 | 22 | if ( 23 | refRect.bottom < bound.top || 24 | refRect.left > bound.right || 25 | refRect.top > bound.bottom || 26 | refRect.right < bound.left 27 | ) { 28 | // Avoid unnecessary DOM access if visibility hasn't changed 29 | if (data.hide === true) { 30 | return data; 31 | } 32 | 33 | data.hide = true; 34 | data.attributes['x-out-of-boundaries'] = ''; 35 | } else { 36 | // Avoid unnecessary DOM access if visibility hasn't changed 37 | if (data.hide === false) { 38 | return data; 39 | } 40 | 41 | data.hide = false; 42 | data.attributes['x-out-of-boundaries'] = false; 43 | } 44 | 45 | return data; 46 | } 47 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/modifiers/inner.js: -------------------------------------------------------------------------------- 1 | import getClientRect from '../utils/getClientRect'; 2 | import getOppositePlacement from '../utils/getOppositePlacement'; 3 | 4 | /** 5 | * @function 6 | * @memberof Modifiers 7 | * @argument {Object} data - The data object generated by `update` method 8 | * @argument {Object} options - Modifiers configuration and options 9 | * @returns {Object} The data object, properly modified 10 | */ 11 | export default function inner(data) { 12 | const placement = data.placement; 13 | const basePlacement = placement.split('-')[0]; 14 | const { popper, reference } = data.offsets; 15 | const isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1; 16 | 17 | const subtractLength = ['top', 'left'].indexOf(basePlacement) === -1; 18 | 19 | popper[isHoriz ? 'left' : 'top'] = 20 | reference[basePlacement] - 21 | (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0); 22 | 23 | data.placement = getOppositePlacement(placement); 24 | data.offsets.popper = getClientRect(popper); 25 | 26 | return data; 27 | } 28 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/modifiers/keepTogether.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @function 3 | * @memberof Modifiers 4 | * @argument {Object} data - The data object generated by update method 5 | * @argument {Object} options - Modifiers configuration and options 6 | * @returns {Object} The data object, properly modified 7 | */ 8 | export default function keepTogether(data) { 9 | const { popper, reference } = data.offsets; 10 | const placement = data.placement.split('-')[0]; 11 | const floor = Math.floor; 12 | const isVertical = ['top', 'bottom'].indexOf(placement) !== -1; 13 | const side = isVertical ? 'right' : 'bottom'; 14 | const opSide = isVertical ? 'left' : 'top'; 15 | const measurement = isVertical ? 'width' : 'height'; 16 | 17 | if (popper[side] < floor(reference[opSide])) { 18 | data.offsets.popper[opSide] = 19 | floor(reference[opSide]) - popper[measurement]; 20 | } 21 | if (popper[opSide] > floor(reference[side])) { 22 | data.offsets.popper[opSide] = floor(reference[side]); 23 | } 24 | 25 | return data; 26 | } 27 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/modifiers/shift.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @function 3 | * @memberof Modifiers 4 | * @argument {Object} data - The data object generated by `update` method 5 | * @argument {Object} options - Modifiers configuration and options 6 | * @returns {Object} The data object, properly modified 7 | */ 8 | export default function shift(data) { 9 | const placement = data.placement; 10 | const basePlacement = placement.split('-')[0]; 11 | const shiftvariation = placement.split('-')[1]; 12 | 13 | // if shift shiftvariation is specified, run the modifier 14 | if (shiftvariation) { 15 | const { reference, popper } = data.offsets; 16 | const isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1; 17 | const side = isVertical ? 'left' : 'top'; 18 | const measurement = isVertical ? 'width' : 'height'; 19 | 20 | const shiftOffsets = { 21 | start: { [side]: reference[side] }, 22 | end: { 23 | [side]: reference[side] + reference[measurement] - popper[measurement], 24 | }, 25 | }; 26 | 27 | data.offsets.popper = { ...popper, ...shiftOffsets[shiftvariation] }; 28 | } 29 | 30 | return data; 31 | } 32 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/clockwise.js: -------------------------------------------------------------------------------- 1 | import placements from '../methods/placements'; 2 | 3 | // Get rid of `auto` `auto-start` and `auto-end` 4 | const validPlacements = placements.slice(3); 5 | 6 | /** 7 | * Given an initial placement, returns all the subsequent placements 8 | * clockwise (or counter-clockwise). 9 | * 10 | * @method 11 | * @memberof Popper.Utils 12 | * @argument {String} placement - A valid placement (it accepts variations) 13 | * @argument {Boolean} counter - Set to true to walk the placements counterclockwise 14 | * @returns {Array} placements including their variations 15 | */ 16 | export default function clockwise(placement, counter = false) { 17 | const index = validPlacements.indexOf(placement); 18 | const arr = validPlacements 19 | .slice(index + 1) 20 | .concat(validPlacements.slice(0, index)); 21 | return counter ? arr.reverse() : arr; 22 | } 23 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/computeAutoPlacement.js: -------------------------------------------------------------------------------- 1 | import getBoundaries from '../utils/getBoundaries'; 2 | 3 | function getArea({ width, height }) { 4 | return width * height; 5 | } 6 | 7 | /** 8 | * Utility used to transform the `auto` placement to the placement with more 9 | * available space. 10 | * @method 11 | * @memberof Popper.Utils 12 | * @argument {Object} data - The data object generated by update method 13 | * @argument {Object} options - Modifiers configuration and options 14 | * @returns {Object} The data object, properly modified 15 | */ 16 | export default function computeAutoPlacement( 17 | placement, 18 | refRect, 19 | popper, 20 | reference, 21 | boundariesElement, 22 | padding = 0 23 | ) { 24 | if (placement.indexOf('auto') === -1) { 25 | return placement; 26 | } 27 | 28 | const boundaries = getBoundaries( 29 | popper, 30 | reference, 31 | padding, 32 | boundariesElement 33 | ); 34 | 35 | const rects = { 36 | top: { 37 | width: boundaries.width, 38 | height: refRect.top - boundaries.top, 39 | }, 40 | right: { 41 | width: boundaries.right - refRect.right, 42 | height: boundaries.height, 43 | }, 44 | bottom: { 45 | width: boundaries.width, 46 | height: boundaries.bottom - refRect.bottom, 47 | }, 48 | left: { 49 | width: refRect.left - boundaries.left, 50 | height: boundaries.height, 51 | }, 52 | }; 53 | 54 | const sortedAreas = Object.keys(rects) 55 | .map(key => ({ 56 | key, 57 | ...rects[key], 58 | area: getArea(rects[key]), 59 | })) 60 | .sort((a, b) => b.area - a.area); 61 | 62 | const filteredAreas = sortedAreas.filter( 63 | ({ width, height }) => 64 | width >= popper.clientWidth && height >= popper.clientHeight 65 | ); 66 | 67 | const computedPlacement = filteredAreas.length > 0 68 | ? filteredAreas[0].key 69 | : sortedAreas[0].key; 70 | 71 | const variation = placement.split('-')[1]; 72 | 73 | return computedPlacement + (variation ? `-${variation}` : ''); 74 | } 75 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/debounce.js: -------------------------------------------------------------------------------- 1 | import isBrowser from './isBrowser'; 2 | 3 | const timeoutDuration = (function(){ 4 | const longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox']; 5 | for (let i = 0; i < longerTimeoutBrowsers.length; i += 1) { 6 | if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) { 7 | return 1; 8 | } 9 | } 10 | return 0; 11 | }()); 12 | 13 | export function microtaskDebounce(fn) { 14 | let called = false 15 | return () => { 16 | if (called) { 17 | return 18 | } 19 | called = true 20 | window.Promise.resolve().then(() => { 21 | called = false 22 | fn() 23 | }) 24 | } 25 | } 26 | 27 | export function taskDebounce(fn) { 28 | let scheduled = false; 29 | return () => { 30 | if (!scheduled) { 31 | scheduled = true; 32 | setTimeout(() => { 33 | scheduled = false; 34 | fn(); 35 | }, timeoutDuration); 36 | } 37 | }; 38 | } 39 | 40 | const supportsMicroTasks = isBrowser && window.Promise 41 | 42 | 43 | /** 44 | * Create a debounced version of a method, that's asynchronously deferred 45 | * but called in the minimum time possible. 46 | * 47 | * @method 48 | * @memberof Popper.Utils 49 | * @argument {Function} fn 50 | * @returns {Function} 51 | */ 52 | export default (supportsMicroTasks 53 | ? microtaskDebounce 54 | : taskDebounce); 55 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/find.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Mimics the `find` method of Array 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Array} arr 6 | * @argument prop 7 | * @argument value 8 | * @returns index or -1 9 | */ 10 | export default function find(arr, check) { 11 | // use native find if supported 12 | if (Array.prototype.find) { 13 | return arr.find(check); 14 | } 15 | 16 | // use `filter` to obtain the same behavior of `find` 17 | return arr.filter(check)[0]; 18 | } 19 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/findCommonOffsetParent.js: -------------------------------------------------------------------------------- 1 | import isOffsetContainer from './isOffsetContainer'; 2 | import getRoot from './getRoot'; 3 | import getOffsetParent from './getOffsetParent'; 4 | 5 | /** 6 | * Finds the offset parent common to the two provided nodes 7 | * @method 8 | * @memberof Popper.Utils 9 | * @argument {Element} element1 10 | * @argument {Element} element2 11 | * @returns {Element} common offset parent 12 | */ 13 | export default function findCommonOffsetParent(element1, element2) { 14 | // This check is needed to avoid errors in case one of the elements isn't defined for any reason 15 | if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) { 16 | return document.documentElement; 17 | } 18 | 19 | // Here we make sure to give as "start" the element that comes first in the DOM 20 | const order = 21 | element1.compareDocumentPosition(element2) & 22 | Node.DOCUMENT_POSITION_FOLLOWING; 23 | const start = order ? element1 : element2; 24 | const end = order ? element2 : element1; 25 | 26 | // Get common ancestor container 27 | const range = document.createRange(); 28 | range.setStart(start, 0); 29 | range.setEnd(end, 0); 30 | const { commonAncestorContainer } = range; 31 | 32 | // Both nodes are inside #document 33 | if ( 34 | (element1 !== commonAncestorContainer && 35 | element2 !== commonAncestorContainer) || 36 | start.contains(end) 37 | ) { 38 | if (isOffsetContainer(commonAncestorContainer)) { 39 | return commonAncestorContainer; 40 | } 41 | 42 | return getOffsetParent(commonAncestorContainer); 43 | } 44 | 45 | // one of the nodes is inside shadowDOM, find which one 46 | const element1root = getRoot(element1); 47 | if (element1root.host) { 48 | return findCommonOffsetParent(element1root.host, element2); 49 | } else { 50 | return findCommonOffsetParent(element1, getRoot(element2).host); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/findIndex.js: -------------------------------------------------------------------------------- 1 | import find from './find'; 2 | 3 | /** 4 | * Return the index of the matching object 5 | * @method 6 | * @memberof Popper.Utils 7 | * @argument {Array} arr 8 | * @argument prop 9 | * @argument value 10 | * @returns index or -1 11 | */ 12 | export default function findIndex(arr, prop, value) { 13 | // use native findIndex if supported 14 | if (Array.prototype.findIndex) { 15 | return arr.findIndex(cur => cur[prop] === value); 16 | } 17 | 18 | // use `find` + `indexOf` if `findIndex` isn't supported 19 | const match = find(arr, obj => obj[prop] === value); 20 | return arr.indexOf(match); 21 | } 22 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/getBordersSize.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Helper to detect borders of a given element 3 | * @method 4 | * @memberof Popper.Utils 5 | * @param {CSSStyleDeclaration} styles 6 | * Result of `getStyleComputedProperty` on the given element 7 | * @param {String} axis - `x` or `y` 8 | * @return {number} borders - The borders size of the given axis 9 | */ 10 | 11 | export default function getBordersSize(styles, axis) { 12 | const sideA = axis === 'x' ? 'Left' : 'Top'; 13 | const sideB = sideA === 'Left' ? 'Right' : 'Bottom'; 14 | 15 | return ( 16 | parseFloat(styles[`border${sideA}Width`]) + 17 | parseFloat(styles[`border${sideB}Width`]) 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/getClientRect.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Given element offsets, generate an output similar to getBoundingClientRect 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Object} offsets 6 | * @returns {Object} ClientRect like output 7 | */ 8 | export default function getClientRect(offsets) { 9 | return { 10 | ...offsets, 11 | right: offsets.left + offsets.width, 12 | bottom: offsets.top + offsets.height, 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/getFixedPositionOffsetParent.js: -------------------------------------------------------------------------------- 1 | import getStyleComputedProperty from './getStyleComputedProperty'; 2 | import isIE from './isIE'; 3 | /** 4 | * Finds the first parent of an element that has a transformed property defined 5 | * @method 6 | * @memberof Popper.Utils 7 | * @argument {Element} element 8 | * @returns {Element} first transformed parent or documentElement 9 | */ 10 | 11 | export default function getFixedPositionOffsetParent(element) { 12 | // This check is needed to avoid errors in case one of the elements isn't defined for any reason 13 | if (!element || !element.parentElement || isIE()) { 14 | return document.documentElement; 15 | } 16 | let el = element.parentElement; 17 | while (el && getStyleComputedProperty(el, 'transform') === 'none') { 18 | el = el.parentElement; 19 | } 20 | return el || document.documentElement; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/getOffsetParent.js: -------------------------------------------------------------------------------- 1 | import getStyleComputedProperty from './getStyleComputedProperty'; 2 | import isIE from './isIE'; 3 | /** 4 | * Returns the offset parent of the given element 5 | * @method 6 | * @memberof Popper.Utils 7 | * @argument {Element} element 8 | * @returns {Element} offset parent 9 | */ 10 | export default function getOffsetParent(element) { 11 | if (!element) { 12 | return document.documentElement; 13 | } 14 | 15 | const noOffsetParent = isIE(10) ? document.body : null; 16 | 17 | // NOTE: 1 DOM access here 18 | let offsetParent = element.offsetParent || null; 19 | // Skip hidden elements which don't have an offsetParent 20 | while (offsetParent === noOffsetParent && element.nextElementSibling) { 21 | offsetParent = (element = element.nextElementSibling).offsetParent; 22 | } 23 | 24 | const nodeName = offsetParent && offsetParent.nodeName; 25 | 26 | if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') { 27 | return element ? element.ownerDocument.documentElement : document.documentElement; 28 | } 29 | 30 | // .offsetParent will return the closest TH, TD or TABLE in case 31 | // no offsetParent is present, I hate this job... 32 | if ( 33 | ['TH', 'TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && 34 | getStyleComputedProperty(offsetParent, 'position') === 'static' 35 | ) { 36 | return getOffsetParent(offsetParent); 37 | } 38 | 39 | return offsetParent; 40 | } 41 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/getOffsetRect.js: -------------------------------------------------------------------------------- 1 | import getWindowSizes from './getWindowSizes'; 2 | import getClientRect from './getClientRect'; 3 | 4 | /** 5 | * Get the position of the given element, relative to its offset parent 6 | * @method 7 | * @memberof Popper.Utils 8 | * @param {Element} element 9 | * @return {Object} position - Coordinates of the element and its `scrollTop` 10 | */ 11 | export default function getOffsetRect(element) { 12 | let elementRect; 13 | if (element.nodeName === 'HTML') { 14 | const { width, height } = getWindowSizes(element.ownerDocument); 15 | elementRect = { 16 | width, 17 | height, 18 | left: 0, 19 | top: 0, 20 | }; 21 | } else { 22 | elementRect = { 23 | width: element.offsetWidth, 24 | height: element.offsetHeight, 25 | left: element.offsetLeft, 26 | top: element.offsetTop, 27 | }; 28 | } 29 | 30 | // position 31 | return getClientRect(elementRect); 32 | } 33 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/getOppositePlacement.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the opposite placement of the given one 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {String} placement 6 | * @returns {String} flipped placement 7 | */ 8 | export default function getOppositePlacement(placement) { 9 | const hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' }; 10 | return placement.replace(/left|right|bottom|top/g, matched => hash[matched]); 11 | } 12 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/getOppositeVariation.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the opposite placement variation of the given one 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {String} placement variation 6 | * @returns {String} flipped placement variation 7 | */ 8 | export default function getOppositeVariation(variation) { 9 | if (variation === 'end') { 10 | return 'start'; 11 | } else if (variation === 'start') { 12 | return 'end'; 13 | } 14 | return variation; 15 | } 16 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/getOuterSizes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the outer sizes of the given element (offset size + margins) 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Element} element 6 | * @returns {Object} object containing width and height properties 7 | */ 8 | export default function getOuterSizes(element) { 9 | const window = element.ownerDocument.defaultView; 10 | const styles = window.getComputedStyle(element); 11 | const x = parseFloat(styles.marginTop || 0) + parseFloat(styles.marginBottom || 0); 12 | const y = parseFloat(styles.marginLeft || 0) + parseFloat(styles.marginRight || 0); 13 | const result = { 14 | width: element.offsetWidth + y, 15 | height: element.offsetHeight + x, 16 | }; 17 | return result; 18 | } 19 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/getParentNode.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns the parentNode or the host of the element 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Element} element 6 | * @returns {Element} parent 7 | */ 8 | export default function getParentNode(element) { 9 | if (element.nodeName === 'HTML') { 10 | return element; 11 | } 12 | return element.parentNode || element.host; 13 | } 14 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/getPopperOffsets.js: -------------------------------------------------------------------------------- 1 | import getOuterSizes from './getOuterSizes'; 2 | import getOppositePlacement from './getOppositePlacement'; 3 | 4 | /** 5 | * Get offsets to the popper 6 | * @method 7 | * @memberof Popper.Utils 8 | * @param {Object} position - CSS position the Popper will get applied 9 | * @param {HTMLElement} popper - the popper element 10 | * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this) 11 | * @param {String} placement - one of the valid placement options 12 | * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper 13 | */ 14 | export default function getPopperOffsets(popper, referenceOffsets, placement) { 15 | placement = placement.split('-')[0]; 16 | 17 | // Get popper node sizes 18 | const popperRect = getOuterSizes(popper); 19 | 20 | // Add position, width and height to our offsets object 21 | const popperOffsets = { 22 | width: popperRect.width, 23 | height: popperRect.height, 24 | }; 25 | 26 | // depending by the popper placement we have to compute its offsets slightly differently 27 | const isHoriz = ['right', 'left'].indexOf(placement) !== -1; 28 | const mainSide = isHoriz ? 'top' : 'left'; 29 | const secondarySide = isHoriz ? 'left' : 'top'; 30 | const measurement = isHoriz ? 'height' : 'width'; 31 | const secondaryMeasurement = !isHoriz ? 'height' : 'width'; 32 | 33 | popperOffsets[mainSide] = 34 | referenceOffsets[mainSide] + 35 | referenceOffsets[measurement] / 2 - 36 | popperRect[measurement] / 2; 37 | if (placement === secondarySide) { 38 | popperOffsets[secondarySide] = 39 | referenceOffsets[secondarySide] - popperRect[secondaryMeasurement]; 40 | } else { 41 | popperOffsets[secondarySide] = 42 | referenceOffsets[getOppositePlacement(secondarySide)]; 43 | } 44 | 45 | return popperOffsets; 46 | } 47 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/getReferenceNode.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns the reference node of the reference object, or the reference object itself. 3 | * @method 4 | * @memberof Popper.Utils 5 | * @param {Element|Object} reference - the reference element (the popper will be relative to this) 6 | * @returns {Element} parent 7 | */ 8 | export default function getReferenceNode(reference) { 9 | return reference && reference.referenceNode ? reference.referenceNode : reference; 10 | } 11 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/getReferenceOffsets.js: -------------------------------------------------------------------------------- 1 | import findCommonOffsetParent from './findCommonOffsetParent'; 2 | import getOffsetRectRelativeToArbitraryNode from './getOffsetRectRelativeToArbitraryNode'; 3 | import getFixedPositionOffsetParent from './getFixedPositionOffsetParent'; 4 | import getReferenceNode from './getReferenceNode'; 5 | 6 | /** 7 | * Get offsets to the reference element 8 | * @method 9 | * @memberof Popper.Utils 10 | * @param {Object} state 11 | * @param {Element} popper - the popper element 12 | * @param {Element} reference - the reference element (the popper will be relative to this) 13 | * @param {Element} fixedPosition - is in fixed position mode 14 | * @returns {Object} An object containing the offsets which will be applied to the popper 15 | */ 16 | export default function getReferenceOffsets(state, popper, reference, fixedPosition = null) { 17 | const commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, getReferenceNode(reference)); 18 | return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition); 19 | } 20 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/getRoot.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Finds the root node (document, shadowDOM root) of the given element 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Element} node 6 | * @returns {Element} root node 7 | */ 8 | export default function getRoot(node) { 9 | if (node.parentNode !== null) { 10 | return getRoot(node.parentNode); 11 | } 12 | 13 | return node; 14 | } 15 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/getRoundedOffsets.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @function 3 | * @memberof Popper.Utils 4 | * @argument {Object} data - The data object generated by `update` method 5 | * @argument {Boolean} shouldRound - If the offsets should be rounded at all 6 | * @returns {Object} The popper's position offsets rounded 7 | * 8 | * The tale of pixel-perfect positioning. It's still not 100% perfect, but as 9 | * good as it can be within reason. 10 | * Discussion here: https://github.com/FezVrasta/popper.js/pull/715 11 | * 12 | * Low DPI screens cause a popper to be blurry if not using full pixels (Safari 13 | * as well on High DPI screens). 14 | * 15 | * Firefox prefers no rounding for positioning and does not have blurriness on 16 | * high DPI screens. 17 | * 18 | * Only horizontal placement and left/right values need to be considered. 19 | */ 20 | export default function getRoundedOffsets(data, shouldRound) { 21 | const { popper, reference } = data.offsets; 22 | const { round, floor } = Math; 23 | const noRound = v => v; 24 | 25 | const referenceWidth = round(reference.width); 26 | const popperWidth = round(popper.width); 27 | 28 | const isVertical = ['left', 'right'].indexOf(data.placement) !== -1; 29 | const isVariation = data.placement.indexOf('-') !== -1; 30 | const sameWidthParity = referenceWidth % 2 === popperWidth % 2; 31 | const bothOddWidth = referenceWidth % 2 === 1 && popperWidth % 2 === 1; 32 | 33 | const horizontalToInteger = !shouldRound 34 | ? noRound 35 | : isVertical || isVariation || sameWidthParity 36 | ? round 37 | : floor; 38 | const verticalToInteger = !shouldRound ? noRound : round; 39 | 40 | return { 41 | left: horizontalToInteger( 42 | bothOddWidth && !isVariation && shouldRound 43 | ? popper.left - 1 44 | : popper.left 45 | ), 46 | top: verticalToInteger(popper.top), 47 | bottom: verticalToInteger(popper.bottom), 48 | right: horizontalToInteger(popper.right), 49 | }; 50 | } 51 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/getScroll.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Gets the scroll value of the given element in the given side (top and left) 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Element} element 6 | * @argument {String} side `top` or `left` 7 | * @returns {number} amount of scrolled pixels 8 | */ 9 | export default function getScroll(element, side = 'top') { 10 | const upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft'; 11 | const nodeName = element.nodeName; 12 | 13 | if (nodeName === 'BODY' || nodeName === 'HTML') { 14 | const html = element.ownerDocument.documentElement; 15 | const scrollingElement = element.ownerDocument.scrollingElement || html; 16 | return scrollingElement[upperSide]; 17 | } 18 | 19 | return element[upperSide]; 20 | } 21 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/getScrollParent.js: -------------------------------------------------------------------------------- 1 | import getStyleComputedProperty from './getStyleComputedProperty'; 2 | import getParentNode from './getParentNode'; 3 | 4 | /** 5 | * Returns the scrolling parent of the given element 6 | * @method 7 | * @memberof Popper.Utils 8 | * @argument {Element} element 9 | * @returns {Element} scroll parent 10 | */ 11 | export default function getScrollParent(element) { 12 | // Return body, `getScroll` will take care to get the correct `scrollTop` from it 13 | if (!element) { 14 | return document.body 15 | } 16 | 17 | switch (element.nodeName) { 18 | case 'HTML': 19 | case 'BODY': 20 | return element.ownerDocument.body 21 | case '#document': 22 | return element.body 23 | } 24 | 25 | // Firefox want us to check `-x` and `-y` variations as well 26 | const { overflow, overflowX, overflowY } = getStyleComputedProperty(element); 27 | if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) { 28 | return element; 29 | } 30 | 31 | return getScrollParent(getParentNode(element)); 32 | } 33 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/getStyleComputedProperty.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get CSS computed property of the given element 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Eement} element 6 | * @argument {String} property 7 | */ 8 | export default function getStyleComputedProperty(element, property) { 9 | if (element.nodeType !== 1) { 10 | return []; 11 | } 12 | // NOTE: 1 DOM access here 13 | const window = element.ownerDocument.defaultView; 14 | const css = window.getComputedStyle(element, null); 15 | return property ? css[property] : css; 16 | } 17 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/getSupportedPropertyName.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the prefixed supported property name 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {String} property (camelCase) 6 | * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix) 7 | */ 8 | export default function getSupportedPropertyName(property) { 9 | const prefixes = [false, 'ms', 'Webkit', 'Moz', 'O']; 10 | const upperProp = property.charAt(0).toUpperCase() + property.slice(1); 11 | 12 | for (let i = 0; i < prefixes.length; i++) { 13 | const prefix = prefixes[i]; 14 | const toCheck = prefix ? `${prefix}${upperProp}` : property; 15 | if (typeof document.body.style[toCheck] !== 'undefined') { 16 | return toCheck; 17 | } 18 | } 19 | return null; 20 | } 21 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/getViewportOffsetRectRelativeToArtbitraryNode.js: -------------------------------------------------------------------------------- 1 | import getOffsetRectRelativeToArbitraryNode from './getOffsetRectRelativeToArbitraryNode'; 2 | import getScroll from './getScroll'; 3 | import getClientRect from './getClientRect'; 4 | 5 | export default function getViewportOffsetRectRelativeToArtbitraryNode(element, excludeScroll = false) { 6 | const html = element.ownerDocument.documentElement; 7 | const relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html); 8 | const width = Math.max(html.clientWidth, window.innerWidth || 0); 9 | const height = Math.max(html.clientHeight, window.innerHeight || 0); 10 | 11 | const scrollTop = !excludeScroll ? getScroll(html) : 0; 12 | const scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0; 13 | 14 | const offset = { 15 | top: scrollTop - relativeOffset.top + relativeOffset.marginTop, 16 | left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft, 17 | width, 18 | height, 19 | }; 20 | 21 | return getClientRect(offset); 22 | } 23 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/getWindow.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the window associated with the element 3 | * @argument {Element} element 4 | * @returns {Window} 5 | */ 6 | export default function getWindow(element) { 7 | const ownerDocument = element.ownerDocument; 8 | return ownerDocument ? ownerDocument.defaultView : window; 9 | } 10 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/getWindowSizes.js: -------------------------------------------------------------------------------- 1 | import isIE from './isIE'; 2 | 3 | function getSize(axis, body, html, computedStyle) { 4 | return Math.max( 5 | body[`offset${axis}`], 6 | body[`scroll${axis}`], 7 | html[`client${axis}`], 8 | html[`offset${axis}`], 9 | html[`scroll${axis}`], 10 | isIE(10) 11 | ? (parseInt(html[`offset${axis}`]) + 12 | parseInt(computedStyle[`margin${axis === 'Height' ? 'Top' : 'Left'}`]) + 13 | parseInt(computedStyle[`margin${axis === 'Height' ? 'Bottom' : 'Right'}`])) 14 | : 0 15 | ); 16 | } 17 | 18 | export default function getWindowSizes(document) { 19 | const body = document.body; 20 | const html = document.documentElement; 21 | const computedStyle = isIE(10) && getComputedStyle(html); 22 | 23 | return { 24 | height: getSize('Height', body, html, computedStyle), 25 | width: getSize('Width', body, html, computedStyle), 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/includeScroll.js: -------------------------------------------------------------------------------- 1 | import getScroll from './getScroll'; 2 | 3 | /* 4 | * Sum or subtract the element scroll values (left and top) from a given rect object 5 | * @method 6 | * @memberof Popper.Utils 7 | * @param {Object} rect - Rect object you want to change 8 | * @param {HTMLElement} element - The element from the function reads the scroll values 9 | * @param {Boolean} subtract - set to true if you want to subtract the scroll values 10 | * @return {Object} rect - The modifier rect object 11 | */ 12 | export default function includeScroll(rect, element, subtract = false) { 13 | const scrollTop = getScroll(element, 'top'); 14 | const scrollLeft = getScroll(element, 'left'); 15 | const modifier = subtract ? -1 : 1; 16 | rect.top += scrollTop * modifier; 17 | rect.bottom += scrollTop * modifier; 18 | rect.left += scrollLeft * modifier; 19 | rect.right += scrollLeft * modifier; 20 | return rect; 21 | } 22 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/isBrowser.js: -------------------------------------------------------------------------------- 1 | export default typeof window !== 'undefined' && typeof document !== 'undefined' && typeof navigator !== 'undefined'; 2 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/isFixed.js: -------------------------------------------------------------------------------- 1 | import getStyleComputedProperty from './getStyleComputedProperty'; 2 | import getParentNode from './getParentNode'; 3 | 4 | /** 5 | * Check if the given element is fixed or is inside a fixed parent 6 | * @method 7 | * @memberof Popper.Utils 8 | * @argument {Element} element 9 | * @argument {Element} customContainer 10 | * @returns {Boolean} answer to "isFixed?" 11 | */ 12 | export default function isFixed(element) { 13 | const nodeName = element.nodeName; 14 | if (nodeName === 'BODY' || nodeName === 'HTML') { 15 | return false; 16 | } 17 | if (getStyleComputedProperty(element, 'position') === 'fixed') { 18 | return true; 19 | } 20 | const parentNode = getParentNode(element); 21 | if (!parentNode) { 22 | return false; 23 | } 24 | return isFixed(parentNode); 25 | } 26 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/isFunction.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Check if the given variable is a function 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Any} functionToCheck - variable to check 6 | * @returns {Boolean} answer to: is a function? 7 | */ 8 | export default function isFunction(functionToCheck) { 9 | const getType = {}; 10 | return ( 11 | functionToCheck && 12 | getType.toString.call(functionToCheck) === '[object Function]' 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/isIE.js: -------------------------------------------------------------------------------- 1 | import isBrowser from './isBrowser'; 2 | 3 | const isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode); 4 | const isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent); 5 | 6 | /** 7 | * Determines if the browser is Internet Explorer 8 | * @method 9 | * @memberof Popper.Utils 10 | * @param {Number} version to check 11 | * @returns {Boolean} isIE 12 | */ 13 | export default function isIE(version) { 14 | if (version === 11) { 15 | return isIE11; 16 | } 17 | if (version === 10) { 18 | return isIE10; 19 | } 20 | return isIE11 || isIE10; 21 | } 22 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/isModifierEnabled.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Helper used to know if the given modifier is enabled. 3 | * @method 4 | * @memberof Popper.Utils 5 | * @returns {Boolean} 6 | */ 7 | export default function isModifierEnabled(modifiers, modifierName) { 8 | return modifiers.some( 9 | ({ name, enabled }) => enabled && name === modifierName 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/isModifierRequired.js: -------------------------------------------------------------------------------- 1 | import find from './find'; 2 | 3 | /** 4 | * Helper used to know if the given modifier depends from another one.
5 | * It checks if the needed modifier is listed and enabled. 6 | * @method 7 | * @memberof Popper.Utils 8 | * @param {Array} modifiers - list of modifiers 9 | * @param {String} requestingName - name of requesting modifier 10 | * @param {String} requestedName - name of requested modifier 11 | * @returns {Boolean} 12 | */ 13 | export default function isModifierRequired( 14 | modifiers, 15 | requestingName, 16 | requestedName 17 | ) { 18 | const requesting = find(modifiers, ({ name }) => name === requestingName); 19 | 20 | const isRequired = 21 | !!requesting && 22 | modifiers.some(modifier => { 23 | return ( 24 | modifier.name === requestedName && 25 | modifier.enabled && 26 | modifier.order < requesting.order 27 | ); 28 | }); 29 | 30 | if (!isRequired) { 31 | const requesting = `\`${requestingName}\``; 32 | const requested = `\`${requestedName}\``; 33 | console.warn( 34 | `${requested} modifier is required by ${requesting} modifier in order to work, be sure to include it before ${requesting}!` 35 | ); 36 | } 37 | return isRequired; 38 | } 39 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/isNumeric.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Tells if a given input is a number 3 | * @method 4 | * @memberof Popper.Utils 5 | * @param {*} input to check 6 | * @return {Boolean} 7 | */ 8 | export default function isNumeric(n) { 9 | return n !== '' && !isNaN(parseFloat(n)) && isFinite(n); 10 | } 11 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/isOffsetContainer.js: -------------------------------------------------------------------------------- 1 | import getOffsetParent from './getOffsetParent'; 2 | 3 | export default function isOffsetContainer(element) { 4 | const { nodeName } = element; 5 | if (nodeName === 'BODY') { 6 | return false; 7 | } 8 | return ( 9 | nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/removeEventListeners.js: -------------------------------------------------------------------------------- 1 | import getWindow from './getWindow'; 2 | 3 | /** 4 | * Remove event listeners used to update the popper position 5 | * @method 6 | * @memberof Popper.Utils 7 | * @private 8 | */ 9 | export default function removeEventListeners(reference, state) { 10 | // Remove resize event listener on window 11 | getWindow(reference).removeEventListener('resize', state.updateBound); 12 | 13 | // Remove scroll event listener on scroll parents 14 | state.scrollParents.forEach(target => { 15 | target.removeEventListener('scroll', state.updateBound); 16 | }); 17 | 18 | // Reset state 19 | state.updateBound = null; 20 | state.scrollParents = []; 21 | state.scrollElement = null; 22 | state.eventsEnabled = false; 23 | return state; 24 | } 25 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/runModifiers.js: -------------------------------------------------------------------------------- 1 | import isFunction from './isFunction'; 2 | import findIndex from './findIndex'; 3 | import getClientRect from '../utils/getClientRect'; 4 | 5 | /** 6 | * Loop trough the list of modifiers and run them in order, 7 | * each of them will then edit the data object. 8 | * @method 9 | * @memberof Popper.Utils 10 | * @param {dataObject} data 11 | * @param {Array} modifiers 12 | * @param {String} ends - Optional modifier name used as stopper 13 | * @returns {dataObject} 14 | */ 15 | export default function runModifiers(modifiers, data, ends) { 16 | const modifiersToRun = ends === undefined 17 | ? modifiers 18 | : modifiers.slice(0, findIndex(modifiers, 'name', ends)); 19 | 20 | modifiersToRun.forEach(modifier => { 21 | if (modifier['function']) { // eslint-disable-line dot-notation 22 | console.warn('`modifier.function` is deprecated, use `modifier.fn`!'); 23 | } 24 | const fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation 25 | if (modifier.enabled && isFunction(fn)) { 26 | // Add properties to offsets to make them a complete clientRect object 27 | // we do this before each modifier to make sure the previous one doesn't 28 | // mess with these values 29 | data.offsets.popper = getClientRect(data.offsets.popper); 30 | data.offsets.reference = getClientRect(data.offsets.reference); 31 | 32 | data = fn(data, modifier); 33 | } 34 | }); 35 | 36 | return data; 37 | } 38 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/setAttributes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Set the attributes to the given popper 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Element} element - Element to apply the attributes to 6 | * @argument {Object} styles 7 | * Object with a list of properties and values which will be applied to the element 8 | */ 9 | export default function setAttributes(element, attributes) { 10 | Object.keys(attributes).forEach(function(prop) { 11 | const value = attributes[prop]; 12 | if (value !== false) { 13 | element.setAttribute(prop, attributes[prop]); 14 | } else { 15 | element.removeAttribute(prop); 16 | } 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/setStyles.js: -------------------------------------------------------------------------------- 1 | import isNumeric from './isNumeric'; 2 | 3 | /** 4 | * Set the style to the given popper 5 | * @method 6 | * @memberof Popper.Utils 7 | * @argument {Element} element - Element to apply the style to 8 | * @argument {Object} styles 9 | * Object with a list of properties and values which will be applied to the element 10 | */ 11 | export default function setStyles(element, styles) { 12 | Object.keys(styles).forEach(prop => { 13 | let unit = ''; 14 | // add unit if the value is numeric and is one of the following 15 | if ( 16 | ['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== 17 | -1 && 18 | isNumeric(styles[prop]) 19 | ) { 20 | unit = 'px'; 21 | } 22 | element.style[prop] = styles[prop] + unit; 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Scripts/src/utils/setupEventListeners.js: -------------------------------------------------------------------------------- 1 | import getScrollParent from './getScrollParent'; 2 | import getWindow from './getWindow'; 3 | 4 | function attachToScrollParents(scrollParent, event, callback, scrollParents) { 5 | const isBody = scrollParent.nodeName === 'BODY'; 6 | const target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent; 7 | target.addEventListener(event, callback, { passive: true }); 8 | 9 | if (!isBody) { 10 | attachToScrollParents( 11 | getScrollParent(target.parentNode), 12 | event, 13 | callback, 14 | scrollParents 15 | ); 16 | } 17 | scrollParents.push(target); 18 | } 19 | 20 | /** 21 | * Setup needed event listeners used to update the popper position 22 | * @method 23 | * @memberof Popper.Utils 24 | * @private 25 | */ 26 | export default function setupEventListeners( 27 | reference, 28 | options, 29 | state, 30 | updateBound 31 | ) { 32 | // Resize event listener on window 33 | state.updateBound = updateBound; 34 | getWindow(reference).addEventListener('resize', state.updateBound, { passive: true }); 35 | 36 | // Scroll event listener on scroll parents 37 | const scrollElement = getScrollParent(reference); 38 | attachToScrollParents( 39 | scrollElement, 40 | 'scroll', 41 | state.updateBound, 42 | state.scrollParents 43 | ); 44 | state.scrollElement = scrollElement; 45 | state.eventsEnabled = true; 46 | 47 | return state; 48 | } 49 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Startup.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | using Microsoft.Owin; 5 | using Owin; 6 | using System; 7 | using System.Threading.Tasks; 8 | 9 | [assembly: OwinStartup(typeof(graph_tutorial.Startup))] 10 | 11 | namespace graph_tutorial 12 | { 13 | public class Startup 14 | { 15 | public void Configuration(IAppBuilder app) 16 | { 17 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=316888 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "About"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

6 | 7 |

Use this area to provide additional information.

8 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Views/Home/Contact.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Contact"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

6 | 7 |
8 | One Microsoft Way
9 | Redmond, WA 98052-6399
10 | P: 11 | 425.555.0100 12 |
13 | 14 |
15 | Support: Support@example.com
16 | Marketing: Marketing@example.com 17 |
-------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 |  5 | 6 | @{ 7 | ViewBag.Current = "Home"; 8 | } 9 | 10 |
11 |

ASP.NET Graph Tutorial

12 |

This sample app shows how to use the Microsoft Graph API to access a user's data from ASP.NET

13 | @if (Request.IsAuthenticated) 14 | { 15 |

Welcome @ViewBag.User.DisplayName!

16 |

Use the navigation bar at the top of the page to get started.

17 | } 18 | else 19 | { 20 | @Html.ActionLink("Click here to sign in", "SignIn", "Account", new { area = "" }, new { @class = "btn btn-primary btn-large" }) 21 | } 22 |
23 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Error 6 | 7 | 8 |
9 |

Error.

10 |

An error occurred while processing your request.

11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Views/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } 4 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Web.Debug.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/Web.Release.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Demos/01-create-app/graph-tutorial/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoftgraph/msgraph-training-aspnetmvcapp/08112c10ecf3107da7c6ef9eb5311672b1270649/Demos/01-create-app/graph-tutorial/favicon.ico -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/README.md: -------------------------------------------------------------------------------- 1 | # Demo: Add Azure AD authentication 2 | 3 | This completed project is the result of the lab exercise **Add Azure AD authentication** that is referenced in the [README](../../README.md) in this repo. 4 | 5 | ## Prerequisites 6 | 7 | - [Microsoft 365 tenant](https://developer.microsoft.com/office/dev-program?ocid=MSlearn) 8 | - [.NET Framework 4.8](https://dotnet.microsoft.com/download/dotnet-framework) 9 | - [Visual Studio 2022](https://visualstudio.microsoft.com/vs/) 10 | 11 | ## Run this Completed Project 12 | 13 | - Rename the file **PrivateSettings.config.example** to **PrivateSettings.config** 14 | - Update the properties in the **PrivateSettings.config** with the values you collected in the first exercise. 15 | - Build and run the application by following the instructions in the lab exercise associated with this demo. 16 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.2.32505.173 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "graph-tutorial", "graph-tutorial\graph-tutorial.csproj", "{3839C133-E2D0-466C-ABB3-E92ABCDB6388}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3839C133-E2D0-466C-ABB3-E92ABCDB6388}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {3839C133-E2D0-466C-ABB3-E92ABCDB6388}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {3839C133-E2D0-466C-ABB3-E92ABCDB6388}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {3839C133-E2D0-466C-ABB3-E92ABCDB6388}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {5D8392F3-02AC-499D-9495-D6ED8CE615C5} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/App_Start/BundleConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Optimization; 3 | 4 | namespace graph_tutorial 5 | { 6 | public class BundleConfig 7 | { 8 | // For more information on bundling, visit https://go.microsoft.com/fwlink/?LinkId=301862 9 | public static void RegisterBundles(BundleCollection bundles) 10 | { 11 | bundles.Add(new ScriptBundle("~/bundles/jquery").Include( 12 | "~/Scripts/jquery-{version}.js")); 13 | 14 | bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include( 15 | "~/Scripts/jquery.validate*")); 16 | 17 | // Use the development version of Modernizr to develop with and learn from. Then, when you're 18 | // ready for production, use the build tool at https://modernizr.com to pick only the tests you need. 19 | bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( 20 | "~/Scripts/modernizr-*")); 21 | 22 | bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include( 23 | "~/Scripts/bootstrap.js")); 24 | 25 | bundles.Add(new StyleBundle("~/Content/css").Include( 26 | "~/Content/bootstrap.css", 27 | "~/Content/site.css")); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/App_Start/FilterConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Mvc; 3 | 4 | namespace graph_tutorial 5 | { 6 | public class FilterConfig 7 | { 8 | public static void RegisterGlobalFilters(GlobalFilterCollection filters) 9 | { 10 | filters.Add(new HandleErrorAttribute()); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace graph_tutorial 9 | { 10 | public class RouteConfig 11 | { 12 | public static void RegisterRoutes(RouteCollection routes) 13 | { 14 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 15 | 16 | routes.MapRoute( 17 | name: "Default", 18 | url: "{controller}/{action}/{id}", 19 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 20 | ); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Content/Site.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | body { 7 | padding-top: 4.5rem; 8 | } 9 | 10 | .alert-pre { 11 | word-wrap: break-word; 12 | word-break: break-all; 13 | white-space: pre-wrap; 14 | } -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Controllers/AccountController.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | using Microsoft.Owin.Security; 5 | using Microsoft.Owin.Security.Cookies; 6 | using Microsoft.Owin.Security.OpenIdConnect; 7 | using System.Security.Claims; 8 | using System.Web; 9 | using System.Web.Mvc; 10 | using graph_tutorial.TokenStorage; 11 | 12 | namespace graph_tutorial.Controllers 13 | { 14 | public class AccountController : Controller 15 | { 16 | public void SignIn() 17 | { 18 | if (!Request.IsAuthenticated) 19 | { 20 | // Signal OWIN to send an authorization request to Azure 21 | Request.GetOwinContext().Authentication.Challenge( 22 | new AuthenticationProperties { RedirectUri = "/" }, 23 | OpenIdConnectAuthenticationDefaults.AuthenticationType); 24 | } 25 | } 26 | 27 | public ActionResult SignOut() 28 | { 29 | if (Request.IsAuthenticated) 30 | { 31 | var tokenStore = new SessionTokenStore(null, 32 | System.Web.HttpContext.Current, ClaimsPrincipal.Current); 33 | 34 | tokenStore.Clear(); 35 | 36 | Request.GetOwinContext().Authentication.SignOut( 37 | CookieAuthenticationDefaults.AuthenticationType); 38 | } 39 | 40 | return RedirectToAction("Index", "Home"); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Controllers/BaseController.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | using graph_tutorial.Models; 5 | using System.Collections.Generic; 6 | using System.Web.Mvc; 7 | using graph_tutorial.TokenStorage; 8 | using System.Security.Claims; 9 | using System.Web; 10 | using Microsoft.Owin.Security.Cookies; 11 | 12 | namespace graph_tutorial.Controllers 13 | { 14 | public abstract class BaseController : Controller 15 | { 16 | protected void Flash(string message, string debug = null) 17 | { 18 | var alerts = TempData.ContainsKey(Alert.AlertKey) ? 19 | (List)TempData[Alert.AlertKey] : 20 | new List(); 21 | 22 | alerts.Add(new Alert 23 | { 24 | Message = message, 25 | Debug = debug 26 | }); 27 | 28 | TempData[Alert.AlertKey] = alerts; 29 | } 30 | 31 | protected override void OnActionExecuting(ActionExecutingContext filterContext) 32 | { 33 | if (Request.IsAuthenticated) 34 | { 35 | // Get the user's token cache 36 | var tokenStore = new SessionTokenStore(null, 37 | System.Web.HttpContext.Current, ClaimsPrincipal.Current); 38 | 39 | if (tokenStore.HasData()) 40 | { 41 | // Add the user to the view bag 42 | ViewBag.User = tokenStore.GetUserDetails(); 43 | } 44 | else 45 | { 46 | // The session has lost data. This happens often 47 | // when debugging. Log out so the user can log back in 48 | Request.GetOwinContext().Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType); 49 | filterContext.Result = RedirectToAction("Index", "Home"); 50 | } 51 | } 52 | 53 | base.OnActionExecuting(filterContext); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Web; 8 | using System.Web.Mvc; 9 | 10 | namespace graph_tutorial.Controllers 11 | { 12 | public class HomeController : BaseController 13 | { 14 | public ActionResult Index() 15 | { 16 | return View(); 17 | } 18 | 19 | public ActionResult About() 20 | { 21 | ViewBag.Message = "Your application description page."; 22 | 23 | return View(); 24 | } 25 | 26 | public ActionResult Contact() 27 | { 28 | ViewBag.Message = "Your contact page."; 29 | 30 | return View(); 31 | } 32 | 33 | public ActionResult Error(string message, string debug) 34 | { 35 | Flash(message, debug); 36 | return RedirectToAction("Index"); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="graph_tutorial.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Optimization; 7 | using System.Web.Routing; 8 | 9 | namespace graph_tutorial 10 | { 11 | public class MvcApplication : System.Web.HttpApplication 12 | { 13 | protected void Application_Start() 14 | { 15 | AreaRegistration.RegisterAllAreas(); 16 | FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 17 | RouteConfig.RegisterRoutes(RouteTable.Routes); 18 | BundleConfig.RegisterBundles(BundleTable.Bundles); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Helpers/GraphHelper.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | using graph_tutorial.Models; 5 | using Microsoft.Graph; 6 | using System.Net.Http.Headers; 7 | using System.Threading.Tasks; 8 | 9 | namespace graph_tutorial.Helpers 10 | { 11 | public static class GraphHelper 12 | { 13 | public static async Task GetUserDetailsAsync(string accessToken) 14 | { 15 | var graphClient = new GraphServiceClient( 16 | new DelegateAuthenticationProvider( 17 | async (requestMessage) => 18 | { 19 | requestMessage.Headers.Authorization = 20 | new AuthenticationHeaderValue("Bearer", accessToken); 21 | })); 22 | 23 | var user = await graphClient.Me.Request() 24 | .Select(u => new { 25 | u.DisplayName, 26 | u.Mail, 27 | u.UserPrincipalName 28 | }) 29 | .GetAsync(); 30 | 31 | return new CachedUser 32 | { 33 | Avatar = string.Empty, 34 | DisplayName = user.DisplayName, 35 | Email = string.IsNullOrEmpty(user.Mail) ? 36 | user.UserPrincipalName : user.Mail 37 | }; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Models/Alert.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | namespace graph_tutorial.Models 5 | { 6 | // Used to flash error messages in the app's views. 7 | public class Alert 8 | { 9 | public const string AlertKey = "TempDataAlerts"; 10 | public string Message { get; set; } 11 | public string Debug { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Models/CachedUser.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | namespace graph_tutorial.Models 5 | { 6 | // Simple class to serialize user details 7 | public class CachedUser 8 | { 9 | public string DisplayName { get; set; } 10 | public string Email { get; set; } 11 | public string Avatar { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("graph_tutorial")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("graph_tutorial")] 13 | [assembly: AssemblyCopyright("Copyright © 2022")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("78062d3f-74c7-42ac-8885-7fe5f61a094c")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/methods/destroy.js: -------------------------------------------------------------------------------- 1 | import isModifierEnabled from '../utils/isModifierEnabled'; 2 | import getSupportedPropertyName from '../utils/getSupportedPropertyName'; 3 | 4 | /** 5 | * Destroys the popper. 6 | * @method 7 | * @memberof Popper 8 | */ 9 | export default function destroy() { 10 | this.state.isDestroyed = true; 11 | 12 | // touch DOM only if `applyStyle` modifier is enabled 13 | if (isModifierEnabled(this.modifiers, 'applyStyle')) { 14 | this.popper.removeAttribute('x-placement'); 15 | this.popper.style.position = ''; 16 | this.popper.style.top = ''; 17 | this.popper.style.left = ''; 18 | this.popper.style.right = ''; 19 | this.popper.style.bottom = ''; 20 | this.popper.style.willChange = ''; 21 | this.popper.style[getSupportedPropertyName('transform')] = ''; 22 | } 23 | 24 | this.disableEventListeners(); 25 | 26 | // remove the popper if user explicitly asked for the deletion on destroy 27 | // do not use `remove` because IE11 doesn't support it 28 | if (this.options.removeOnDestroy) { 29 | this.popper.parentNode.removeChild(this.popper); 30 | } 31 | return this; 32 | } 33 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/methods/disableEventListeners.js: -------------------------------------------------------------------------------- 1 | import removeEventListeners from '../utils/removeEventListeners'; 2 | 3 | /** 4 | * It will remove resize/scroll events and won't recalculate popper position 5 | * when they are triggered. It also won't trigger `onUpdate` callback anymore, 6 | * unless you call `update` method manually. 7 | * @method 8 | * @memberof Popper 9 | */ 10 | export default function disableEventListeners() { 11 | if (this.state.eventsEnabled) { 12 | cancelAnimationFrame(this.scheduleUpdate); 13 | this.state = removeEventListeners(this.reference, this.state); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/methods/enableEventListeners.js: -------------------------------------------------------------------------------- 1 | import setupEventListeners from '../utils/setupEventListeners'; 2 | 3 | /** 4 | * It will add resize/scroll events and start recalculating 5 | * position of the popper element when they are triggered. 6 | * @method 7 | * @memberof Popper 8 | */ 9 | export default function enableEventListeners() { 10 | if (!this.state.eventsEnabled) { 11 | this.state = setupEventListeners( 12 | this.reference, 13 | this.options, 14 | this.state, 15 | this.scheduleUpdate 16 | ); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/methods/placements.js: -------------------------------------------------------------------------------- 1 | /** 2 | * List of accepted placements to use as values of the `placement` option.
3 | * Valid placements are: 4 | * - `auto` 5 | * - `top` 6 | * - `right` 7 | * - `bottom` 8 | * - `left` 9 | * 10 | * Each placement can have a variation from this list: 11 | * - `-start` 12 | * - `-end` 13 | * 14 | * Variations are interpreted easily if you think of them as the left to right 15 | * written languages. Horizontally (`top` and `bottom`), `start` is left and `end` 16 | * is right.
17 | * Vertically (`left` and `right`), `start` is top and `end` is bottom. 18 | * 19 | * Some valid examples are: 20 | * - `top-end` (on top of reference, right aligned) 21 | * - `right-start` (on right of reference, top aligned) 22 | * - `bottom` (on bottom, centered) 23 | * - `auto-end` (on the side with more space available, alignment depends by placement) 24 | * 25 | * @static 26 | * @type {Array} 27 | * @enum {String} 28 | * @readonly 29 | * @method placements 30 | * @memberof Popper 31 | */ 32 | export default [ 33 | 'auto-start', 34 | 'auto', 35 | 'auto-end', 36 | 'top-start', 37 | 'top', 38 | 'top-end', 39 | 'right-start', 40 | 'right', 41 | 'right-end', 42 | 'bottom-end', 43 | 'bottom', 44 | 'bottom-start', 45 | 'left-end', 46 | 'left', 47 | 'left-start', 48 | ]; 49 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/modifiers/hide.js: -------------------------------------------------------------------------------- 1 | import isModifierRequired from '../utils/isModifierRequired'; 2 | import find from '../utils/find'; 3 | 4 | /** 5 | * @function 6 | * @memberof Modifiers 7 | * @argument {Object} data - The data object generated by update method 8 | * @argument {Object} options - Modifiers configuration and options 9 | * @returns {Object} The data object, properly modified 10 | */ 11 | export default function hide(data) { 12 | if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) { 13 | return data; 14 | } 15 | 16 | const refRect = data.offsets.reference; 17 | const bound = find( 18 | data.instance.modifiers, 19 | modifier => modifier.name === 'preventOverflow' 20 | ).boundaries; 21 | 22 | if ( 23 | refRect.bottom < bound.top || 24 | refRect.left > bound.right || 25 | refRect.top > bound.bottom || 26 | refRect.right < bound.left 27 | ) { 28 | // Avoid unnecessary DOM access if visibility hasn't changed 29 | if (data.hide === true) { 30 | return data; 31 | } 32 | 33 | data.hide = true; 34 | data.attributes['x-out-of-boundaries'] = ''; 35 | } else { 36 | // Avoid unnecessary DOM access if visibility hasn't changed 37 | if (data.hide === false) { 38 | return data; 39 | } 40 | 41 | data.hide = false; 42 | data.attributes['x-out-of-boundaries'] = false; 43 | } 44 | 45 | return data; 46 | } 47 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/modifiers/inner.js: -------------------------------------------------------------------------------- 1 | import getClientRect from '../utils/getClientRect'; 2 | import getOppositePlacement from '../utils/getOppositePlacement'; 3 | 4 | /** 5 | * @function 6 | * @memberof Modifiers 7 | * @argument {Object} data - The data object generated by `update` method 8 | * @argument {Object} options - Modifiers configuration and options 9 | * @returns {Object} The data object, properly modified 10 | */ 11 | export default function inner(data) { 12 | const placement = data.placement; 13 | const basePlacement = placement.split('-')[0]; 14 | const { popper, reference } = data.offsets; 15 | const isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1; 16 | 17 | const subtractLength = ['top', 'left'].indexOf(basePlacement) === -1; 18 | 19 | popper[isHoriz ? 'left' : 'top'] = 20 | reference[basePlacement] - 21 | (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0); 22 | 23 | data.placement = getOppositePlacement(placement); 24 | data.offsets.popper = getClientRect(popper); 25 | 26 | return data; 27 | } 28 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/modifiers/keepTogether.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @function 3 | * @memberof Modifiers 4 | * @argument {Object} data - The data object generated by update method 5 | * @argument {Object} options - Modifiers configuration and options 6 | * @returns {Object} The data object, properly modified 7 | */ 8 | export default function keepTogether(data) { 9 | const { popper, reference } = data.offsets; 10 | const placement = data.placement.split('-')[0]; 11 | const floor = Math.floor; 12 | const isVertical = ['top', 'bottom'].indexOf(placement) !== -1; 13 | const side = isVertical ? 'right' : 'bottom'; 14 | const opSide = isVertical ? 'left' : 'top'; 15 | const measurement = isVertical ? 'width' : 'height'; 16 | 17 | if (popper[side] < floor(reference[opSide])) { 18 | data.offsets.popper[opSide] = 19 | floor(reference[opSide]) - popper[measurement]; 20 | } 21 | if (popper[opSide] > floor(reference[side])) { 22 | data.offsets.popper[opSide] = floor(reference[side]); 23 | } 24 | 25 | return data; 26 | } 27 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/modifiers/shift.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @function 3 | * @memberof Modifiers 4 | * @argument {Object} data - The data object generated by `update` method 5 | * @argument {Object} options - Modifiers configuration and options 6 | * @returns {Object} The data object, properly modified 7 | */ 8 | export default function shift(data) { 9 | const placement = data.placement; 10 | const basePlacement = placement.split('-')[0]; 11 | const shiftvariation = placement.split('-')[1]; 12 | 13 | // if shift shiftvariation is specified, run the modifier 14 | if (shiftvariation) { 15 | const { reference, popper } = data.offsets; 16 | const isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1; 17 | const side = isVertical ? 'left' : 'top'; 18 | const measurement = isVertical ? 'width' : 'height'; 19 | 20 | const shiftOffsets = { 21 | start: { [side]: reference[side] }, 22 | end: { 23 | [side]: reference[side] + reference[measurement] - popper[measurement], 24 | }, 25 | }; 26 | 27 | data.offsets.popper = { ...popper, ...shiftOffsets[shiftvariation] }; 28 | } 29 | 30 | return data; 31 | } 32 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/clockwise.js: -------------------------------------------------------------------------------- 1 | import placements from '../methods/placements'; 2 | 3 | // Get rid of `auto` `auto-start` and `auto-end` 4 | const validPlacements = placements.slice(3); 5 | 6 | /** 7 | * Given an initial placement, returns all the subsequent placements 8 | * clockwise (or counter-clockwise). 9 | * 10 | * @method 11 | * @memberof Popper.Utils 12 | * @argument {String} placement - A valid placement (it accepts variations) 13 | * @argument {Boolean} counter - Set to true to walk the placements counterclockwise 14 | * @returns {Array} placements including their variations 15 | */ 16 | export default function clockwise(placement, counter = false) { 17 | const index = validPlacements.indexOf(placement); 18 | const arr = validPlacements 19 | .slice(index + 1) 20 | .concat(validPlacements.slice(0, index)); 21 | return counter ? arr.reverse() : arr; 22 | } 23 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/computeAutoPlacement.js: -------------------------------------------------------------------------------- 1 | import getBoundaries from '../utils/getBoundaries'; 2 | 3 | function getArea({ width, height }) { 4 | return width * height; 5 | } 6 | 7 | /** 8 | * Utility used to transform the `auto` placement to the placement with more 9 | * available space. 10 | * @method 11 | * @memberof Popper.Utils 12 | * @argument {Object} data - The data object generated by update method 13 | * @argument {Object} options - Modifiers configuration and options 14 | * @returns {Object} The data object, properly modified 15 | */ 16 | export default function computeAutoPlacement( 17 | placement, 18 | refRect, 19 | popper, 20 | reference, 21 | boundariesElement, 22 | padding = 0 23 | ) { 24 | if (placement.indexOf('auto') === -1) { 25 | return placement; 26 | } 27 | 28 | const boundaries = getBoundaries( 29 | popper, 30 | reference, 31 | padding, 32 | boundariesElement 33 | ); 34 | 35 | const rects = { 36 | top: { 37 | width: boundaries.width, 38 | height: refRect.top - boundaries.top, 39 | }, 40 | right: { 41 | width: boundaries.right - refRect.right, 42 | height: boundaries.height, 43 | }, 44 | bottom: { 45 | width: boundaries.width, 46 | height: boundaries.bottom - refRect.bottom, 47 | }, 48 | left: { 49 | width: refRect.left - boundaries.left, 50 | height: boundaries.height, 51 | }, 52 | }; 53 | 54 | const sortedAreas = Object.keys(rects) 55 | .map(key => ({ 56 | key, 57 | ...rects[key], 58 | area: getArea(rects[key]), 59 | })) 60 | .sort((a, b) => b.area - a.area); 61 | 62 | const filteredAreas = sortedAreas.filter( 63 | ({ width, height }) => 64 | width >= popper.clientWidth && height >= popper.clientHeight 65 | ); 66 | 67 | const computedPlacement = filteredAreas.length > 0 68 | ? filteredAreas[0].key 69 | : sortedAreas[0].key; 70 | 71 | const variation = placement.split('-')[1]; 72 | 73 | return computedPlacement + (variation ? `-${variation}` : ''); 74 | } 75 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/debounce.js: -------------------------------------------------------------------------------- 1 | import isBrowser from './isBrowser'; 2 | 3 | const timeoutDuration = (function(){ 4 | const longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox']; 5 | for (let i = 0; i < longerTimeoutBrowsers.length; i += 1) { 6 | if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) { 7 | return 1; 8 | } 9 | } 10 | return 0; 11 | }()); 12 | 13 | export function microtaskDebounce(fn) { 14 | let called = false 15 | return () => { 16 | if (called) { 17 | return 18 | } 19 | called = true 20 | window.Promise.resolve().then(() => { 21 | called = false 22 | fn() 23 | }) 24 | } 25 | } 26 | 27 | export function taskDebounce(fn) { 28 | let scheduled = false; 29 | return () => { 30 | if (!scheduled) { 31 | scheduled = true; 32 | setTimeout(() => { 33 | scheduled = false; 34 | fn(); 35 | }, timeoutDuration); 36 | } 37 | }; 38 | } 39 | 40 | const supportsMicroTasks = isBrowser && window.Promise 41 | 42 | 43 | /** 44 | * Create a debounced version of a method, that's asynchronously deferred 45 | * but called in the minimum time possible. 46 | * 47 | * @method 48 | * @memberof Popper.Utils 49 | * @argument {Function} fn 50 | * @returns {Function} 51 | */ 52 | export default (supportsMicroTasks 53 | ? microtaskDebounce 54 | : taskDebounce); 55 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/find.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Mimics the `find` method of Array 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Array} arr 6 | * @argument prop 7 | * @argument value 8 | * @returns index or -1 9 | */ 10 | export default function find(arr, check) { 11 | // use native find if supported 12 | if (Array.prototype.find) { 13 | return arr.find(check); 14 | } 15 | 16 | // use `filter` to obtain the same behavior of `find` 17 | return arr.filter(check)[0]; 18 | } 19 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/findCommonOffsetParent.js: -------------------------------------------------------------------------------- 1 | import isOffsetContainer from './isOffsetContainer'; 2 | import getRoot from './getRoot'; 3 | import getOffsetParent from './getOffsetParent'; 4 | 5 | /** 6 | * Finds the offset parent common to the two provided nodes 7 | * @method 8 | * @memberof Popper.Utils 9 | * @argument {Element} element1 10 | * @argument {Element} element2 11 | * @returns {Element} common offset parent 12 | */ 13 | export default function findCommonOffsetParent(element1, element2) { 14 | // This check is needed to avoid errors in case one of the elements isn't defined for any reason 15 | if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) { 16 | return document.documentElement; 17 | } 18 | 19 | // Here we make sure to give as "start" the element that comes first in the DOM 20 | const order = 21 | element1.compareDocumentPosition(element2) & 22 | Node.DOCUMENT_POSITION_FOLLOWING; 23 | const start = order ? element1 : element2; 24 | const end = order ? element2 : element1; 25 | 26 | // Get common ancestor container 27 | const range = document.createRange(); 28 | range.setStart(start, 0); 29 | range.setEnd(end, 0); 30 | const { commonAncestorContainer } = range; 31 | 32 | // Both nodes are inside #document 33 | if ( 34 | (element1 !== commonAncestorContainer && 35 | element2 !== commonAncestorContainer) || 36 | start.contains(end) 37 | ) { 38 | if (isOffsetContainer(commonAncestorContainer)) { 39 | return commonAncestorContainer; 40 | } 41 | 42 | return getOffsetParent(commonAncestorContainer); 43 | } 44 | 45 | // one of the nodes is inside shadowDOM, find which one 46 | const element1root = getRoot(element1); 47 | if (element1root.host) { 48 | return findCommonOffsetParent(element1root.host, element2); 49 | } else { 50 | return findCommonOffsetParent(element1, getRoot(element2).host); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/findIndex.js: -------------------------------------------------------------------------------- 1 | import find from './find'; 2 | 3 | /** 4 | * Return the index of the matching object 5 | * @method 6 | * @memberof Popper.Utils 7 | * @argument {Array} arr 8 | * @argument prop 9 | * @argument value 10 | * @returns index or -1 11 | */ 12 | export default function findIndex(arr, prop, value) { 13 | // use native findIndex if supported 14 | if (Array.prototype.findIndex) { 15 | return arr.findIndex(cur => cur[prop] === value); 16 | } 17 | 18 | // use `find` + `indexOf` if `findIndex` isn't supported 19 | const match = find(arr, obj => obj[prop] === value); 20 | return arr.indexOf(match); 21 | } 22 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/getBordersSize.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Helper to detect borders of a given element 3 | * @method 4 | * @memberof Popper.Utils 5 | * @param {CSSStyleDeclaration} styles 6 | * Result of `getStyleComputedProperty` on the given element 7 | * @param {String} axis - `x` or `y` 8 | * @return {number} borders - The borders size of the given axis 9 | */ 10 | 11 | export default function getBordersSize(styles, axis) { 12 | const sideA = axis === 'x' ? 'Left' : 'Top'; 13 | const sideB = sideA === 'Left' ? 'Right' : 'Bottom'; 14 | 15 | return ( 16 | parseFloat(styles[`border${sideA}Width`]) + 17 | parseFloat(styles[`border${sideB}Width`]) 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/getClientRect.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Given element offsets, generate an output similar to getBoundingClientRect 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Object} offsets 6 | * @returns {Object} ClientRect like output 7 | */ 8 | export default function getClientRect(offsets) { 9 | return { 10 | ...offsets, 11 | right: offsets.left + offsets.width, 12 | bottom: offsets.top + offsets.height, 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/getFixedPositionOffsetParent.js: -------------------------------------------------------------------------------- 1 | import getStyleComputedProperty from './getStyleComputedProperty'; 2 | import isIE from './isIE'; 3 | /** 4 | * Finds the first parent of an element that has a transformed property defined 5 | * @method 6 | * @memberof Popper.Utils 7 | * @argument {Element} element 8 | * @returns {Element} first transformed parent or documentElement 9 | */ 10 | 11 | export default function getFixedPositionOffsetParent(element) { 12 | // This check is needed to avoid errors in case one of the elements isn't defined for any reason 13 | if (!element || !element.parentElement || isIE()) { 14 | return document.documentElement; 15 | } 16 | let el = element.parentElement; 17 | while (el && getStyleComputedProperty(el, 'transform') === 'none') { 18 | el = el.parentElement; 19 | } 20 | return el || document.documentElement; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/getOffsetParent.js: -------------------------------------------------------------------------------- 1 | import getStyleComputedProperty from './getStyleComputedProperty'; 2 | import isIE from './isIE'; 3 | /** 4 | * Returns the offset parent of the given element 5 | * @method 6 | * @memberof Popper.Utils 7 | * @argument {Element} element 8 | * @returns {Element} offset parent 9 | */ 10 | export default function getOffsetParent(element) { 11 | if (!element) { 12 | return document.documentElement; 13 | } 14 | 15 | const noOffsetParent = isIE(10) ? document.body : null; 16 | 17 | // NOTE: 1 DOM access here 18 | let offsetParent = element.offsetParent || null; 19 | // Skip hidden elements which don't have an offsetParent 20 | while (offsetParent === noOffsetParent && element.nextElementSibling) { 21 | offsetParent = (element = element.nextElementSibling).offsetParent; 22 | } 23 | 24 | const nodeName = offsetParent && offsetParent.nodeName; 25 | 26 | if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') { 27 | return element ? element.ownerDocument.documentElement : document.documentElement; 28 | } 29 | 30 | // .offsetParent will return the closest TH, TD or TABLE in case 31 | // no offsetParent is present, I hate this job... 32 | if ( 33 | ['TH', 'TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && 34 | getStyleComputedProperty(offsetParent, 'position') === 'static' 35 | ) { 36 | return getOffsetParent(offsetParent); 37 | } 38 | 39 | return offsetParent; 40 | } 41 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/getOffsetRect.js: -------------------------------------------------------------------------------- 1 | import getWindowSizes from './getWindowSizes'; 2 | import getClientRect from './getClientRect'; 3 | 4 | /** 5 | * Get the position of the given element, relative to its offset parent 6 | * @method 7 | * @memberof Popper.Utils 8 | * @param {Element} element 9 | * @return {Object} position - Coordinates of the element and its `scrollTop` 10 | */ 11 | export default function getOffsetRect(element) { 12 | let elementRect; 13 | if (element.nodeName === 'HTML') { 14 | const { width, height } = getWindowSizes(element.ownerDocument); 15 | elementRect = { 16 | width, 17 | height, 18 | left: 0, 19 | top: 0, 20 | }; 21 | } else { 22 | elementRect = { 23 | width: element.offsetWidth, 24 | height: element.offsetHeight, 25 | left: element.offsetLeft, 26 | top: element.offsetTop, 27 | }; 28 | } 29 | 30 | // position 31 | return getClientRect(elementRect); 32 | } 33 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/getOppositePlacement.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the opposite placement of the given one 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {String} placement 6 | * @returns {String} flipped placement 7 | */ 8 | export default function getOppositePlacement(placement) { 9 | const hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' }; 10 | return placement.replace(/left|right|bottom|top/g, matched => hash[matched]); 11 | } 12 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/getOppositeVariation.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the opposite placement variation of the given one 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {String} placement variation 6 | * @returns {String} flipped placement variation 7 | */ 8 | export default function getOppositeVariation(variation) { 9 | if (variation === 'end') { 10 | return 'start'; 11 | } else if (variation === 'start') { 12 | return 'end'; 13 | } 14 | return variation; 15 | } 16 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/getOuterSizes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the outer sizes of the given element (offset size + margins) 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Element} element 6 | * @returns {Object} object containing width and height properties 7 | */ 8 | export default function getOuterSizes(element) { 9 | const window = element.ownerDocument.defaultView; 10 | const styles = window.getComputedStyle(element); 11 | const x = parseFloat(styles.marginTop || 0) + parseFloat(styles.marginBottom || 0); 12 | const y = parseFloat(styles.marginLeft || 0) + parseFloat(styles.marginRight || 0); 13 | const result = { 14 | width: element.offsetWidth + y, 15 | height: element.offsetHeight + x, 16 | }; 17 | return result; 18 | } 19 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/getParentNode.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns the parentNode or the host of the element 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Element} element 6 | * @returns {Element} parent 7 | */ 8 | export default function getParentNode(element) { 9 | if (element.nodeName === 'HTML') { 10 | return element; 11 | } 12 | return element.parentNode || element.host; 13 | } 14 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/getPopperOffsets.js: -------------------------------------------------------------------------------- 1 | import getOuterSizes from './getOuterSizes'; 2 | import getOppositePlacement from './getOppositePlacement'; 3 | 4 | /** 5 | * Get offsets to the popper 6 | * @method 7 | * @memberof Popper.Utils 8 | * @param {Object} position - CSS position the Popper will get applied 9 | * @param {HTMLElement} popper - the popper element 10 | * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this) 11 | * @param {String} placement - one of the valid placement options 12 | * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper 13 | */ 14 | export default function getPopperOffsets(popper, referenceOffsets, placement) { 15 | placement = placement.split('-')[0]; 16 | 17 | // Get popper node sizes 18 | const popperRect = getOuterSizes(popper); 19 | 20 | // Add position, width and height to our offsets object 21 | const popperOffsets = { 22 | width: popperRect.width, 23 | height: popperRect.height, 24 | }; 25 | 26 | // depending by the popper placement we have to compute its offsets slightly differently 27 | const isHoriz = ['right', 'left'].indexOf(placement) !== -1; 28 | const mainSide = isHoriz ? 'top' : 'left'; 29 | const secondarySide = isHoriz ? 'left' : 'top'; 30 | const measurement = isHoriz ? 'height' : 'width'; 31 | const secondaryMeasurement = !isHoriz ? 'height' : 'width'; 32 | 33 | popperOffsets[mainSide] = 34 | referenceOffsets[mainSide] + 35 | referenceOffsets[measurement] / 2 - 36 | popperRect[measurement] / 2; 37 | if (placement === secondarySide) { 38 | popperOffsets[secondarySide] = 39 | referenceOffsets[secondarySide] - popperRect[secondaryMeasurement]; 40 | } else { 41 | popperOffsets[secondarySide] = 42 | referenceOffsets[getOppositePlacement(secondarySide)]; 43 | } 44 | 45 | return popperOffsets; 46 | } 47 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/getReferenceNode.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns the reference node of the reference object, or the reference object itself. 3 | * @method 4 | * @memberof Popper.Utils 5 | * @param {Element|Object} reference - the reference element (the popper will be relative to this) 6 | * @returns {Element} parent 7 | */ 8 | export default function getReferenceNode(reference) { 9 | return reference && reference.referenceNode ? reference.referenceNode : reference; 10 | } 11 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/getReferenceOffsets.js: -------------------------------------------------------------------------------- 1 | import findCommonOffsetParent from './findCommonOffsetParent'; 2 | import getOffsetRectRelativeToArbitraryNode from './getOffsetRectRelativeToArbitraryNode'; 3 | import getFixedPositionOffsetParent from './getFixedPositionOffsetParent'; 4 | import getReferenceNode from './getReferenceNode'; 5 | 6 | /** 7 | * Get offsets to the reference element 8 | * @method 9 | * @memberof Popper.Utils 10 | * @param {Object} state 11 | * @param {Element} popper - the popper element 12 | * @param {Element} reference - the reference element (the popper will be relative to this) 13 | * @param {Element} fixedPosition - is in fixed position mode 14 | * @returns {Object} An object containing the offsets which will be applied to the popper 15 | */ 16 | export default function getReferenceOffsets(state, popper, reference, fixedPosition = null) { 17 | const commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, getReferenceNode(reference)); 18 | return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition); 19 | } 20 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/getRoot.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Finds the root node (document, shadowDOM root) of the given element 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Element} node 6 | * @returns {Element} root node 7 | */ 8 | export default function getRoot(node) { 9 | if (node.parentNode !== null) { 10 | return getRoot(node.parentNode); 11 | } 12 | 13 | return node; 14 | } 15 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/getRoundedOffsets.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @function 3 | * @memberof Popper.Utils 4 | * @argument {Object} data - The data object generated by `update` method 5 | * @argument {Boolean} shouldRound - If the offsets should be rounded at all 6 | * @returns {Object} The popper's position offsets rounded 7 | * 8 | * The tale of pixel-perfect positioning. It's still not 100% perfect, but as 9 | * good as it can be within reason. 10 | * Discussion here: https://github.com/FezVrasta/popper.js/pull/715 11 | * 12 | * Low DPI screens cause a popper to be blurry if not using full pixels (Safari 13 | * as well on High DPI screens). 14 | * 15 | * Firefox prefers no rounding for positioning and does not have blurriness on 16 | * high DPI screens. 17 | * 18 | * Only horizontal placement and left/right values need to be considered. 19 | */ 20 | export default function getRoundedOffsets(data, shouldRound) { 21 | const { popper, reference } = data.offsets; 22 | const { round, floor } = Math; 23 | const noRound = v => v; 24 | 25 | const referenceWidth = round(reference.width); 26 | const popperWidth = round(popper.width); 27 | 28 | const isVertical = ['left', 'right'].indexOf(data.placement) !== -1; 29 | const isVariation = data.placement.indexOf('-') !== -1; 30 | const sameWidthParity = referenceWidth % 2 === popperWidth % 2; 31 | const bothOddWidth = referenceWidth % 2 === 1 && popperWidth % 2 === 1; 32 | 33 | const horizontalToInteger = !shouldRound 34 | ? noRound 35 | : isVertical || isVariation || sameWidthParity 36 | ? round 37 | : floor; 38 | const verticalToInteger = !shouldRound ? noRound : round; 39 | 40 | return { 41 | left: horizontalToInteger( 42 | bothOddWidth && !isVariation && shouldRound 43 | ? popper.left - 1 44 | : popper.left 45 | ), 46 | top: verticalToInteger(popper.top), 47 | bottom: verticalToInteger(popper.bottom), 48 | right: horizontalToInteger(popper.right), 49 | }; 50 | } 51 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/getScroll.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Gets the scroll value of the given element in the given side (top and left) 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Element} element 6 | * @argument {String} side `top` or `left` 7 | * @returns {number} amount of scrolled pixels 8 | */ 9 | export default function getScroll(element, side = 'top') { 10 | const upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft'; 11 | const nodeName = element.nodeName; 12 | 13 | if (nodeName === 'BODY' || nodeName === 'HTML') { 14 | const html = element.ownerDocument.documentElement; 15 | const scrollingElement = element.ownerDocument.scrollingElement || html; 16 | return scrollingElement[upperSide]; 17 | } 18 | 19 | return element[upperSide]; 20 | } 21 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/getScrollParent.js: -------------------------------------------------------------------------------- 1 | import getStyleComputedProperty from './getStyleComputedProperty'; 2 | import getParentNode from './getParentNode'; 3 | 4 | /** 5 | * Returns the scrolling parent of the given element 6 | * @method 7 | * @memberof Popper.Utils 8 | * @argument {Element} element 9 | * @returns {Element} scroll parent 10 | */ 11 | export default function getScrollParent(element) { 12 | // Return body, `getScroll` will take care to get the correct `scrollTop` from it 13 | if (!element) { 14 | return document.body 15 | } 16 | 17 | switch (element.nodeName) { 18 | case 'HTML': 19 | case 'BODY': 20 | return element.ownerDocument.body 21 | case '#document': 22 | return element.body 23 | } 24 | 25 | // Firefox want us to check `-x` and `-y` variations as well 26 | const { overflow, overflowX, overflowY } = getStyleComputedProperty(element); 27 | if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) { 28 | return element; 29 | } 30 | 31 | return getScrollParent(getParentNode(element)); 32 | } 33 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/getStyleComputedProperty.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get CSS computed property of the given element 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Eement} element 6 | * @argument {String} property 7 | */ 8 | export default function getStyleComputedProperty(element, property) { 9 | if (element.nodeType !== 1) { 10 | return []; 11 | } 12 | // NOTE: 1 DOM access here 13 | const window = element.ownerDocument.defaultView; 14 | const css = window.getComputedStyle(element, null); 15 | return property ? css[property] : css; 16 | } 17 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/getSupportedPropertyName.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the prefixed supported property name 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {String} property (camelCase) 6 | * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix) 7 | */ 8 | export default function getSupportedPropertyName(property) { 9 | const prefixes = [false, 'ms', 'Webkit', 'Moz', 'O']; 10 | const upperProp = property.charAt(0).toUpperCase() + property.slice(1); 11 | 12 | for (let i = 0; i < prefixes.length; i++) { 13 | const prefix = prefixes[i]; 14 | const toCheck = prefix ? `${prefix}${upperProp}` : property; 15 | if (typeof document.body.style[toCheck] !== 'undefined') { 16 | return toCheck; 17 | } 18 | } 19 | return null; 20 | } 21 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/getViewportOffsetRectRelativeToArtbitraryNode.js: -------------------------------------------------------------------------------- 1 | import getOffsetRectRelativeToArbitraryNode from './getOffsetRectRelativeToArbitraryNode'; 2 | import getScroll from './getScroll'; 3 | import getClientRect from './getClientRect'; 4 | 5 | export default function getViewportOffsetRectRelativeToArtbitraryNode(element, excludeScroll = false) { 6 | const html = element.ownerDocument.documentElement; 7 | const relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html); 8 | const width = Math.max(html.clientWidth, window.innerWidth || 0); 9 | const height = Math.max(html.clientHeight, window.innerHeight || 0); 10 | 11 | const scrollTop = !excludeScroll ? getScroll(html) : 0; 12 | const scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0; 13 | 14 | const offset = { 15 | top: scrollTop - relativeOffset.top + relativeOffset.marginTop, 16 | left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft, 17 | width, 18 | height, 19 | }; 20 | 21 | return getClientRect(offset); 22 | } 23 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/getWindow.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the window associated with the element 3 | * @argument {Element} element 4 | * @returns {Window} 5 | */ 6 | export default function getWindow(element) { 7 | const ownerDocument = element.ownerDocument; 8 | return ownerDocument ? ownerDocument.defaultView : window; 9 | } 10 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/getWindowSizes.js: -------------------------------------------------------------------------------- 1 | import isIE from './isIE'; 2 | 3 | function getSize(axis, body, html, computedStyle) { 4 | return Math.max( 5 | body[`offset${axis}`], 6 | body[`scroll${axis}`], 7 | html[`client${axis}`], 8 | html[`offset${axis}`], 9 | html[`scroll${axis}`], 10 | isIE(10) 11 | ? (parseInt(html[`offset${axis}`]) + 12 | parseInt(computedStyle[`margin${axis === 'Height' ? 'Top' : 'Left'}`]) + 13 | parseInt(computedStyle[`margin${axis === 'Height' ? 'Bottom' : 'Right'}`])) 14 | : 0 15 | ); 16 | } 17 | 18 | export default function getWindowSizes(document) { 19 | const body = document.body; 20 | const html = document.documentElement; 21 | const computedStyle = isIE(10) && getComputedStyle(html); 22 | 23 | return { 24 | height: getSize('Height', body, html, computedStyle), 25 | width: getSize('Width', body, html, computedStyle), 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/includeScroll.js: -------------------------------------------------------------------------------- 1 | import getScroll from './getScroll'; 2 | 3 | /* 4 | * Sum or subtract the element scroll values (left and top) from a given rect object 5 | * @method 6 | * @memberof Popper.Utils 7 | * @param {Object} rect - Rect object you want to change 8 | * @param {HTMLElement} element - The element from the function reads the scroll values 9 | * @param {Boolean} subtract - set to true if you want to subtract the scroll values 10 | * @return {Object} rect - The modifier rect object 11 | */ 12 | export default function includeScroll(rect, element, subtract = false) { 13 | const scrollTop = getScroll(element, 'top'); 14 | const scrollLeft = getScroll(element, 'left'); 15 | const modifier = subtract ? -1 : 1; 16 | rect.top += scrollTop * modifier; 17 | rect.bottom += scrollTop * modifier; 18 | rect.left += scrollLeft * modifier; 19 | rect.right += scrollLeft * modifier; 20 | return rect; 21 | } 22 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/isBrowser.js: -------------------------------------------------------------------------------- 1 | export default typeof window !== 'undefined' && typeof document !== 'undefined' && typeof navigator !== 'undefined'; 2 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/isFixed.js: -------------------------------------------------------------------------------- 1 | import getStyleComputedProperty from './getStyleComputedProperty'; 2 | import getParentNode from './getParentNode'; 3 | 4 | /** 5 | * Check if the given element is fixed or is inside a fixed parent 6 | * @method 7 | * @memberof Popper.Utils 8 | * @argument {Element} element 9 | * @argument {Element} customContainer 10 | * @returns {Boolean} answer to "isFixed?" 11 | */ 12 | export default function isFixed(element) { 13 | const nodeName = element.nodeName; 14 | if (nodeName === 'BODY' || nodeName === 'HTML') { 15 | return false; 16 | } 17 | if (getStyleComputedProperty(element, 'position') === 'fixed') { 18 | return true; 19 | } 20 | const parentNode = getParentNode(element); 21 | if (!parentNode) { 22 | return false; 23 | } 24 | return isFixed(parentNode); 25 | } 26 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/isFunction.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Check if the given variable is a function 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Any} functionToCheck - variable to check 6 | * @returns {Boolean} answer to: is a function? 7 | */ 8 | export default function isFunction(functionToCheck) { 9 | const getType = {}; 10 | return ( 11 | functionToCheck && 12 | getType.toString.call(functionToCheck) === '[object Function]' 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/isIE.js: -------------------------------------------------------------------------------- 1 | import isBrowser from './isBrowser'; 2 | 3 | const isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode); 4 | const isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent); 5 | 6 | /** 7 | * Determines if the browser is Internet Explorer 8 | * @method 9 | * @memberof Popper.Utils 10 | * @param {Number} version to check 11 | * @returns {Boolean} isIE 12 | */ 13 | export default function isIE(version) { 14 | if (version === 11) { 15 | return isIE11; 16 | } 17 | if (version === 10) { 18 | return isIE10; 19 | } 20 | return isIE11 || isIE10; 21 | } 22 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/isModifierEnabled.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Helper used to know if the given modifier is enabled. 3 | * @method 4 | * @memberof Popper.Utils 5 | * @returns {Boolean} 6 | */ 7 | export default function isModifierEnabled(modifiers, modifierName) { 8 | return modifiers.some( 9 | ({ name, enabled }) => enabled && name === modifierName 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/isModifierRequired.js: -------------------------------------------------------------------------------- 1 | import find from './find'; 2 | 3 | /** 4 | * Helper used to know if the given modifier depends from another one.
5 | * It checks if the needed modifier is listed and enabled. 6 | * @method 7 | * @memberof Popper.Utils 8 | * @param {Array} modifiers - list of modifiers 9 | * @param {String} requestingName - name of requesting modifier 10 | * @param {String} requestedName - name of requested modifier 11 | * @returns {Boolean} 12 | */ 13 | export default function isModifierRequired( 14 | modifiers, 15 | requestingName, 16 | requestedName 17 | ) { 18 | const requesting = find(modifiers, ({ name }) => name === requestingName); 19 | 20 | const isRequired = 21 | !!requesting && 22 | modifiers.some(modifier => { 23 | return ( 24 | modifier.name === requestedName && 25 | modifier.enabled && 26 | modifier.order < requesting.order 27 | ); 28 | }); 29 | 30 | if (!isRequired) { 31 | const requesting = `\`${requestingName}\``; 32 | const requested = `\`${requestedName}\``; 33 | console.warn( 34 | `${requested} modifier is required by ${requesting} modifier in order to work, be sure to include it before ${requesting}!` 35 | ); 36 | } 37 | return isRequired; 38 | } 39 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/isNumeric.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Tells if a given input is a number 3 | * @method 4 | * @memberof Popper.Utils 5 | * @param {*} input to check 6 | * @return {Boolean} 7 | */ 8 | export default function isNumeric(n) { 9 | return n !== '' && !isNaN(parseFloat(n)) && isFinite(n); 10 | } 11 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/isOffsetContainer.js: -------------------------------------------------------------------------------- 1 | import getOffsetParent from './getOffsetParent'; 2 | 3 | export default function isOffsetContainer(element) { 4 | const { nodeName } = element; 5 | if (nodeName === 'BODY') { 6 | return false; 7 | } 8 | return ( 9 | nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/removeEventListeners.js: -------------------------------------------------------------------------------- 1 | import getWindow from './getWindow'; 2 | 3 | /** 4 | * Remove event listeners used to update the popper position 5 | * @method 6 | * @memberof Popper.Utils 7 | * @private 8 | */ 9 | export default function removeEventListeners(reference, state) { 10 | // Remove resize event listener on window 11 | getWindow(reference).removeEventListener('resize', state.updateBound); 12 | 13 | // Remove scroll event listener on scroll parents 14 | state.scrollParents.forEach(target => { 15 | target.removeEventListener('scroll', state.updateBound); 16 | }); 17 | 18 | // Reset state 19 | state.updateBound = null; 20 | state.scrollParents = []; 21 | state.scrollElement = null; 22 | state.eventsEnabled = false; 23 | return state; 24 | } 25 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/runModifiers.js: -------------------------------------------------------------------------------- 1 | import isFunction from './isFunction'; 2 | import findIndex from './findIndex'; 3 | import getClientRect from '../utils/getClientRect'; 4 | 5 | /** 6 | * Loop trough the list of modifiers and run them in order, 7 | * each of them will then edit the data object. 8 | * @method 9 | * @memberof Popper.Utils 10 | * @param {dataObject} data 11 | * @param {Array} modifiers 12 | * @param {String} ends - Optional modifier name used as stopper 13 | * @returns {dataObject} 14 | */ 15 | export default function runModifiers(modifiers, data, ends) { 16 | const modifiersToRun = ends === undefined 17 | ? modifiers 18 | : modifiers.slice(0, findIndex(modifiers, 'name', ends)); 19 | 20 | modifiersToRun.forEach(modifier => { 21 | if (modifier['function']) { // eslint-disable-line dot-notation 22 | console.warn('`modifier.function` is deprecated, use `modifier.fn`!'); 23 | } 24 | const fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation 25 | if (modifier.enabled && isFunction(fn)) { 26 | // Add properties to offsets to make them a complete clientRect object 27 | // we do this before each modifier to make sure the previous one doesn't 28 | // mess with these values 29 | data.offsets.popper = getClientRect(data.offsets.popper); 30 | data.offsets.reference = getClientRect(data.offsets.reference); 31 | 32 | data = fn(data, modifier); 33 | } 34 | }); 35 | 36 | return data; 37 | } 38 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/setAttributes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Set the attributes to the given popper 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Element} element - Element to apply the attributes to 6 | * @argument {Object} styles 7 | * Object with a list of properties and values which will be applied to the element 8 | */ 9 | export default function setAttributes(element, attributes) { 10 | Object.keys(attributes).forEach(function(prop) { 11 | const value = attributes[prop]; 12 | if (value !== false) { 13 | element.setAttribute(prop, attributes[prop]); 14 | } else { 15 | element.removeAttribute(prop); 16 | } 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/setStyles.js: -------------------------------------------------------------------------------- 1 | import isNumeric from './isNumeric'; 2 | 3 | /** 4 | * Set the style to the given popper 5 | * @method 6 | * @memberof Popper.Utils 7 | * @argument {Element} element - Element to apply the style to 8 | * @argument {Object} styles 9 | * Object with a list of properties and values which will be applied to the element 10 | */ 11 | export default function setStyles(element, styles) { 12 | Object.keys(styles).forEach(prop => { 13 | let unit = ''; 14 | // add unit if the value is numeric and is one of the following 15 | if ( 16 | ['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== 17 | -1 && 18 | isNumeric(styles[prop]) 19 | ) { 20 | unit = 'px'; 21 | } 22 | element.style[prop] = styles[prop] + unit; 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Scripts/src/utils/setupEventListeners.js: -------------------------------------------------------------------------------- 1 | import getScrollParent from './getScrollParent'; 2 | import getWindow from './getWindow'; 3 | 4 | function attachToScrollParents(scrollParent, event, callback, scrollParents) { 5 | const isBody = scrollParent.nodeName === 'BODY'; 6 | const target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent; 7 | target.addEventListener(event, callback, { passive: true }); 8 | 9 | if (!isBody) { 10 | attachToScrollParents( 11 | getScrollParent(target.parentNode), 12 | event, 13 | callback, 14 | scrollParents 15 | ); 16 | } 17 | scrollParents.push(target); 18 | } 19 | 20 | /** 21 | * Setup needed event listeners used to update the popper position 22 | * @method 23 | * @memberof Popper.Utils 24 | * @private 25 | */ 26 | export default function setupEventListeners( 27 | reference, 28 | options, 29 | state, 30 | updateBound 31 | ) { 32 | // Resize event listener on window 33 | state.updateBound = updateBound; 34 | getWindow(reference).addEventListener('resize', state.updateBound, { passive: true }); 35 | 36 | // Scroll event listener on scroll parents 37 | const scrollElement = getScrollParent(reference); 38 | attachToScrollParents( 39 | scrollElement, 40 | 'scroll', 41 | state.updateBound, 42 | state.scrollParents 43 | ); 44 | state.scrollElement = scrollElement; 45 | state.eventsEnabled = true; 46 | 47 | return state; 48 | } 49 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Startup.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | using Microsoft.Owin; 5 | using Owin; 6 | 7 | [assembly: OwinStartup(typeof(graph_tutorial.Startup))] 8 | 9 | namespace graph_tutorial 10 | { 11 | public partial class Startup 12 | { 13 | public void Configuration(IAppBuilder app) 14 | { 15 | ConfigureAuth(app); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "About"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

6 | 7 |

Use this area to provide additional information.

8 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Views/Home/Contact.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Contact"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

6 | 7 |
8 | One Microsoft Way
9 | Redmond, WA 98052-6399
10 | P: 11 | 425.555.0100 12 |
13 | 14 |
15 | Support: Support@example.com
16 | Marketing: Marketing@example.com 17 |
-------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 |  5 | 6 | @{ 7 | ViewBag.Current = "Home"; 8 | } 9 | 10 |
11 |

ASP.NET Graph Tutorial

12 |

This sample app shows how to use the Microsoft Graph API to access a user's data from ASP.NET

13 | @if (Request.IsAuthenticated) 14 | { 15 |

Welcome @ViewBag.User.DisplayName!

16 |

Use the navigation bar at the top of the page to get started.

17 | } 18 | else 19 | { 20 | @Html.ActionLink("Click here to sign in", "SignIn", "Account", new { area = "" }, new { @class = "btn btn-primary btn-large" }) 21 | } 22 |
23 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Error 6 | 7 | 8 |
9 |

Error.

10 |

An error occurred while processing your request.

11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Views/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } 4 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Web.Debug.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/Web.Release.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Demos/02-add-aad-auth/graph-tutorial/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoftgraph/msgraph-training-aspnetmvcapp/08112c10ecf3107da7c6ef9eb5311672b1270649/Demos/02-add-aad-auth/graph-tutorial/favicon.ico -------------------------------------------------------------------------------- /Demos/03-add-msgraph/README.md: -------------------------------------------------------------------------------- 1 | # Demo: Add Microsoft Graph 2 | 3 | This completed project is the result of the lab exercise **Add Microsoft Graph** that is referenced in the [README](../../README.md) in this repo. 4 | 5 | ## Prerequisites 6 | 7 | - [Microsoft 365 tenant](https://developer.microsoft.com/office/dev-program?ocid=MSlearn) 8 | - [.NET Framework 4.8](https://dotnet.microsoft.com/download/dotnet-framework) 9 | - [Visual Studio 2022](https://visualstudio.microsoft.com/vs/) 10 | 11 | ## Run this Completed Project 12 | 13 | - Rename the file **PrivateSettings.config.example** to **PrivateSettings.config** 14 | - Update the properties in the **PrivateSettings.config** with the values you collected in the first exercise. 15 | - Build and run the application by following the instructions in the lab exercise associated with this demo. -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.2.32505.173 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "graph-tutorial", "graph-tutorial\graph-tutorial.csproj", "{3839C133-E2D0-466C-ABB3-E92ABCDB6388}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3839C133-E2D0-466C-ABB3-E92ABCDB6388}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {3839C133-E2D0-466C-ABB3-E92ABCDB6388}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {3839C133-E2D0-466C-ABB3-E92ABCDB6388}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {3839C133-E2D0-466C-ABB3-E92ABCDB6388}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {5D8392F3-02AC-499D-9495-D6ED8CE615C5} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/App_Start/BundleConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Optimization; 3 | 4 | namespace graph_tutorial 5 | { 6 | public class BundleConfig 7 | { 8 | // For more information on bundling, visit https://go.microsoft.com/fwlink/?LinkId=301862 9 | public static void RegisterBundles(BundleCollection bundles) 10 | { 11 | bundles.Add(new ScriptBundle("~/bundles/jquery").Include( 12 | "~/Scripts/jquery-{version}.js")); 13 | 14 | bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include( 15 | "~/Scripts/jquery.validate*")); 16 | 17 | // Use the development version of Modernizr to develop with and learn from. Then, when you're 18 | // ready for production, use the build tool at https://modernizr.com to pick only the tests you need. 19 | bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( 20 | "~/Scripts/modernizr-*")); 21 | 22 | bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include( 23 | "~/Scripts/bootstrap.js")); 24 | 25 | bundles.Add(new StyleBundle("~/Content/css").Include( 26 | "~/Content/bootstrap.css", 27 | "~/Content/site.css")); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/App_Start/FilterConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Mvc; 3 | 4 | namespace graph_tutorial 5 | { 6 | public class FilterConfig 7 | { 8 | public static void RegisterGlobalFilters(GlobalFilterCollection filters) 9 | { 10 | filters.Add(new HandleErrorAttribute()); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace graph_tutorial 9 | { 10 | public class RouteConfig 11 | { 12 | public static void RegisterRoutes(RouteCollection routes) 13 | { 14 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 15 | 16 | routes.MapRoute( 17 | name: "Default", 18 | url: "{controller}/{action}/{id}", 19 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 20 | ); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Content/Site.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT license. 4 | */ 5 | 6 | body { 7 | padding-top: 4.5rem; 8 | } 9 | 10 | .alert-pre { 11 | word-wrap: break-word; 12 | word-break: break-all; 13 | white-space: pre-wrap; 14 | } -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Controllers/AccountController.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | using Microsoft.Owin.Security; 5 | using Microsoft.Owin.Security.Cookies; 6 | using Microsoft.Owin.Security.OpenIdConnect; 7 | using System.Security.Claims; 8 | using System.Web; 9 | using System.Web.Mvc; 10 | using graph_tutorial.TokenStorage; 11 | 12 | namespace graph_tutorial.Controllers 13 | { 14 | public class AccountController : Controller 15 | { 16 | public void SignIn() 17 | { 18 | if (!Request.IsAuthenticated) 19 | { 20 | // Signal OWIN to send an authorization request to Azure 21 | Request.GetOwinContext().Authentication.Challenge( 22 | new AuthenticationProperties { RedirectUri = "/" }, 23 | OpenIdConnectAuthenticationDefaults.AuthenticationType); 24 | } 25 | } 26 | 27 | public ActionResult SignOut() 28 | { 29 | if (Request.IsAuthenticated) 30 | { 31 | var tokenStore = new SessionTokenStore(null, 32 | System.Web.HttpContext.Current, ClaimsPrincipal.Current); 33 | 34 | tokenStore.Clear(); 35 | 36 | Request.GetOwinContext().Authentication.SignOut( 37 | CookieAuthenticationDefaults.AuthenticationType); 38 | } 39 | 40 | return RedirectToAction("Index", "Home"); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Controllers/BaseController.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | using graph_tutorial.Models; 5 | using System.Collections.Generic; 6 | using System.Web.Mvc; 7 | using graph_tutorial.TokenStorage; 8 | using System.Security.Claims; 9 | using System.Web; 10 | using Microsoft.Owin.Security.Cookies; 11 | 12 | namespace graph_tutorial.Controllers 13 | { 14 | public abstract class BaseController : Controller 15 | { 16 | protected void Flash(string message, string debug = null) 17 | { 18 | var alerts = TempData.ContainsKey(Alert.AlertKey) ? 19 | (List)TempData[Alert.AlertKey] : 20 | new List(); 21 | 22 | alerts.Add(new Alert 23 | { 24 | Message = message, 25 | Debug = debug 26 | }); 27 | 28 | TempData[Alert.AlertKey] = alerts; 29 | } 30 | 31 | protected override void OnActionExecuting(ActionExecutingContext filterContext) 32 | { 33 | if (Request.IsAuthenticated) 34 | { 35 | // Get the user's token cache 36 | var tokenStore = new SessionTokenStore(null, 37 | System.Web.HttpContext.Current, ClaimsPrincipal.Current); 38 | 39 | if (tokenStore.HasData()) 40 | { 41 | // Add the user to the view bag 42 | ViewBag.User = tokenStore.GetUserDetails(); 43 | } 44 | else 45 | { 46 | // The session has lost data. This happens often 47 | // when debugging. Log out so the user can log back in 48 | Request.GetOwinContext().Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType); 49 | filterContext.Result = RedirectToAction("Index", "Home"); 50 | } 51 | } 52 | 53 | base.OnActionExecuting(filterContext); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Controllers/CalendarController.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | using graph_tutorial.Helpers; 5 | using System; 6 | using System.Threading.Tasks; 7 | using System.Web.Mvc; 8 | 9 | namespace graph_tutorial.Controllers 10 | { 11 | public class CalendarController : BaseController 12 | { 13 | // GET: Calendar 14 | [Authorize] 15 | public async Task Index() 16 | { 17 | var events = await GraphHelper.GetEventsAsync(); 18 | 19 | // Change start and end dates from UTC to local time 20 | foreach (var ev in events) 21 | { 22 | ev.Start.DateTime = DateTime.Parse(ev.Start.DateTime).ToLocalTime().ToString(); 23 | ev.Start.TimeZone = TimeZoneInfo.Local.Id; 24 | ev.End.DateTime = DateTime.Parse(ev.End.DateTime).ToLocalTime().ToString(); 25 | ev.End.TimeZone = TimeZoneInfo.Local.Id; 26 | } 27 | 28 | return View(events); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Web; 8 | using System.Web.Mvc; 9 | 10 | namespace graph_tutorial.Controllers 11 | { 12 | public class HomeController : BaseController 13 | { 14 | public ActionResult Index() 15 | { 16 | return View(); 17 | } 18 | 19 | public ActionResult About() 20 | { 21 | ViewBag.Message = "Your application description page."; 22 | 23 | return View(); 24 | } 25 | 26 | public ActionResult Contact() 27 | { 28 | ViewBag.Message = "Your contact page."; 29 | 30 | return View(); 31 | } 32 | 33 | public ActionResult Error(string message, string debug) 34 | { 35 | Flash(message, debug); 36 | return RedirectToAction("Index"); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="graph_tutorial.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Optimization; 7 | using System.Web.Routing; 8 | 9 | namespace graph_tutorial 10 | { 11 | public class MvcApplication : System.Web.HttpApplication 12 | { 13 | protected void Application_Start() 14 | { 15 | AreaRegistration.RegisterAllAreas(); 16 | FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 17 | RouteConfig.RegisterRoutes(RouteTable.Routes); 18 | BundleConfig.RegisterBundles(BundleTable.Bundles); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Models/Alert.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | namespace graph_tutorial.Models 5 | { 6 | // Used to flash error messages in the app's views. 7 | public class Alert 8 | { 9 | public const string AlertKey = "TempDataAlerts"; 10 | public string Message { get; set; } 11 | public string Debug { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Models/CachedUser.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | namespace graph_tutorial.Models 5 | { 6 | // Simple class to serialize user details 7 | public class CachedUser 8 | { 9 | public string DisplayName { get; set; } 10 | public string Email { get; set; } 11 | public string Avatar { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("graph_tutorial")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("graph_tutorial")] 13 | [assembly: AssemblyCopyright("Copyright © 2022")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("78062d3f-74c7-42ac-8885-7fe5f61a094c")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/methods/destroy.js: -------------------------------------------------------------------------------- 1 | import isModifierEnabled from '../utils/isModifierEnabled'; 2 | import getSupportedPropertyName from '../utils/getSupportedPropertyName'; 3 | 4 | /** 5 | * Destroys the popper. 6 | * @method 7 | * @memberof Popper 8 | */ 9 | export default function destroy() { 10 | this.state.isDestroyed = true; 11 | 12 | // touch DOM only if `applyStyle` modifier is enabled 13 | if (isModifierEnabled(this.modifiers, 'applyStyle')) { 14 | this.popper.removeAttribute('x-placement'); 15 | this.popper.style.position = ''; 16 | this.popper.style.top = ''; 17 | this.popper.style.left = ''; 18 | this.popper.style.right = ''; 19 | this.popper.style.bottom = ''; 20 | this.popper.style.willChange = ''; 21 | this.popper.style[getSupportedPropertyName('transform')] = ''; 22 | } 23 | 24 | this.disableEventListeners(); 25 | 26 | // remove the popper if user explicitly asked for the deletion on destroy 27 | // do not use `remove` because IE11 doesn't support it 28 | if (this.options.removeOnDestroy) { 29 | this.popper.parentNode.removeChild(this.popper); 30 | } 31 | return this; 32 | } 33 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/methods/disableEventListeners.js: -------------------------------------------------------------------------------- 1 | import removeEventListeners from '../utils/removeEventListeners'; 2 | 3 | /** 4 | * It will remove resize/scroll events and won't recalculate popper position 5 | * when they are triggered. It also won't trigger `onUpdate` callback anymore, 6 | * unless you call `update` method manually. 7 | * @method 8 | * @memberof Popper 9 | */ 10 | export default function disableEventListeners() { 11 | if (this.state.eventsEnabled) { 12 | cancelAnimationFrame(this.scheduleUpdate); 13 | this.state = removeEventListeners(this.reference, this.state); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/methods/enableEventListeners.js: -------------------------------------------------------------------------------- 1 | import setupEventListeners from '../utils/setupEventListeners'; 2 | 3 | /** 4 | * It will add resize/scroll events and start recalculating 5 | * position of the popper element when they are triggered. 6 | * @method 7 | * @memberof Popper 8 | */ 9 | export default function enableEventListeners() { 10 | if (!this.state.eventsEnabled) { 11 | this.state = setupEventListeners( 12 | this.reference, 13 | this.options, 14 | this.state, 15 | this.scheduleUpdate 16 | ); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/methods/placements.js: -------------------------------------------------------------------------------- 1 | /** 2 | * List of accepted placements to use as values of the `placement` option.
3 | * Valid placements are: 4 | * - `auto` 5 | * - `top` 6 | * - `right` 7 | * - `bottom` 8 | * - `left` 9 | * 10 | * Each placement can have a variation from this list: 11 | * - `-start` 12 | * - `-end` 13 | * 14 | * Variations are interpreted easily if you think of them as the left to right 15 | * written languages. Horizontally (`top` and `bottom`), `start` is left and `end` 16 | * is right.
17 | * Vertically (`left` and `right`), `start` is top and `end` is bottom. 18 | * 19 | * Some valid examples are: 20 | * - `top-end` (on top of reference, right aligned) 21 | * - `right-start` (on right of reference, top aligned) 22 | * - `bottom` (on bottom, centered) 23 | * - `auto-end` (on the side with more space available, alignment depends by placement) 24 | * 25 | * @static 26 | * @type {Array} 27 | * @enum {String} 28 | * @readonly 29 | * @method placements 30 | * @memberof Popper 31 | */ 32 | export default [ 33 | 'auto-start', 34 | 'auto', 35 | 'auto-end', 36 | 'top-start', 37 | 'top', 38 | 'top-end', 39 | 'right-start', 40 | 'right', 41 | 'right-end', 42 | 'bottom-end', 43 | 'bottom', 44 | 'bottom-start', 45 | 'left-end', 46 | 'left', 47 | 'left-start', 48 | ]; 49 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/modifiers/hide.js: -------------------------------------------------------------------------------- 1 | import isModifierRequired from '../utils/isModifierRequired'; 2 | import find from '../utils/find'; 3 | 4 | /** 5 | * @function 6 | * @memberof Modifiers 7 | * @argument {Object} data - The data object generated by update method 8 | * @argument {Object} options - Modifiers configuration and options 9 | * @returns {Object} The data object, properly modified 10 | */ 11 | export default function hide(data) { 12 | if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) { 13 | return data; 14 | } 15 | 16 | const refRect = data.offsets.reference; 17 | const bound = find( 18 | data.instance.modifiers, 19 | modifier => modifier.name === 'preventOverflow' 20 | ).boundaries; 21 | 22 | if ( 23 | refRect.bottom < bound.top || 24 | refRect.left > bound.right || 25 | refRect.top > bound.bottom || 26 | refRect.right < bound.left 27 | ) { 28 | // Avoid unnecessary DOM access if visibility hasn't changed 29 | if (data.hide === true) { 30 | return data; 31 | } 32 | 33 | data.hide = true; 34 | data.attributes['x-out-of-boundaries'] = ''; 35 | } else { 36 | // Avoid unnecessary DOM access if visibility hasn't changed 37 | if (data.hide === false) { 38 | return data; 39 | } 40 | 41 | data.hide = false; 42 | data.attributes['x-out-of-boundaries'] = false; 43 | } 44 | 45 | return data; 46 | } 47 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/modifiers/inner.js: -------------------------------------------------------------------------------- 1 | import getClientRect from '../utils/getClientRect'; 2 | import getOppositePlacement from '../utils/getOppositePlacement'; 3 | 4 | /** 5 | * @function 6 | * @memberof Modifiers 7 | * @argument {Object} data - The data object generated by `update` method 8 | * @argument {Object} options - Modifiers configuration and options 9 | * @returns {Object} The data object, properly modified 10 | */ 11 | export default function inner(data) { 12 | const placement = data.placement; 13 | const basePlacement = placement.split('-')[0]; 14 | const { popper, reference } = data.offsets; 15 | const isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1; 16 | 17 | const subtractLength = ['top', 'left'].indexOf(basePlacement) === -1; 18 | 19 | popper[isHoriz ? 'left' : 'top'] = 20 | reference[basePlacement] - 21 | (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0); 22 | 23 | data.placement = getOppositePlacement(placement); 24 | data.offsets.popper = getClientRect(popper); 25 | 26 | return data; 27 | } 28 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/modifiers/keepTogether.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @function 3 | * @memberof Modifiers 4 | * @argument {Object} data - The data object generated by update method 5 | * @argument {Object} options - Modifiers configuration and options 6 | * @returns {Object} The data object, properly modified 7 | */ 8 | export default function keepTogether(data) { 9 | const { popper, reference } = data.offsets; 10 | const placement = data.placement.split('-')[0]; 11 | const floor = Math.floor; 12 | const isVertical = ['top', 'bottom'].indexOf(placement) !== -1; 13 | const side = isVertical ? 'right' : 'bottom'; 14 | const opSide = isVertical ? 'left' : 'top'; 15 | const measurement = isVertical ? 'width' : 'height'; 16 | 17 | if (popper[side] < floor(reference[opSide])) { 18 | data.offsets.popper[opSide] = 19 | floor(reference[opSide]) - popper[measurement]; 20 | } 21 | if (popper[opSide] > floor(reference[side])) { 22 | data.offsets.popper[opSide] = floor(reference[side]); 23 | } 24 | 25 | return data; 26 | } 27 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/modifiers/shift.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @function 3 | * @memberof Modifiers 4 | * @argument {Object} data - The data object generated by `update` method 5 | * @argument {Object} options - Modifiers configuration and options 6 | * @returns {Object} The data object, properly modified 7 | */ 8 | export default function shift(data) { 9 | const placement = data.placement; 10 | const basePlacement = placement.split('-')[0]; 11 | const shiftvariation = placement.split('-')[1]; 12 | 13 | // if shift shiftvariation is specified, run the modifier 14 | if (shiftvariation) { 15 | const { reference, popper } = data.offsets; 16 | const isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1; 17 | const side = isVertical ? 'left' : 'top'; 18 | const measurement = isVertical ? 'width' : 'height'; 19 | 20 | const shiftOffsets = { 21 | start: { [side]: reference[side] }, 22 | end: { 23 | [side]: reference[side] + reference[measurement] - popper[measurement], 24 | }, 25 | }; 26 | 27 | data.offsets.popper = { ...popper, ...shiftOffsets[shiftvariation] }; 28 | } 29 | 30 | return data; 31 | } 32 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/clockwise.js: -------------------------------------------------------------------------------- 1 | import placements from '../methods/placements'; 2 | 3 | // Get rid of `auto` `auto-start` and `auto-end` 4 | const validPlacements = placements.slice(3); 5 | 6 | /** 7 | * Given an initial placement, returns all the subsequent placements 8 | * clockwise (or counter-clockwise). 9 | * 10 | * @method 11 | * @memberof Popper.Utils 12 | * @argument {String} placement - A valid placement (it accepts variations) 13 | * @argument {Boolean} counter - Set to true to walk the placements counterclockwise 14 | * @returns {Array} placements including their variations 15 | */ 16 | export default function clockwise(placement, counter = false) { 17 | const index = validPlacements.indexOf(placement); 18 | const arr = validPlacements 19 | .slice(index + 1) 20 | .concat(validPlacements.slice(0, index)); 21 | return counter ? arr.reverse() : arr; 22 | } 23 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/computeAutoPlacement.js: -------------------------------------------------------------------------------- 1 | import getBoundaries from '../utils/getBoundaries'; 2 | 3 | function getArea({ width, height }) { 4 | return width * height; 5 | } 6 | 7 | /** 8 | * Utility used to transform the `auto` placement to the placement with more 9 | * available space. 10 | * @method 11 | * @memberof Popper.Utils 12 | * @argument {Object} data - The data object generated by update method 13 | * @argument {Object} options - Modifiers configuration and options 14 | * @returns {Object} The data object, properly modified 15 | */ 16 | export default function computeAutoPlacement( 17 | placement, 18 | refRect, 19 | popper, 20 | reference, 21 | boundariesElement, 22 | padding = 0 23 | ) { 24 | if (placement.indexOf('auto') === -1) { 25 | return placement; 26 | } 27 | 28 | const boundaries = getBoundaries( 29 | popper, 30 | reference, 31 | padding, 32 | boundariesElement 33 | ); 34 | 35 | const rects = { 36 | top: { 37 | width: boundaries.width, 38 | height: refRect.top - boundaries.top, 39 | }, 40 | right: { 41 | width: boundaries.right - refRect.right, 42 | height: boundaries.height, 43 | }, 44 | bottom: { 45 | width: boundaries.width, 46 | height: boundaries.bottom - refRect.bottom, 47 | }, 48 | left: { 49 | width: refRect.left - boundaries.left, 50 | height: boundaries.height, 51 | }, 52 | }; 53 | 54 | const sortedAreas = Object.keys(rects) 55 | .map(key => ({ 56 | key, 57 | ...rects[key], 58 | area: getArea(rects[key]), 59 | })) 60 | .sort((a, b) => b.area - a.area); 61 | 62 | const filteredAreas = sortedAreas.filter( 63 | ({ width, height }) => 64 | width >= popper.clientWidth && height >= popper.clientHeight 65 | ); 66 | 67 | const computedPlacement = filteredAreas.length > 0 68 | ? filteredAreas[0].key 69 | : sortedAreas[0].key; 70 | 71 | const variation = placement.split('-')[1]; 72 | 73 | return computedPlacement + (variation ? `-${variation}` : ''); 74 | } 75 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/debounce.js: -------------------------------------------------------------------------------- 1 | import isBrowser from './isBrowser'; 2 | 3 | const timeoutDuration = (function(){ 4 | const longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox']; 5 | for (let i = 0; i < longerTimeoutBrowsers.length; i += 1) { 6 | if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) { 7 | return 1; 8 | } 9 | } 10 | return 0; 11 | }()); 12 | 13 | export function microtaskDebounce(fn) { 14 | let called = false 15 | return () => { 16 | if (called) { 17 | return 18 | } 19 | called = true 20 | window.Promise.resolve().then(() => { 21 | called = false 22 | fn() 23 | }) 24 | } 25 | } 26 | 27 | export function taskDebounce(fn) { 28 | let scheduled = false; 29 | return () => { 30 | if (!scheduled) { 31 | scheduled = true; 32 | setTimeout(() => { 33 | scheduled = false; 34 | fn(); 35 | }, timeoutDuration); 36 | } 37 | }; 38 | } 39 | 40 | const supportsMicroTasks = isBrowser && window.Promise 41 | 42 | 43 | /** 44 | * Create a debounced version of a method, that's asynchronously deferred 45 | * but called in the minimum time possible. 46 | * 47 | * @method 48 | * @memberof Popper.Utils 49 | * @argument {Function} fn 50 | * @returns {Function} 51 | */ 52 | export default (supportsMicroTasks 53 | ? microtaskDebounce 54 | : taskDebounce); 55 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/find.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Mimics the `find` method of Array 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Array} arr 6 | * @argument prop 7 | * @argument value 8 | * @returns index or -1 9 | */ 10 | export default function find(arr, check) { 11 | // use native find if supported 12 | if (Array.prototype.find) { 13 | return arr.find(check); 14 | } 15 | 16 | // use `filter` to obtain the same behavior of `find` 17 | return arr.filter(check)[0]; 18 | } 19 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/findCommonOffsetParent.js: -------------------------------------------------------------------------------- 1 | import isOffsetContainer from './isOffsetContainer'; 2 | import getRoot from './getRoot'; 3 | import getOffsetParent from './getOffsetParent'; 4 | 5 | /** 6 | * Finds the offset parent common to the two provided nodes 7 | * @method 8 | * @memberof Popper.Utils 9 | * @argument {Element} element1 10 | * @argument {Element} element2 11 | * @returns {Element} common offset parent 12 | */ 13 | export default function findCommonOffsetParent(element1, element2) { 14 | // This check is needed to avoid errors in case one of the elements isn't defined for any reason 15 | if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) { 16 | return document.documentElement; 17 | } 18 | 19 | // Here we make sure to give as "start" the element that comes first in the DOM 20 | const order = 21 | element1.compareDocumentPosition(element2) & 22 | Node.DOCUMENT_POSITION_FOLLOWING; 23 | const start = order ? element1 : element2; 24 | const end = order ? element2 : element1; 25 | 26 | // Get common ancestor container 27 | const range = document.createRange(); 28 | range.setStart(start, 0); 29 | range.setEnd(end, 0); 30 | const { commonAncestorContainer } = range; 31 | 32 | // Both nodes are inside #document 33 | if ( 34 | (element1 !== commonAncestorContainer && 35 | element2 !== commonAncestorContainer) || 36 | start.contains(end) 37 | ) { 38 | if (isOffsetContainer(commonAncestorContainer)) { 39 | return commonAncestorContainer; 40 | } 41 | 42 | return getOffsetParent(commonAncestorContainer); 43 | } 44 | 45 | // one of the nodes is inside shadowDOM, find which one 46 | const element1root = getRoot(element1); 47 | if (element1root.host) { 48 | return findCommonOffsetParent(element1root.host, element2); 49 | } else { 50 | return findCommonOffsetParent(element1, getRoot(element2).host); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/findIndex.js: -------------------------------------------------------------------------------- 1 | import find from './find'; 2 | 3 | /** 4 | * Return the index of the matching object 5 | * @method 6 | * @memberof Popper.Utils 7 | * @argument {Array} arr 8 | * @argument prop 9 | * @argument value 10 | * @returns index or -1 11 | */ 12 | export default function findIndex(arr, prop, value) { 13 | // use native findIndex if supported 14 | if (Array.prototype.findIndex) { 15 | return arr.findIndex(cur => cur[prop] === value); 16 | } 17 | 18 | // use `find` + `indexOf` if `findIndex` isn't supported 19 | const match = find(arr, obj => obj[prop] === value); 20 | return arr.indexOf(match); 21 | } 22 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/getBordersSize.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Helper to detect borders of a given element 3 | * @method 4 | * @memberof Popper.Utils 5 | * @param {CSSStyleDeclaration} styles 6 | * Result of `getStyleComputedProperty` on the given element 7 | * @param {String} axis - `x` or `y` 8 | * @return {number} borders - The borders size of the given axis 9 | */ 10 | 11 | export default function getBordersSize(styles, axis) { 12 | const sideA = axis === 'x' ? 'Left' : 'Top'; 13 | const sideB = sideA === 'Left' ? 'Right' : 'Bottom'; 14 | 15 | return ( 16 | parseFloat(styles[`border${sideA}Width`]) + 17 | parseFloat(styles[`border${sideB}Width`]) 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/getClientRect.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Given element offsets, generate an output similar to getBoundingClientRect 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Object} offsets 6 | * @returns {Object} ClientRect like output 7 | */ 8 | export default function getClientRect(offsets) { 9 | return { 10 | ...offsets, 11 | right: offsets.left + offsets.width, 12 | bottom: offsets.top + offsets.height, 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/getFixedPositionOffsetParent.js: -------------------------------------------------------------------------------- 1 | import getStyleComputedProperty from './getStyleComputedProperty'; 2 | import isIE from './isIE'; 3 | /** 4 | * Finds the first parent of an element that has a transformed property defined 5 | * @method 6 | * @memberof Popper.Utils 7 | * @argument {Element} element 8 | * @returns {Element} first transformed parent or documentElement 9 | */ 10 | 11 | export default function getFixedPositionOffsetParent(element) { 12 | // This check is needed to avoid errors in case one of the elements isn't defined for any reason 13 | if (!element || !element.parentElement || isIE()) { 14 | return document.documentElement; 15 | } 16 | let el = element.parentElement; 17 | while (el && getStyleComputedProperty(el, 'transform') === 'none') { 18 | el = el.parentElement; 19 | } 20 | return el || document.documentElement; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/getOffsetParent.js: -------------------------------------------------------------------------------- 1 | import getStyleComputedProperty from './getStyleComputedProperty'; 2 | import isIE from './isIE'; 3 | /** 4 | * Returns the offset parent of the given element 5 | * @method 6 | * @memberof Popper.Utils 7 | * @argument {Element} element 8 | * @returns {Element} offset parent 9 | */ 10 | export default function getOffsetParent(element) { 11 | if (!element) { 12 | return document.documentElement; 13 | } 14 | 15 | const noOffsetParent = isIE(10) ? document.body : null; 16 | 17 | // NOTE: 1 DOM access here 18 | let offsetParent = element.offsetParent || null; 19 | // Skip hidden elements which don't have an offsetParent 20 | while (offsetParent === noOffsetParent && element.nextElementSibling) { 21 | offsetParent = (element = element.nextElementSibling).offsetParent; 22 | } 23 | 24 | const nodeName = offsetParent && offsetParent.nodeName; 25 | 26 | if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') { 27 | return element ? element.ownerDocument.documentElement : document.documentElement; 28 | } 29 | 30 | // .offsetParent will return the closest TH, TD or TABLE in case 31 | // no offsetParent is present, I hate this job... 32 | if ( 33 | ['TH', 'TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && 34 | getStyleComputedProperty(offsetParent, 'position') === 'static' 35 | ) { 36 | return getOffsetParent(offsetParent); 37 | } 38 | 39 | return offsetParent; 40 | } 41 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/getOffsetRect.js: -------------------------------------------------------------------------------- 1 | import getWindowSizes from './getWindowSizes'; 2 | import getClientRect from './getClientRect'; 3 | 4 | /** 5 | * Get the position of the given element, relative to its offset parent 6 | * @method 7 | * @memberof Popper.Utils 8 | * @param {Element} element 9 | * @return {Object} position - Coordinates of the element and its `scrollTop` 10 | */ 11 | export default function getOffsetRect(element) { 12 | let elementRect; 13 | if (element.nodeName === 'HTML') { 14 | const { width, height } = getWindowSizes(element.ownerDocument); 15 | elementRect = { 16 | width, 17 | height, 18 | left: 0, 19 | top: 0, 20 | }; 21 | } else { 22 | elementRect = { 23 | width: element.offsetWidth, 24 | height: element.offsetHeight, 25 | left: element.offsetLeft, 26 | top: element.offsetTop, 27 | }; 28 | } 29 | 30 | // position 31 | return getClientRect(elementRect); 32 | } 33 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/getOppositePlacement.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the opposite placement of the given one 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {String} placement 6 | * @returns {String} flipped placement 7 | */ 8 | export default function getOppositePlacement(placement) { 9 | const hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' }; 10 | return placement.replace(/left|right|bottom|top/g, matched => hash[matched]); 11 | } 12 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/getOppositeVariation.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the opposite placement variation of the given one 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {String} placement variation 6 | * @returns {String} flipped placement variation 7 | */ 8 | export default function getOppositeVariation(variation) { 9 | if (variation === 'end') { 10 | return 'start'; 11 | } else if (variation === 'start') { 12 | return 'end'; 13 | } 14 | return variation; 15 | } 16 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/getOuterSizes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the outer sizes of the given element (offset size + margins) 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Element} element 6 | * @returns {Object} object containing width and height properties 7 | */ 8 | export default function getOuterSizes(element) { 9 | const window = element.ownerDocument.defaultView; 10 | const styles = window.getComputedStyle(element); 11 | const x = parseFloat(styles.marginTop || 0) + parseFloat(styles.marginBottom || 0); 12 | const y = parseFloat(styles.marginLeft || 0) + parseFloat(styles.marginRight || 0); 13 | const result = { 14 | width: element.offsetWidth + y, 15 | height: element.offsetHeight + x, 16 | }; 17 | return result; 18 | } 19 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/getParentNode.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns the parentNode or the host of the element 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Element} element 6 | * @returns {Element} parent 7 | */ 8 | export default function getParentNode(element) { 9 | if (element.nodeName === 'HTML') { 10 | return element; 11 | } 12 | return element.parentNode || element.host; 13 | } 14 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/getPopperOffsets.js: -------------------------------------------------------------------------------- 1 | import getOuterSizes from './getOuterSizes'; 2 | import getOppositePlacement from './getOppositePlacement'; 3 | 4 | /** 5 | * Get offsets to the popper 6 | * @method 7 | * @memberof Popper.Utils 8 | * @param {Object} position - CSS position the Popper will get applied 9 | * @param {HTMLElement} popper - the popper element 10 | * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this) 11 | * @param {String} placement - one of the valid placement options 12 | * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper 13 | */ 14 | export default function getPopperOffsets(popper, referenceOffsets, placement) { 15 | placement = placement.split('-')[0]; 16 | 17 | // Get popper node sizes 18 | const popperRect = getOuterSizes(popper); 19 | 20 | // Add position, width and height to our offsets object 21 | const popperOffsets = { 22 | width: popperRect.width, 23 | height: popperRect.height, 24 | }; 25 | 26 | // depending by the popper placement we have to compute its offsets slightly differently 27 | const isHoriz = ['right', 'left'].indexOf(placement) !== -1; 28 | const mainSide = isHoriz ? 'top' : 'left'; 29 | const secondarySide = isHoriz ? 'left' : 'top'; 30 | const measurement = isHoriz ? 'height' : 'width'; 31 | const secondaryMeasurement = !isHoriz ? 'height' : 'width'; 32 | 33 | popperOffsets[mainSide] = 34 | referenceOffsets[mainSide] + 35 | referenceOffsets[measurement] / 2 - 36 | popperRect[measurement] / 2; 37 | if (placement === secondarySide) { 38 | popperOffsets[secondarySide] = 39 | referenceOffsets[secondarySide] - popperRect[secondaryMeasurement]; 40 | } else { 41 | popperOffsets[secondarySide] = 42 | referenceOffsets[getOppositePlacement(secondarySide)]; 43 | } 44 | 45 | return popperOffsets; 46 | } 47 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/getReferenceNode.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns the reference node of the reference object, or the reference object itself. 3 | * @method 4 | * @memberof Popper.Utils 5 | * @param {Element|Object} reference - the reference element (the popper will be relative to this) 6 | * @returns {Element} parent 7 | */ 8 | export default function getReferenceNode(reference) { 9 | return reference && reference.referenceNode ? reference.referenceNode : reference; 10 | } 11 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/getReferenceOffsets.js: -------------------------------------------------------------------------------- 1 | import findCommonOffsetParent from './findCommonOffsetParent'; 2 | import getOffsetRectRelativeToArbitraryNode from './getOffsetRectRelativeToArbitraryNode'; 3 | import getFixedPositionOffsetParent from './getFixedPositionOffsetParent'; 4 | import getReferenceNode from './getReferenceNode'; 5 | 6 | /** 7 | * Get offsets to the reference element 8 | * @method 9 | * @memberof Popper.Utils 10 | * @param {Object} state 11 | * @param {Element} popper - the popper element 12 | * @param {Element} reference - the reference element (the popper will be relative to this) 13 | * @param {Element} fixedPosition - is in fixed position mode 14 | * @returns {Object} An object containing the offsets which will be applied to the popper 15 | */ 16 | export default function getReferenceOffsets(state, popper, reference, fixedPosition = null) { 17 | const commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, getReferenceNode(reference)); 18 | return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition); 19 | } 20 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/getRoot.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Finds the root node (document, shadowDOM root) of the given element 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Element} node 6 | * @returns {Element} root node 7 | */ 8 | export default function getRoot(node) { 9 | if (node.parentNode !== null) { 10 | return getRoot(node.parentNode); 11 | } 12 | 13 | return node; 14 | } 15 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/getRoundedOffsets.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @function 3 | * @memberof Popper.Utils 4 | * @argument {Object} data - The data object generated by `update` method 5 | * @argument {Boolean} shouldRound - If the offsets should be rounded at all 6 | * @returns {Object} The popper's position offsets rounded 7 | * 8 | * The tale of pixel-perfect positioning. It's still not 100% perfect, but as 9 | * good as it can be within reason. 10 | * Discussion here: https://github.com/FezVrasta/popper.js/pull/715 11 | * 12 | * Low DPI screens cause a popper to be blurry if not using full pixels (Safari 13 | * as well on High DPI screens). 14 | * 15 | * Firefox prefers no rounding for positioning and does not have blurriness on 16 | * high DPI screens. 17 | * 18 | * Only horizontal placement and left/right values need to be considered. 19 | */ 20 | export default function getRoundedOffsets(data, shouldRound) { 21 | const { popper, reference } = data.offsets; 22 | const { round, floor } = Math; 23 | const noRound = v => v; 24 | 25 | const referenceWidth = round(reference.width); 26 | const popperWidth = round(popper.width); 27 | 28 | const isVertical = ['left', 'right'].indexOf(data.placement) !== -1; 29 | const isVariation = data.placement.indexOf('-') !== -1; 30 | const sameWidthParity = referenceWidth % 2 === popperWidth % 2; 31 | const bothOddWidth = referenceWidth % 2 === 1 && popperWidth % 2 === 1; 32 | 33 | const horizontalToInteger = !shouldRound 34 | ? noRound 35 | : isVertical || isVariation || sameWidthParity 36 | ? round 37 | : floor; 38 | const verticalToInteger = !shouldRound ? noRound : round; 39 | 40 | return { 41 | left: horizontalToInteger( 42 | bothOddWidth && !isVariation && shouldRound 43 | ? popper.left - 1 44 | : popper.left 45 | ), 46 | top: verticalToInteger(popper.top), 47 | bottom: verticalToInteger(popper.bottom), 48 | right: horizontalToInteger(popper.right), 49 | }; 50 | } 51 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/getScroll.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Gets the scroll value of the given element in the given side (top and left) 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Element} element 6 | * @argument {String} side `top` or `left` 7 | * @returns {number} amount of scrolled pixels 8 | */ 9 | export default function getScroll(element, side = 'top') { 10 | const upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft'; 11 | const nodeName = element.nodeName; 12 | 13 | if (nodeName === 'BODY' || nodeName === 'HTML') { 14 | const html = element.ownerDocument.documentElement; 15 | const scrollingElement = element.ownerDocument.scrollingElement || html; 16 | return scrollingElement[upperSide]; 17 | } 18 | 19 | return element[upperSide]; 20 | } 21 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/getScrollParent.js: -------------------------------------------------------------------------------- 1 | import getStyleComputedProperty from './getStyleComputedProperty'; 2 | import getParentNode from './getParentNode'; 3 | 4 | /** 5 | * Returns the scrolling parent of the given element 6 | * @method 7 | * @memberof Popper.Utils 8 | * @argument {Element} element 9 | * @returns {Element} scroll parent 10 | */ 11 | export default function getScrollParent(element) { 12 | // Return body, `getScroll` will take care to get the correct `scrollTop` from it 13 | if (!element) { 14 | return document.body 15 | } 16 | 17 | switch (element.nodeName) { 18 | case 'HTML': 19 | case 'BODY': 20 | return element.ownerDocument.body 21 | case '#document': 22 | return element.body 23 | } 24 | 25 | // Firefox want us to check `-x` and `-y` variations as well 26 | const { overflow, overflowX, overflowY } = getStyleComputedProperty(element); 27 | if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) { 28 | return element; 29 | } 30 | 31 | return getScrollParent(getParentNode(element)); 32 | } 33 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/getStyleComputedProperty.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get CSS computed property of the given element 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Eement} element 6 | * @argument {String} property 7 | */ 8 | export default function getStyleComputedProperty(element, property) { 9 | if (element.nodeType !== 1) { 10 | return []; 11 | } 12 | // NOTE: 1 DOM access here 13 | const window = element.ownerDocument.defaultView; 14 | const css = window.getComputedStyle(element, null); 15 | return property ? css[property] : css; 16 | } 17 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/getSupportedPropertyName.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the prefixed supported property name 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {String} property (camelCase) 6 | * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix) 7 | */ 8 | export default function getSupportedPropertyName(property) { 9 | const prefixes = [false, 'ms', 'Webkit', 'Moz', 'O']; 10 | const upperProp = property.charAt(0).toUpperCase() + property.slice(1); 11 | 12 | for (let i = 0; i < prefixes.length; i++) { 13 | const prefix = prefixes[i]; 14 | const toCheck = prefix ? `${prefix}${upperProp}` : property; 15 | if (typeof document.body.style[toCheck] !== 'undefined') { 16 | return toCheck; 17 | } 18 | } 19 | return null; 20 | } 21 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/getViewportOffsetRectRelativeToArtbitraryNode.js: -------------------------------------------------------------------------------- 1 | import getOffsetRectRelativeToArbitraryNode from './getOffsetRectRelativeToArbitraryNode'; 2 | import getScroll from './getScroll'; 3 | import getClientRect from './getClientRect'; 4 | 5 | export default function getViewportOffsetRectRelativeToArtbitraryNode(element, excludeScroll = false) { 6 | const html = element.ownerDocument.documentElement; 7 | const relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html); 8 | const width = Math.max(html.clientWidth, window.innerWidth || 0); 9 | const height = Math.max(html.clientHeight, window.innerHeight || 0); 10 | 11 | const scrollTop = !excludeScroll ? getScroll(html) : 0; 12 | const scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0; 13 | 14 | const offset = { 15 | top: scrollTop - relativeOffset.top + relativeOffset.marginTop, 16 | left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft, 17 | width, 18 | height, 19 | }; 20 | 21 | return getClientRect(offset); 22 | } 23 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/getWindow.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the window associated with the element 3 | * @argument {Element} element 4 | * @returns {Window} 5 | */ 6 | export default function getWindow(element) { 7 | const ownerDocument = element.ownerDocument; 8 | return ownerDocument ? ownerDocument.defaultView : window; 9 | } 10 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/getWindowSizes.js: -------------------------------------------------------------------------------- 1 | import isIE from './isIE'; 2 | 3 | function getSize(axis, body, html, computedStyle) { 4 | return Math.max( 5 | body[`offset${axis}`], 6 | body[`scroll${axis}`], 7 | html[`client${axis}`], 8 | html[`offset${axis}`], 9 | html[`scroll${axis}`], 10 | isIE(10) 11 | ? (parseInt(html[`offset${axis}`]) + 12 | parseInt(computedStyle[`margin${axis === 'Height' ? 'Top' : 'Left'}`]) + 13 | parseInt(computedStyle[`margin${axis === 'Height' ? 'Bottom' : 'Right'}`])) 14 | : 0 15 | ); 16 | } 17 | 18 | export default function getWindowSizes(document) { 19 | const body = document.body; 20 | const html = document.documentElement; 21 | const computedStyle = isIE(10) && getComputedStyle(html); 22 | 23 | return { 24 | height: getSize('Height', body, html, computedStyle), 25 | width: getSize('Width', body, html, computedStyle), 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/includeScroll.js: -------------------------------------------------------------------------------- 1 | import getScroll from './getScroll'; 2 | 3 | /* 4 | * Sum or subtract the element scroll values (left and top) from a given rect object 5 | * @method 6 | * @memberof Popper.Utils 7 | * @param {Object} rect - Rect object you want to change 8 | * @param {HTMLElement} element - The element from the function reads the scroll values 9 | * @param {Boolean} subtract - set to true if you want to subtract the scroll values 10 | * @return {Object} rect - The modifier rect object 11 | */ 12 | export default function includeScroll(rect, element, subtract = false) { 13 | const scrollTop = getScroll(element, 'top'); 14 | const scrollLeft = getScroll(element, 'left'); 15 | const modifier = subtract ? -1 : 1; 16 | rect.top += scrollTop * modifier; 17 | rect.bottom += scrollTop * modifier; 18 | rect.left += scrollLeft * modifier; 19 | rect.right += scrollLeft * modifier; 20 | return rect; 21 | } 22 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/isBrowser.js: -------------------------------------------------------------------------------- 1 | export default typeof window !== 'undefined' && typeof document !== 'undefined' && typeof navigator !== 'undefined'; 2 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/isFixed.js: -------------------------------------------------------------------------------- 1 | import getStyleComputedProperty from './getStyleComputedProperty'; 2 | import getParentNode from './getParentNode'; 3 | 4 | /** 5 | * Check if the given element is fixed or is inside a fixed parent 6 | * @method 7 | * @memberof Popper.Utils 8 | * @argument {Element} element 9 | * @argument {Element} customContainer 10 | * @returns {Boolean} answer to "isFixed?" 11 | */ 12 | export default function isFixed(element) { 13 | const nodeName = element.nodeName; 14 | if (nodeName === 'BODY' || nodeName === 'HTML') { 15 | return false; 16 | } 17 | if (getStyleComputedProperty(element, 'position') === 'fixed') { 18 | return true; 19 | } 20 | const parentNode = getParentNode(element); 21 | if (!parentNode) { 22 | return false; 23 | } 24 | return isFixed(parentNode); 25 | } 26 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/isFunction.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Check if the given variable is a function 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Any} functionToCheck - variable to check 6 | * @returns {Boolean} answer to: is a function? 7 | */ 8 | export default function isFunction(functionToCheck) { 9 | const getType = {}; 10 | return ( 11 | functionToCheck && 12 | getType.toString.call(functionToCheck) === '[object Function]' 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/isIE.js: -------------------------------------------------------------------------------- 1 | import isBrowser from './isBrowser'; 2 | 3 | const isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode); 4 | const isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent); 5 | 6 | /** 7 | * Determines if the browser is Internet Explorer 8 | * @method 9 | * @memberof Popper.Utils 10 | * @param {Number} version to check 11 | * @returns {Boolean} isIE 12 | */ 13 | export default function isIE(version) { 14 | if (version === 11) { 15 | return isIE11; 16 | } 17 | if (version === 10) { 18 | return isIE10; 19 | } 20 | return isIE11 || isIE10; 21 | } 22 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/isModifierEnabled.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Helper used to know if the given modifier is enabled. 3 | * @method 4 | * @memberof Popper.Utils 5 | * @returns {Boolean} 6 | */ 7 | export default function isModifierEnabled(modifiers, modifierName) { 8 | return modifiers.some( 9 | ({ name, enabled }) => enabled && name === modifierName 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/isModifierRequired.js: -------------------------------------------------------------------------------- 1 | import find from './find'; 2 | 3 | /** 4 | * Helper used to know if the given modifier depends from another one.
5 | * It checks if the needed modifier is listed and enabled. 6 | * @method 7 | * @memberof Popper.Utils 8 | * @param {Array} modifiers - list of modifiers 9 | * @param {String} requestingName - name of requesting modifier 10 | * @param {String} requestedName - name of requested modifier 11 | * @returns {Boolean} 12 | */ 13 | export default function isModifierRequired( 14 | modifiers, 15 | requestingName, 16 | requestedName 17 | ) { 18 | const requesting = find(modifiers, ({ name }) => name === requestingName); 19 | 20 | const isRequired = 21 | !!requesting && 22 | modifiers.some(modifier => { 23 | return ( 24 | modifier.name === requestedName && 25 | modifier.enabled && 26 | modifier.order < requesting.order 27 | ); 28 | }); 29 | 30 | if (!isRequired) { 31 | const requesting = `\`${requestingName}\``; 32 | const requested = `\`${requestedName}\``; 33 | console.warn( 34 | `${requested} modifier is required by ${requesting} modifier in order to work, be sure to include it before ${requesting}!` 35 | ); 36 | } 37 | return isRequired; 38 | } 39 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/isNumeric.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Tells if a given input is a number 3 | * @method 4 | * @memberof Popper.Utils 5 | * @param {*} input to check 6 | * @return {Boolean} 7 | */ 8 | export default function isNumeric(n) { 9 | return n !== '' && !isNaN(parseFloat(n)) && isFinite(n); 10 | } 11 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/isOffsetContainer.js: -------------------------------------------------------------------------------- 1 | import getOffsetParent from './getOffsetParent'; 2 | 3 | export default function isOffsetContainer(element) { 4 | const { nodeName } = element; 5 | if (nodeName === 'BODY') { 6 | return false; 7 | } 8 | return ( 9 | nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/removeEventListeners.js: -------------------------------------------------------------------------------- 1 | import getWindow from './getWindow'; 2 | 3 | /** 4 | * Remove event listeners used to update the popper position 5 | * @method 6 | * @memberof Popper.Utils 7 | * @private 8 | */ 9 | export default function removeEventListeners(reference, state) { 10 | // Remove resize event listener on window 11 | getWindow(reference).removeEventListener('resize', state.updateBound); 12 | 13 | // Remove scroll event listener on scroll parents 14 | state.scrollParents.forEach(target => { 15 | target.removeEventListener('scroll', state.updateBound); 16 | }); 17 | 18 | // Reset state 19 | state.updateBound = null; 20 | state.scrollParents = []; 21 | state.scrollElement = null; 22 | state.eventsEnabled = false; 23 | return state; 24 | } 25 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/runModifiers.js: -------------------------------------------------------------------------------- 1 | import isFunction from './isFunction'; 2 | import findIndex from './findIndex'; 3 | import getClientRect from '../utils/getClientRect'; 4 | 5 | /** 6 | * Loop trough the list of modifiers and run them in order, 7 | * each of them will then edit the data object. 8 | * @method 9 | * @memberof Popper.Utils 10 | * @param {dataObject} data 11 | * @param {Array} modifiers 12 | * @param {String} ends - Optional modifier name used as stopper 13 | * @returns {dataObject} 14 | */ 15 | export default function runModifiers(modifiers, data, ends) { 16 | const modifiersToRun = ends === undefined 17 | ? modifiers 18 | : modifiers.slice(0, findIndex(modifiers, 'name', ends)); 19 | 20 | modifiersToRun.forEach(modifier => { 21 | if (modifier['function']) { // eslint-disable-line dot-notation 22 | console.warn('`modifier.function` is deprecated, use `modifier.fn`!'); 23 | } 24 | const fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation 25 | if (modifier.enabled && isFunction(fn)) { 26 | // Add properties to offsets to make them a complete clientRect object 27 | // we do this before each modifier to make sure the previous one doesn't 28 | // mess with these values 29 | data.offsets.popper = getClientRect(data.offsets.popper); 30 | data.offsets.reference = getClientRect(data.offsets.reference); 31 | 32 | data = fn(data, modifier); 33 | } 34 | }); 35 | 36 | return data; 37 | } 38 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/setAttributes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Set the attributes to the given popper 3 | * @method 4 | * @memberof Popper.Utils 5 | * @argument {Element} element - Element to apply the attributes to 6 | * @argument {Object} styles 7 | * Object with a list of properties and values which will be applied to the element 8 | */ 9 | export default function setAttributes(element, attributes) { 10 | Object.keys(attributes).forEach(function(prop) { 11 | const value = attributes[prop]; 12 | if (value !== false) { 13 | element.setAttribute(prop, attributes[prop]); 14 | } else { 15 | element.removeAttribute(prop); 16 | } 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/setStyles.js: -------------------------------------------------------------------------------- 1 | import isNumeric from './isNumeric'; 2 | 3 | /** 4 | * Set the style to the given popper 5 | * @method 6 | * @memberof Popper.Utils 7 | * @argument {Element} element - Element to apply the style to 8 | * @argument {Object} styles 9 | * Object with a list of properties and values which will be applied to the element 10 | */ 11 | export default function setStyles(element, styles) { 12 | Object.keys(styles).forEach(prop => { 13 | let unit = ''; 14 | // add unit if the value is numeric and is one of the following 15 | if ( 16 | ['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== 17 | -1 && 18 | isNumeric(styles[prop]) 19 | ) { 20 | unit = 'px'; 21 | } 22 | element.style[prop] = styles[prop] + unit; 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Scripts/src/utils/setupEventListeners.js: -------------------------------------------------------------------------------- 1 | import getScrollParent from './getScrollParent'; 2 | import getWindow from './getWindow'; 3 | 4 | function attachToScrollParents(scrollParent, event, callback, scrollParents) { 5 | const isBody = scrollParent.nodeName === 'BODY'; 6 | const target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent; 7 | target.addEventListener(event, callback, { passive: true }); 8 | 9 | if (!isBody) { 10 | attachToScrollParents( 11 | getScrollParent(target.parentNode), 12 | event, 13 | callback, 14 | scrollParents 15 | ); 16 | } 17 | scrollParents.push(target); 18 | } 19 | 20 | /** 21 | * Setup needed event listeners used to update the popper position 22 | * @method 23 | * @memberof Popper.Utils 24 | * @private 25 | */ 26 | export default function setupEventListeners( 27 | reference, 28 | options, 29 | state, 30 | updateBound 31 | ) { 32 | // Resize event listener on window 33 | state.updateBound = updateBound; 34 | getWindow(reference).addEventListener('resize', state.updateBound, { passive: true }); 35 | 36 | // Scroll event listener on scroll parents 37 | const scrollElement = getScrollParent(reference); 38 | attachToScrollParents( 39 | scrollElement, 40 | 'scroll', 41 | state.updateBound, 42 | state.scrollParents 43 | ); 44 | state.scrollElement = scrollElement; 45 | state.eventsEnabled = true; 46 | 47 | return state; 48 | } 49 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Startup.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft Corporation. All rights reserved. 2 | // Licensed under the MIT license. 3 | 4 | using Microsoft.Owin; 5 | using Owin; 6 | 7 | [assembly: OwinStartup(typeof(graph_tutorial.Startup))] 8 | 9 | namespace graph_tutorial 10 | { 11 | public partial class Startup 12 | { 13 | public void Configuration(IAppBuilder app) 14 | { 15 | ConfigureAuth(app); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Views/Calendar/Index.cshtml: -------------------------------------------------------------------------------- 1 |  5 | 6 | @model IEnumerable 7 | 8 | @{ 9 | ViewBag.Current = "Calendar"; 10 | } 11 | 12 |

Calendar

13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | @foreach (var item in Model) 24 | { 25 | 26 | 27 | 28 | 29 | 30 | 31 | } 32 | 33 |
OrganizerSubjectStartEnd
@item.Organizer.EmailAddress.Name@item.Subject@Convert.ToDateTime(item.Start.DateTime).ToString("M/d/yy h:mm tt")@Convert.ToDateTime(item.End.DateTime).ToString("M/d/yy h:mm tt")
-------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "About"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

6 | 7 |

Use this area to provide additional information.

8 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Views/Home/Contact.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Contact"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

6 | 7 |
8 | One Microsoft Way
9 | Redmond, WA 98052-6399
10 | P: 11 | 425.555.0100 12 |
13 | 14 |
15 | Support: Support@example.com
16 | Marketing: Marketing@example.com 17 |
-------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 |  5 | 6 | @{ 7 | ViewBag.Current = "Home"; 8 | } 9 | 10 |
11 |

ASP.NET Graph Tutorial

12 |

This sample app shows how to use the Microsoft Graph API to access a user's data from ASP.NET

13 | @if (Request.IsAuthenticated) 14 | { 15 |

Welcome @ViewBag.User.DisplayName!

16 |

Use the navigation bar at the top of the page to get started.

17 | } 18 | else 19 | { 20 | @Html.ActionLink("Click here to sign in", "SignIn", "Account", new { area = "" }, new { @class = "btn btn-primary btn-large" }) 21 | } 22 |
23 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Error 6 | 7 | 8 |
9 |

Error.

10 |

An error occurred while processing your request.

11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Views/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } 4 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Web.Debug.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/Web.Release.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Demos/03-add-msgraph/graph-tutorial/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoftgraph/msgraph-training-aspnetmvcapp/08112c10ecf3107da7c6ef9eb5311672b1270649/Demos/03-add-msgraph/graph-tutorial/favicon.ico -------------------------------------------------------------------------------- /Demos/03-add-msgraph/version: -------------------------------------------------------------------------------- 1 | 1.3 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Microsoft Graph 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /qs.json: -------------------------------------------------------------------------------- 1 | { 2 | "sourceDirectory": "./Demos/03-add-msgraph", 3 | "exampleConfigFile": "./graph-tutorial/PrivateSettings.example.config", 4 | "configFile": "PrivateSettings.config", 5 | "archiveFile": "AspNetQuickStart.zip", 6 | "zipReadMe": "./README.md" 7 | } -------------------------------------------------------------------------------- /slides.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoftgraph/msgraph-training-aspnetmvcapp/08112c10ecf3107da7c6ef9eb5311672b1270649/slides.pptx --------------------------------------------------------------------------------