@kato-lee/cdk 14.2.7 → 20.2.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +8 -8
- package/_adev_assets/cdk_drag_drop.json +7215 -0
- package/_adev_assets/cdk_testing.json +7605 -0
- package/_adev_assets/cdk_testing_protractor.json +1747 -0
- package/_adev_assets/cdk_testing_selenium_webdriver.json +1801 -0
- package/_adev_assets/cdk_testing_testbed.json +1903 -0
- package/_index.scss +8 -8
- package/a11y/_index.scss +60 -102
- package/a11y/index.d.ts +550 -1212
- package/a11y-module.d.d.ts +314 -0
- package/a11y-prebuilt.css +1 -1
- package/accordion/index.d.ts +92 -140
- package/activedescendant-key-manager.d.d.ts +39 -0
- package/bidi/index.d.ts +21 -80
- package/bidi-module.d.d.ts +57 -0
- package/clipboard/index.d.ts +101 -115
- package/coercion/index.d.ts +45 -67
- package/coercion/private/index.d.ts +9 -0
- package/collections/index.d.ts +99 -374
- package/data-source.d.d.ts +43 -0
- package/dialog/index.d.ts +412 -469
- package/drag-drop/index.d.ts +1410 -1614
- package/fesm2022/a11y-module.mjs +951 -0
- package/fesm2022/a11y-module.mjs.map +1 -0
- package/fesm2022/a11y.mjs +538 -0
- package/fesm2022/a11y.mjs.map +1 -0
- package/fesm2022/accordion.mjs +216 -0
- package/fesm2022/accordion.mjs.map +1 -0
- package/fesm2022/activedescendant-key-manager.mjs +16 -0
- package/fesm2022/activedescendant-key-manager.mjs.map +1 -0
- package/fesm2022/array.mjs +6 -0
- package/fesm2022/array.mjs.map +1 -0
- package/fesm2022/bidi.mjs +78 -0
- package/fesm2022/bidi.mjs.map +1 -0
- package/fesm2022/breakpoints-observer.mjs +179 -0
- package/fesm2022/breakpoints-observer.mjs.map +1 -0
- package/fesm2022/cdk.mjs +7 -0
- package/fesm2022/cdk.mjs.map +1 -0
- package/{fesm2020 → fesm2022}/clipboard.mjs +210 -259
- package/fesm2022/clipboard.mjs.map +1 -0
- package/fesm2022/coercion/private.mjs +15 -0
- package/fesm2022/coercion/private.mjs.map +1 -0
- package/fesm2022/coercion.mjs +43 -0
- package/fesm2022/coercion.mjs.map +1 -0
- package/fesm2022/collections.mjs +8 -0
- package/fesm2022/collections.mjs.map +1 -0
- package/fesm2022/css-pixel-value.mjs +10 -0
- package/fesm2022/css-pixel-value.mjs.map +1 -0
- package/fesm2022/data-source.mjs +15 -0
- package/fesm2022/data-source.mjs.map +1 -0
- package/{fesm2020 → fesm2022}/dialog.mjs +874 -787
- package/fesm2022/dialog.mjs.map +1 -0
- package/fesm2022/directionality.mjs +77 -0
- package/fesm2022/directionality.mjs.map +1 -0
- package/fesm2022/dispose-view-repeater-strategy.mjs +44 -0
- package/fesm2022/dispose-view-repeater-strategy.mjs.map +1 -0
- package/{fesm2020 → fesm2022}/drag-drop.mjs +4477 -3808
- package/fesm2022/drag-drop.mjs.map +1 -0
- package/fesm2022/element.mjs +29 -0
- package/fesm2022/element.mjs.map +1 -0
- package/fesm2022/fake-event-detection.mjs +24 -0
- package/fesm2022/fake-event-detection.mjs.map +1 -0
- package/fesm2022/focus-key-manager.mjs +22 -0
- package/fesm2022/focus-key-manager.mjs.map +1 -0
- package/fesm2022/focus-monitor.mjs +622 -0
- package/fesm2022/focus-monitor.mjs.map +1 -0
- package/fesm2022/id-generator.mjs +37 -0
- package/fesm2022/id-generator.mjs.map +1 -0
- package/fesm2022/keycodes.mjs +15 -0
- package/fesm2022/keycodes.mjs.map +1 -0
- package/{fesm2015/keycodes.mjs → fesm2022/keycodes2.mjs} +122 -167
- package/fesm2022/keycodes2.mjs.map +1 -0
- package/fesm2022/layout.mjs +43 -0
- package/fesm2022/layout.mjs.map +1 -0
- package/fesm2022/list-key-manager.mjs +360 -0
- package/fesm2022/list-key-manager.mjs.map +1 -0
- package/fesm2022/listbox.mjs +928 -0
- package/fesm2022/listbox.mjs.map +1 -0
- package/fesm2022/menu.mjs +2001 -0
- package/fesm2022/menu.mjs.map +1 -0
- package/fesm2022/observers/private.mjs +124 -0
- package/fesm2022/observers/private.mjs.map +1 -0
- package/fesm2022/observers.mjs +210 -0
- package/fesm2022/observers.mjs.map +1 -0
- package/{fesm2020/overlay.mjs → fesm2022/overlay-module.mjs} +3062 -3145
- package/fesm2022/overlay-module.mjs.map +1 -0
- package/fesm2022/overlay.mjs +101 -0
- package/fesm2022/overlay.mjs.map +1 -0
- package/fesm2022/passive-listeners.mjs +31 -0
- package/fesm2022/passive-listeners.mjs.map +1 -0
- package/fesm2022/platform.mjs +73 -0
- package/fesm2022/platform.mjs.map +1 -0
- package/fesm2022/platform2.mjs +77 -0
- package/fesm2022/platform2.mjs.map +1 -0
- package/{fesm2020 → fesm2022}/portal.mjs +614 -689
- package/fesm2022/portal.mjs.map +1 -0
- package/fesm2022/private.mjs +19 -0
- package/fesm2022/private.mjs.map +1 -0
- package/fesm2022/recycle-view-repeater-strategy.mjs +156 -0
- package/fesm2022/recycle-view-repeater-strategy.mjs.map +1 -0
- package/{fesm2015 → fesm2022}/scrolling.mjs +1472 -1558
- package/fesm2022/scrolling.mjs.map +1 -0
- package/fesm2022/scrolling2.mjs +99 -0
- package/fesm2022/scrolling2.mjs.map +1 -0
- package/fesm2022/selection-model.mjs +221 -0
- package/fesm2022/selection-model.mjs.map +1 -0
- package/fesm2022/shadow-dom.mjs +49 -0
- package/fesm2022/shadow-dom.mjs.map +1 -0
- package/fesm2022/stepper.mjs +632 -0
- package/fesm2022/stepper.mjs.map +1 -0
- package/fesm2022/style-loader.mjs +47 -0
- package/fesm2022/style-loader.mjs.map +1 -0
- package/{fesm2020 → fesm2022}/table.mjs +2511 -2348
- package/fesm2022/table.mjs.map +1 -0
- package/fesm2022/test-environment.mjs +19 -0
- package/fesm2022/test-environment.mjs.map +1 -0
- package/fesm2022/testing/selenium-webdriver.mjs +353 -0
- package/fesm2022/testing/selenium-webdriver.mjs.map +1 -0
- package/fesm2022/testing/testbed.mjs +782 -0
- package/fesm2022/testing/testbed.mjs.map +1 -0
- package/fesm2022/testing.mjs +950 -0
- package/fesm2022/testing.mjs.map +1 -0
- package/{fesm2020 → fesm2022}/text-field.mjs +432 -459
- package/fesm2022/text-field.mjs.map +1 -0
- package/fesm2022/tree-key-manager.mjs +360 -0
- package/fesm2022/tree-key-manager.mjs.map +1 -0
- package/fesm2022/tree.mjs +1800 -0
- package/fesm2022/tree.mjs.map +1 -0
- package/fesm2022/typeahead.mjs +88 -0
- package/fesm2022/typeahead.mjs.map +1 -0
- package/fesm2022/unique-selection-dispatcher.mjs +49 -0
- package/fesm2022/unique-selection-dispatcher.mjs.map +1 -0
- package/focus-key-manager.d.d.ts +39 -0
- package/focus-monitor.d.d.ts +208 -0
- package/harness-environment.d.d.ts +944 -0
- package/index.d.ts +6 -6
- package/keycodes/index.d.ts +129 -249
- package/layout/index.d.ts +89 -90
- package/list-key-manager.d.d.ts +170 -0
- package/listbox/index.d.ts +354 -419
- package/menu/index.d.ts +834 -1013
- package/number-property.d.d.ts +16 -0
- package/observers/index.d.ts +84 -109
- package/observers/private/index.d.ts +34 -0
- package/overlay/_index-deprecated.scss +13 -13
- package/overlay/_index.scss +193 -152
- package/overlay/index.d.ts +328 -1343
- package/overlay-module.d.d.ts +801 -0
- package/overlay-prebuilt.css +1 -1
- package/package.json +177 -232
- package/platform/index.d.ts +67 -106
- package/platform.d.d.ts +33 -0
- package/portal/index.d.ts +51 -328
- package/portal-directives.d.d.ts +211 -0
- package/private/index.d.ts +13 -0
- package/schematics/collection.json +18 -0
- package/schematics/index.d.ts +14 -0
- package/schematics/index.js +37 -0
- package/schematics/index.js.map +1 -0
- package/schematics/migration.json +15 -0
- package/schematics/ng-add/index.d.ts +17 -0
- package/schematics/ng-add/index.js +31 -0
- package/schematics/ng-add/index.js.map +1 -0
- package/schematics/ng-add/schema.d.ts +11 -0
- package/schematics/ng-add/schema.js +10 -0
- package/schematics/ng-add/schema.js.map +1 -0
- package/schematics/ng-add/schema.json +16 -0
- package/schematics/ng-generate/drag-drop/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.__style__.template +53 -0
- package/schematics/ng-generate/drag-drop/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.html.template +21 -0
- package/schematics/ng-generate/drag-drop/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.spec.ts.template +25 -0
- package/schematics/ng-generate/drag-drop/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.ts.template +45 -0
- package/schematics/ng-generate/drag-drop/index.d.ts +11 -0
- package/schematics/ng-generate/drag-drop/index.js +42 -0
- package/schematics/ng-generate/drag-drop/index.js.map +1 -0
- package/schematics/ng-generate/drag-drop/schema.d.ts +10 -0
- package/schematics/ng-generate/drag-drop/schema.js +10 -0
- package/schematics/ng-generate/drag-drop/schema.js.map +1 -0
- package/schematics/ng-generate/drag-drop/schema.json +100 -0
- package/schematics/ng-update/data/attribute-selectors.d.ts +15 -0
- package/schematics/ng-update/data/attribute-selectors.js +12 -0
- package/schematics/ng-update/data/attribute-selectors.js.map +1 -0
- package/schematics/ng-update/data/class-names.d.ts +15 -0
- package/schematics/ng-update/data/class-names.js +12 -0
- package/schematics/ng-update/data/class-names.js.map +1 -0
- package/schematics/ng-update/data/constructor-checks.d.ts +15 -0
- package/schematics/ng-update/data/constructor-checks.js +17 -0
- package/schematics/ng-update/data/constructor-checks.js.map +1 -0
- package/schematics/ng-update/data/css-selectors.d.ts +27 -0
- package/schematics/ng-update/data/css-selectors.js +12 -0
- package/schematics/ng-update/data/css-selectors.js.map +1 -0
- package/schematics/ng-update/data/css-tokens.d.ts +27 -0
- package/schematics/ng-update/data/css-tokens.js +12 -0
- package/schematics/ng-update/data/css-tokens.js.map +1 -0
- package/schematics/ng-update/data/element-selectors.d.ts +15 -0
- package/schematics/ng-update/data/element-selectors.js +12 -0
- package/schematics/ng-update/data/element-selectors.js.map +1 -0
- package/schematics/ng-update/data/index.d.ts +18 -0
- package/schematics/ng-update/data/index.js +35 -0
- package/schematics/ng-update/data/index.js.map +1 -0
- package/schematics/ng-update/data/input-names.d.ts +22 -0
- package/schematics/ng-update/data/input-names.js +12 -0
- package/schematics/ng-update/data/input-names.js.map +1 -0
- package/schematics/ng-update/data/method-call-checks.d.ts +17 -0
- package/schematics/ng-update/data/method-call-checks.js +12 -0
- package/schematics/ng-update/data/method-call-checks.js.map +1 -0
- package/schematics/ng-update/data/output-names.d.ts +22 -0
- package/schematics/ng-update/data/output-names.js +12 -0
- package/schematics/ng-update/data/output-names.js.map +1 -0
- package/schematics/ng-update/data/property-names.d.ts +20 -0
- package/schematics/ng-update/data/property-names.js +12 -0
- package/schematics/ng-update/data/property-names.js.map +1 -0
- package/schematics/ng-update/data/symbol-removal.d.ts +17 -0
- package/schematics/ng-update/data/symbol-removal.js +12 -0
- package/schematics/ng-update/data/symbol-removal.js.map +1 -0
- package/schematics/ng-update/devkit-file-system.d.ts +30 -0
- package/schematics/ng-update/devkit-file-system.js +83 -0
- package/schematics/ng-update/devkit-file-system.js.map +1 -0
- package/schematics/ng-update/devkit-migration-rule.d.ts +24 -0
- package/schematics/ng-update/devkit-migration-rule.js +142 -0
- package/schematics/ng-update/devkit-migration-rule.js.map +1 -0
- package/schematics/ng-update/devkit-migration.d.ts +35 -0
- package/schematics/ng-update/devkit-migration.js +20 -0
- package/schematics/ng-update/devkit-migration.js.map +1 -0
- package/schematics/ng-update/find-stylesheets.d.ts +16 -0
- package/schematics/ng-update/find-stylesheets.js +41 -0
- package/schematics/ng-update/find-stylesheets.js.map +1 -0
- package/schematics/ng-update/html-parsing/angular.d.ts +15 -0
- package/schematics/ng-update/html-parsing/angular.js +51 -0
- package/schematics/ng-update/html-parsing/angular.js.map +1 -0
- package/schematics/ng-update/html-parsing/elements.d.ts +24 -0
- package/schematics/ng-update/html-parsing/elements.js +63 -0
- package/schematics/ng-update/html-parsing/elements.js.map +1 -0
- package/schematics/ng-update/index.d.ts +10 -0
- package/schematics/ng-update/index.js +29 -0
- package/schematics/ng-update/index.js.map +1 -0
- package/schematics/ng-update/migrations/attribute-selectors.d.ts +26 -0
- package/schematics/ng-update/migrations/attribute-selectors.js +71 -0
- package/schematics/ng-update/migrations/attribute-selectors.js.map +1 -0
- package/schematics/ng-update/migrations/class-inheritance.d.ts +26 -0
- package/schematics/ng-update/migrations/class-inheritance.js +58 -0
- package/schematics/ng-update/migrations/class-inheritance.js.map +1 -0
- package/schematics/ng-update/migrations/class-names.d.ts +32 -0
- package/schematics/ng-update/migrations/class-names.js +91 -0
- package/schematics/ng-update/migrations/class-names.js.map +1 -0
- package/schematics/ng-update/migrations/constructor-signature.d.ts +29 -0
- package/schematics/ng-update/migrations/constructor-signature.js +139 -0
- package/schematics/ng-update/migrations/constructor-signature.js.map +1 -0
- package/schematics/ng-update/migrations/css-selectors.d.ts +26 -0
- package/schematics/ng-update/migrations/css-selectors.js +75 -0
- package/schematics/ng-update/migrations/css-selectors.js.map +1 -0
- package/schematics/ng-update/migrations/css-tokens.d.ts +26 -0
- package/schematics/ng-update/migrations/css-tokens.js +83 -0
- package/schematics/ng-update/migrations/css-tokens.js.map +1 -0
- package/schematics/ng-update/migrations/element-selectors.d.ts +26 -0
- package/schematics/ng-update/migrations/element-selectors.js +66 -0
- package/schematics/ng-update/migrations/element-selectors.js.map +1 -0
- package/schematics/ng-update/migrations/input-names.d.ts +26 -0
- package/schematics/ng-update/migrations/input-names.js +59 -0
- package/schematics/ng-update/migrations/input-names.js.map +1 -0
- package/schematics/ng-update/migrations/method-call-arguments.d.ts +22 -0
- package/schematics/ng-update/migrations/method-call-arguments.js +62 -0
- package/schematics/ng-update/migrations/method-call-arguments.js.map +1 -0
- package/schematics/ng-update/migrations/misc-template.d.ts +18 -0
- package/schematics/ng-update/migrations/misc-template.js +25 -0
- package/schematics/ng-update/migrations/misc-template.js.map +1 -0
- package/schematics/ng-update/migrations/output-names.d.ts +22 -0
- package/schematics/ng-update/migrations/output-names.js +46 -0
- package/schematics/ng-update/migrations/output-names.js.map +1 -0
- package/schematics/ng-update/migrations/property-names.d.ts +22 -0
- package/schematics/ng-update/migrations/property-names.js +60 -0
- package/schematics/ng-update/migrations/property-names.js.map +1 -0
- package/schematics/ng-update/migrations/symbol-removal.d.ts +18 -0
- package/schematics/ng-update/migrations/symbol-removal.js +47 -0
- package/schematics/ng-update/migrations/symbol-removal.js.map +1 -0
- package/schematics/ng-update/public-api.d.ts +19 -0
- package/schematics/ng-update/public-api.js +36 -0
- package/schematics/ng-update/public-api.js.map +1 -0
- package/schematics/ng-update/typescript/base-types.d.ts +10 -0
- package/schematics/ng-update/typescript/base-types.js +23 -0
- package/schematics/ng-update/typescript/base-types.js.map +1 -0
- package/schematics/ng-update/typescript/imports.d.ts +18 -0
- package/schematics/ng-update/typescript/imports.js +53 -0
- package/schematics/ng-update/typescript/imports.js.map +1 -0
- package/schematics/ng-update/typescript/literal.d.ts +18 -0
- package/schematics/ng-update/typescript/literal.js +32 -0
- package/schematics/ng-update/typescript/literal.js.map +1 -0
- package/schematics/ng-update/typescript/module-specifiers.d.ts +16 -0
- package/schematics/ng-update/typescript/module-specifiers.js +35 -0
- package/schematics/ng-update/typescript/module-specifiers.js.map +1 -0
- package/schematics/ng-update/upgrade-data.d.ts +35 -0
- package/schematics/ng-update/upgrade-data.js +40 -0
- package/schematics/ng-update/upgrade-data.js.map +1 -0
- package/schematics/package.json +3 -0
- package/schematics/paths.d.ts +11 -0
- package/schematics/paths.js +16 -0
- package/schematics/paths.js.map +1 -0
- package/schematics/update-tool/component-resource-collector.d.ts +44 -0
- package/schematics/update-tool/component-resource-collector.js +164 -0
- package/schematics/update-tool/component-resource-collector.js.map +1 -0
- package/schematics/update-tool/file-system.d.ts +72 -0
- package/schematics/update-tool/file-system.js +18 -0
- package/schematics/update-tool/file-system.js.map +1 -0
- package/schematics/update-tool/index.d.ts +74 -0
- package/schematics/update-tool/index.js +172 -0
- package/schematics/update-tool/index.js.map +1 -0
- package/schematics/update-tool/logger.d.ts +15 -0
- package/schematics/update-tool/logger.js +18 -0
- package/schematics/update-tool/logger.js.map +1 -0
- package/schematics/update-tool/migration.d.ts +87 -0
- package/schematics/update-tool/migration.js +70 -0
- package/schematics/update-tool/migration.js.map +1 -0
- package/schematics/update-tool/public-api.d.ts +16 -0
- package/schematics/update-tool/public-api.js +33 -0
- package/schematics/update-tool/public-api.js.map +1 -0
- package/schematics/update-tool/target-version.d.ts +16 -0
- package/schematics/update-tool/target-version.js +27 -0
- package/schematics/update-tool/target-version.js.map +1 -0
- package/schematics/update-tool/update-recorder.d.ts +13 -0
- package/schematics/update-tool/update-recorder.js +10 -0
- package/schematics/update-tool/update-recorder.js.map +1 -0
- package/schematics/update-tool/utils/decorators.d.ts +22 -0
- package/schematics/update-tool/utils/decorators.js +41 -0
- package/schematics/update-tool/utils/decorators.js.map +1 -0
- package/schematics/update-tool/utils/diagnostics.d.ts +11 -0
- package/schematics/update-tool/utils/diagnostics.js +18 -0
- package/schematics/update-tool/utils/diagnostics.js.map +1 -0
- package/schematics/update-tool/utils/functions.d.ts +14 -0
- package/schematics/update-tool/utils/functions.js +20 -0
- package/schematics/update-tool/utils/functions.js.map +1 -0
- package/schematics/update-tool/utils/imports.d.ts +17 -0
- package/schematics/update-tool/utils/imports.js +110 -0
- package/schematics/update-tool/utils/imports.js.map +1 -0
- package/schematics/update-tool/utils/line-mappings.d.ts +21 -0
- package/schematics/update-tool/utils/line-mappings.js +75 -0
- package/schematics/update-tool/utils/line-mappings.js.map +1 -0
- package/schematics/update-tool/utils/parse-tsconfig.d.ts +18 -0
- package/schematics/update-tool/utils/parse-tsconfig.js +45 -0
- package/schematics/update-tool/utils/parse-tsconfig.js.map +1 -0
- package/schematics/update-tool/utils/property-name.d.ts +18 -0
- package/schematics/update-tool/utils/property-name.js +27 -0
- package/schematics/update-tool/utils/property-name.js.map +1 -0
- package/schematics/update-tool/utils/virtual-host.d.ts +36 -0
- package/schematics/update-tool/utils/virtual-host.js +71 -0
- package/schematics/update-tool/utils/virtual-host.js.map +1 -0
- package/schematics/update-tool/version-changes.d.ts +32 -0
- package/schematics/update-tool/version-changes.js +38 -0
- package/schematics/update-tool/version-changes.js.map +1 -0
- package/schematics/utils/ast/ng-module-imports.d.ts +12 -0
- package/schematics/utils/ast/ng-module-imports.js +82 -0
- package/schematics/utils/ast/ng-module-imports.js.map +1 -0
- package/schematics/utils/ast.d.ts +25 -0
- package/schematics/utils/ast.js +79 -0
- package/schematics/utils/ast.js.map +1 -0
- package/schematics/utils/build-component.d.ts +20 -0
- package/schematics/utils/build-component.js +189 -0
- package/schematics/utils/build-component.js.map +1 -0
- package/schematics/utils/get-project.d.ts +13 -0
- package/schematics/utils/get-project.js +28 -0
- package/schematics/utils/get-project.js.map +1 -0
- package/schematics/utils/html-manipulation.d.ts +15 -0
- package/schematics/utils/html-manipulation.js +91 -0
- package/schematics/utils/html-manipulation.js.map +1 -0
- package/schematics/utils/index.d.ts +19 -0
- package/schematics/utils/index.js +36 -0
- package/schematics/utils/index.js.map +1 -0
- package/schematics/utils/parse5-element.d.ts +12 -0
- package/schematics/utils/parse5-element.js +30 -0
- package/schematics/utils/parse5-element.js.map +1 -0
- package/schematics/utils/project-index-file.d.ts +13 -0
- package/schematics/utils/project-index-file.js +43 -0
- package/schematics/utils/project-index-file.js.map +1 -0
- package/schematics/utils/project-main-file.d.ts +11 -0
- package/schematics/utils/project-main-file.js +25 -0
- package/schematics/utils/project-main-file.js.map +1 -0
- package/schematics/utils/project-style-file.d.ts +13 -0
- package/schematics/utils/project-style-file.js +42 -0
- package/schematics/utils/project-style-file.js.map +1 -0
- package/schematics/utils/project-targets.d.ts +15 -0
- package/schematics/utils/project-targets.js +46 -0
- package/schematics/utils/project-targets.js.map +1 -0
- package/schematics/utils/project-tsconfig-paths.d.ts +14 -0
- package/schematics/utils/project-tsconfig-paths.js +46 -0
- package/schematics/utils/project-tsconfig-paths.js.map +1 -0
- package/schematics/utils/schematic-options.d.ts +20 -0
- package/schematics/utils/schematic-options.js +89 -0
- package/schematics/utils/schematic-options.js.map +1 -0
- package/scrolling/index.d.ts +62 -849
- package/scrolling-module.d.d.ts +551 -0
- package/selection-model.d.d.ts +112 -0
- package/stepper/index.d.ts +236 -419
- package/style-loader.d.d.ts +21 -0
- package/table/index.d.ts +901 -1483
- package/testing/index.d.ts +98 -0
- package/testing/selenium-webdriver/index.d.ts +150 -0
- package/testing/testbed/index.d.ts +157 -0
- package/text-field/_index.scss +89 -89
- package/text-field/index.d.ts +154 -203
- package/text-field-prebuilt.css +1 -1
- package/tree/index.d.ts +720 -593
- package/tree-key-manager-strategy.d.d.ts +116 -0
- package/unique-selection-dispatcher.d.d.ts +33 -0
- package/view-repeater.d.d.ts +88 -0
- package/a11y/_index.import.scss +0 -2
- package/esm2020/a11y/a11y-module.mjs +0 -32
- package/esm2020/a11y/a11y_public_index.mjs +0 -5
- package/esm2020/a11y/aria-describer/aria-describer.mjs +0 -232
- package/esm2020/a11y/aria-describer/aria-reference.mjs +0 -44
- package/esm2020/a11y/fake-event-detection.mjs +0 -31
- package/esm2020/a11y/focus-monitor/focus-monitor.mjs +0 -451
- package/esm2020/a11y/focus-trap/configurable-focus-trap-config.mjs +0 -9
- package/esm2020/a11y/focus-trap/configurable-focus-trap-factory.mjs +0 -53
- package/esm2020/a11y/focus-trap/configurable-focus-trap.mjs +0 -51
- package/esm2020/a11y/focus-trap/event-listener-inert-strategy.mjs +0 -61
- package/esm2020/a11y/focus-trap/focus-trap-inert-strategy.mjs +0 -11
- package/esm2020/a11y/focus-trap/focus-trap-manager.mjs +0 -53
- package/esm2020/a11y/focus-trap/focus-trap.mjs +0 -402
- package/esm2020/a11y/high-contrast-mode/high-contrast-mode-detector.mjs +0 -109
- package/esm2020/a11y/index.mjs +0 -9
- package/esm2020/a11y/input-modality/input-modality-detector.mjs +0 -176
- package/esm2020/a11y/interactivity-checker/interactivity-checker.mjs +0 -238
- package/esm2020/a11y/key-manager/activedescendant-key-manager.mjs +0 -20
- package/esm2020/a11y/key-manager/focus-key-manager.mjs +0 -29
- package/esm2020/a11y/key-manager/list-key-manager.mjs +0 -321
- package/esm2020/a11y/live-announcer/live-announcer-tokens.mjs +0 -19
- package/esm2020/a11y/live-announcer/live-announcer.mjs +0 -178
- package/esm2020/a11y/public-api.mjs +0 -26
- package/esm2020/accordion/accordion-item.mjs +0 -167
- package/esm2020/accordion/accordion-module.mjs +0 -24
- package/esm2020/accordion/accordion.mjs +0 -70
- package/esm2020/accordion/accordion_public_index.mjs +0 -5
- package/esm2020/accordion/index.mjs +0 -9
- package/esm2020/accordion/public-api.mjs +0 -11
- package/esm2020/bidi/bidi-module.mjs +0 -23
- package/esm2020/bidi/bidi_public_index.mjs +0 -5
- package/esm2020/bidi/dir-document-token.mjs +0 -33
- package/esm2020/bidi/dir.mjs +0 -69
- package/esm2020/bidi/directionality.mjs +0 -52
- package/esm2020/bidi/index.mjs +0 -9
- package/esm2020/bidi/public-api.mjs +0 -12
- package/esm2020/clipboard/clipboard-module.mjs +0 -23
- package/esm2020/clipboard/clipboard.mjs +0 -53
- package/esm2020/clipboard/clipboard_public_index.mjs +0 -5
- package/esm2020/clipboard/copy-to-clipboard.mjs +0 -99
- package/esm2020/clipboard/index.mjs +0 -9
- package/esm2020/clipboard/pending-copy.mjs +0 -69
- package/esm2020/clipboard/public-api.mjs +0 -12
- package/esm2020/coercion/array.mjs +0 -11
- package/esm2020/coercion/boolean-property.mjs +0 -12
- package/esm2020/coercion/css-pixel-value.mjs +0 -15
- package/esm2020/coercion/element.mjs +0 -16
- package/esm2020/coercion/index.mjs +0 -9
- package/esm2020/coercion/number-property.mjs +0 -21
- package/esm2020/coercion/public-api.mjs +0 -14
- package/esm2020/coercion/string-array.mjs +0 -38
- package/esm2020/collections/array-data-source.mjs +0 -21
- package/esm2020/collections/collection-viewer.mjs +0 -9
- package/esm2020/collections/collections_public_index.mjs +0 -5
- package/esm2020/collections/data-source.mjs +0 -19
- package/esm2020/collections/dispose-view-repeater-strategy.mjs +0 -47
- package/esm2020/collections/index.mjs +0 -9
- package/esm2020/collections/public-api.mjs +0 -17
- package/esm2020/collections/recycle-view-repeater-strategy.mjs +0 -128
- package/esm2020/collections/selection-model.mjs +0 -216
- package/esm2020/collections/tree-adapter.mjs +0 -9
- package/esm2020/collections/unique-selection-dispatcher.mjs +0 -55
- package/esm2020/collections/view-repeater.mjs +0 -14
- package/esm2020/dialog/dialog-config.mjs +0 -63
- package/esm2020/dialog/dialog-container.mjs +0 -278
- package/esm2020/dialog/dialog-injectors.mjs +0 -26
- package/esm2020/dialog/dialog-module.mjs +0 -42
- package/esm2020/dialog/dialog-ref.mjs +0 -76
- package/esm2020/dialog/dialog.mjs +0 -301
- package/esm2020/dialog/dialog_public_index.mjs +0 -5
- package/esm2020/dialog/index.mjs +0 -9
- package/esm2020/dialog/public-api.mjs +0 -14
- package/esm2020/drag-drop/directives/assertions.mjs +0 -18
- package/esm2020/drag-drop/directives/config.mjs +0 -14
- package/esm2020/drag-drop/directives/drag-handle.mjs +0 -66
- package/esm2020/drag-drop/directives/drag-placeholder.mjs +0 -36
- package/esm2020/drag-drop/directives/drag-preview.mjs +0 -47
- package/esm2020/drag-drop/directives/drag.mjs +0 -487
- package/esm2020/drag-drop/directives/drop-list-group.mjs +0 -53
- package/esm2020/drag-drop/directives/drop-list.mjs +0 -345
- package/esm2020/drag-drop/dom/client-rect.mjs +0 -64
- package/esm2020/drag-drop/dom/clone-node.mjs +0 -65
- package/esm2020/drag-drop/dom/parent-position-tracker.mjs +0 -76
- package/esm2020/drag-drop/dom/styling.mjs +0 -69
- package/esm2020/drag-drop/dom/transition-duration.mjs +0 -36
- package/esm2020/drag-drop/drag-drop-module.mjs +0 -57
- package/esm2020/drag-drop/drag-drop-registry.mjs +0 -231
- package/esm2020/drag-drop/drag-drop.mjs +0 -57
- package/esm2020/drag-drop/drag-drop_public_index.mjs +0 -5
- package/esm2020/drag-drop/drag-events.mjs +0 -9
- package/esm2020/drag-drop/drag-parent.mjs +0 -16
- package/esm2020/drag-drop/drag-ref.mjs +0 -1146
- package/esm2020/drag-drop/drag-utils.mjs +0 -60
- package/esm2020/drag-drop/drop-list-ref.mjs +0 -577
- package/esm2020/drag-drop/index.mjs +0 -9
- package/esm2020/drag-drop/public-api.mjs +0 -23
- package/esm2020/drag-drop/sorting/drop-list-sort-strategy.mjs +0 -9
- package/esm2020/drag-drop/sorting/single-axis-sort-strategy.mjs +0 -341
- package/esm2020/index.mjs +0 -9
- package/esm2020/keycodes/index.mjs +0 -9
- package/esm2020/keycodes/keycodes.mjs +0 -127
- package/esm2020/keycodes/keycodes_public_index.mjs +0 -5
- package/esm2020/keycodes/modifiers.mjs +0 -18
- package/esm2020/keycodes/public-api.mjs +0 -10
- package/esm2020/layout/breakpoints-observer.mjs +0 -105
- package/esm2020/layout/breakpoints.mjs +0 -29
- package/esm2020/layout/index.mjs +0 -9
- package/esm2020/layout/layout-module.mjs +0 -19
- package/esm2020/layout/layout_public_index.mjs +0 -5
- package/esm2020/layout/media-matcher.mjs +0 -85
- package/esm2020/layout/public-api.mjs +0 -12
- package/esm2020/listbox/index.mjs +0 -9
- package/esm2020/listbox/listbox-module.mjs +0 -24
- package/esm2020/listbox/listbox.mjs +0 -872
- package/esm2020/listbox/listbox_public_index.mjs +0 -5
- package/esm2020/listbox/public-api.mjs +0 -10
- package/esm2020/menu/context-menu-trigger.mjs +0 -212
- package/esm2020/menu/index.mjs +0 -9
- package/esm2020/menu/menu-aim.mjs +0 -203
- package/esm2020/menu/menu-bar.mjs +0 -133
- package/esm2020/menu/menu-base.mjs +0 -187
- package/esm2020/menu/menu-errors.mjs +0 -22
- package/esm2020/menu/menu-group.mjs +0 -30
- package/esm2020/menu/menu-interface.mjs +0 -11
- package/esm2020/menu/menu-item-checkbox.mjs +0 -49
- package/esm2020/menu/menu-item-radio.mjs +0 -71
- package/esm2020/menu/menu-item-selectable.mjs +0 -42
- package/esm2020/menu/menu-item.mjs +0 -267
- package/esm2020/menu/menu-module.mjs +0 -62
- package/esm2020/menu/menu-stack.mjs +0 -156
- package/esm2020/menu/menu-trigger-base.mjs +0 -107
- package/esm2020/menu/menu-trigger.mjs +0 -291
- package/esm2020/menu/menu.mjs +0 -134
- package/esm2020/menu/menu_public_index.mjs +0 -5
- package/esm2020/menu/pointer-focus-tracker.mjs +0 -51
- package/esm2020/menu/public-api.mjs +0 -24
- package/esm2020/observers/index.mjs +0 -9
- package/esm2020/observers/observe-content.mjs +0 -187
- package/esm2020/observers/observers_public_index.mjs +0 -5
- package/esm2020/observers/public-api.mjs +0 -9
- package/esm2020/overlay/dispatchers/base-overlay-dispatcher.mjs +0 -52
- package/esm2020/overlay/dispatchers/index.mjs +0 -10
- package/esm2020/overlay/dispatchers/overlay-keyboard-dispatcher.mjs +0 -81
- package/esm2020/overlay/dispatchers/overlay-outside-click-dispatcher.mjs +0 -138
- package/esm2020/overlay/fullscreen-overlay-container.mjs +0 -94
- package/esm2020/overlay/index.mjs +0 -9
- package/esm2020/overlay/overlay-config.mjs +0 -45
- package/esm2020/overlay/overlay-container.mjs +0 -81
- package/esm2020/overlay/overlay-directives.mjs +0 -427
- package/esm2020/overlay/overlay-module.mjs +0 -29
- package/esm2020/overlay/overlay-ref.mjs +0 -427
- package/esm2020/overlay/overlay-reference.mjs +0 -9
- package/esm2020/overlay/overlay.mjs +0 -125
- package/esm2020/overlay/overlay_public_index.mjs +0 -5
- package/esm2020/overlay/position/connected-position.mjs +0 -88
- package/esm2020/overlay/position/flexible-connected-position-strategy.mjs +0 -985
- package/esm2020/overlay/position/global-position-strategy.mjs +0 -237
- package/esm2020/overlay/position/overlay-position-builder.mjs +0 -50
- package/esm2020/overlay/position/position-strategy.mjs +0 -9
- package/esm2020/overlay/position/scroll-clip.mjs +0 -40
- package/esm2020/overlay/public-api.mjs +0 -22
- package/esm2020/overlay/scroll/block-scroll-strategy.mjs +0 -80
- package/esm2020/overlay/scroll/close-scroll-strategy.mjs +0 -61
- package/esm2020/overlay/scroll/index.mjs +0 -14
- package/esm2020/overlay/scroll/noop-scroll-strategy.mjs +0 -17
- package/esm2020/overlay/scroll/reposition-scroll-strategy.mjs +0 -61
- package/esm2020/overlay/scroll/scroll-strategy-options.mjs +0 -55
- package/esm2020/overlay/scroll/scroll-strategy.mjs +0 -14
- package/esm2020/platform/features/input-types.mjs +0 -59
- package/esm2020/platform/features/passive-listeners.mjs +0 -36
- package/esm2020/platform/features/scrolling.mjs +0 -85
- package/esm2020/platform/features/shadow-dom.mjs +0 -54
- package/esm2020/platform/features/test-environment.mjs +0 -24
- package/esm2020/platform/index.mjs +0 -9
- package/esm2020/platform/platform-module.mjs +0 -19
- package/esm2020/platform/platform.mjs +0 -85
- package/esm2020/platform/platform_public_index.mjs +0 -5
- package/esm2020/platform/public-api.mjs +0 -15
- package/esm2020/portal/dom-portal-outlet.mjs +0 -158
- package/esm2020/portal/index.mjs +0 -9
- package/esm2020/portal/portal-directives.mjs +0 -246
- package/esm2020/portal/portal-errors.mjs +0 -51
- package/esm2020/portal/portal-injector.mjs +0 -28
- package/esm2020/portal/portal.mjs +0 -188
- package/esm2020/portal/portal_public_index.mjs +0 -5
- package/esm2020/portal/public-api.mjs +0 -12
- package/esm2020/public-api.mjs +0 -9
- package/esm2020/scrolling/fixed-size-virtual-scroll.mjs +0 -217
- package/esm2020/scrolling/index.mjs +0 -9
- package/esm2020/scrolling/public-api.mjs +0 -20
- package/esm2020/scrolling/scroll-dispatcher.mjs +0 -163
- package/esm2020/scrolling/scrollable.mjs +0 -176
- package/esm2020/scrolling/scrolling-module.mjs +0 -67
- package/esm2020/scrolling/scrolling_public_index.mjs +0 -5
- package/esm2020/scrolling/viewport-ruler.mjs +0 -146
- package/esm2020/scrolling/virtual-for-of.mjs +0 -298
- package/esm2020/scrolling/virtual-scroll-repeater.mjs +0 -9
- package/esm2020/scrolling/virtual-scroll-strategy.mjs +0 -11
- package/esm2020/scrolling/virtual-scroll-viewport.mjs +0 -437
- package/esm2020/scrolling/virtual-scrollable-element.mjs +0 -41
- package/esm2020/scrolling/virtual-scrollable-window.mjs +0 -40
- package/esm2020/scrolling/virtual-scrollable.mjs +0 -40
- package/esm2020/stepper/index.mjs +0 -9
- package/esm2020/stepper/public-api.mjs +0 -13
- package/esm2020/stepper/step-header.mjs +0 -30
- package/esm2020/stepper/step-label.mjs +0 -23
- package/esm2020/stepper/stepper-button.mjs +0 -56
- package/esm2020/stepper/stepper-module.mjs +0 -40
- package/esm2020/stepper/stepper.mjs +0 -458
- package/esm2020/stepper/stepper_public_index.mjs +0 -5
- package/esm2020/table/can-stick.mjs +0 -44
- package/esm2020/table/cell.mjs +0 -217
- package/esm2020/table/coalesced-style-scheduler.mjs +0 -91
- package/esm2020/table/index.mjs +0 -9
- package/esm2020/table/public-api.mjs +0 -20
- package/esm2020/table/row.mjs +0 -262
- package/esm2020/table/sticky-position-listener.mjs +0 -11
- package/esm2020/table/sticky-styler.mjs +0 -345
- package/esm2020/table/table-errors.mjs +0 -67
- package/esm2020/table/table-module.mjs +0 -94
- package/esm2020/table/table.mjs +0 -1065
- package/esm2020/table/table_public_index.mjs +0 -5
- package/esm2020/table/text-column.mjs +0 -153
- package/esm2020/table/tokens.mjs +0 -16
- package/esm2020/text-field/autofill.mjs +0 -113
- package/esm2020/text-field/autosize.mjs +0 -309
- package/esm2020/text-field/index.mjs +0 -9
- package/esm2020/text-field/public-api.mjs +0 -11
- package/esm2020/text-field/text-field-module.mjs +0 -24
- package/esm2020/text-field/text-field_public_index.mjs +0 -5
- package/esm2020/tree/control/base-tree-control.mjs +0 -57
- package/esm2020/tree/control/flat-tree-control.mjs +0 -51
- package/esm2020/tree/control/nested-tree-control.mjs +0 -58
- package/esm2020/tree/control/tree-control.mjs +0 -2
- package/esm2020/tree/index.mjs +0 -9
- package/esm2020/tree/nested-node.mjs +0 -112
- package/esm2020/tree/node.mjs +0 -35
- package/esm2020/tree/outlet.mjs +0 -39
- package/esm2020/tree/padding.mjs +0 -131
- package/esm2020/tree/public-api.mjs +0 -20
- package/esm2020/tree/toggle.mjs +0 -50
- package/esm2020/tree/tree-errors.mjs +0 -43
- package/esm2020/tree/tree-module.mjs +0 -49
- package/esm2020/tree/tree.mjs +0 -347
- package/esm2020/tree/tree_public_index.mjs +0 -5
- package/esm2020/version.mjs +0 -11
- package/fesm2015/a11y.mjs +0 -2473
- package/fesm2015/a11y.mjs.map +0 -1
- package/fesm2015/accordion.mjs +0 -414
- package/fesm2015/accordion.mjs.map +0 -1
- package/fesm2015/bidi.mjs +0 -194
- package/fesm2015/bidi.mjs.map +0 -1
- package/fesm2015/cdk.mjs +0 -30
- package/fesm2015/cdk.mjs.map +0 -1
- package/fesm2015/clipboard.mjs +0 -263
- package/fesm2015/clipboard.mjs.map +0 -1
- package/fesm2015/coercion.mjs +0 -132
- package/fesm2015/coercion.mjs.map +0 -1
- package/fesm2015/collections.mjs +0 -519
- package/fesm2015/collections.mjs.map +0 -1
- package/fesm2015/dialog.mjs +0 -1050
- package/fesm2015/dialog.mjs.map +0 -1
- package/fesm2015/drag-drop.mjs +0 -3812
- package/fesm2015/drag-drop.mjs.map +0 -1
- package/fesm2015/keycodes.mjs.map +0 -1
- package/fesm2015/layout.mjs +0 -337
- package/fesm2015/layout.mjs.map +0 -1
- package/fesm2015/listbox.mjs +0 -1200
- package/fesm2015/listbox.mjs.map +0 -1
- package/fesm2015/menu.mjs +0 -2719
- package/fesm2015/menu.mjs.map +0 -1
- package/fesm2015/observers.mjs +0 -326
- package/fesm2015/observers.mjs.map +0 -1
- package/fesm2015/overlay.mjs +0 -3137
- package/fesm2015/overlay.mjs.map +0 -1
- package/fesm2015/platform.mjs +0 -385
- package/fesm2015/platform.mjs.map +0 -1
- package/fesm2015/portal.mjs +0 -691
- package/fesm2015/portal.mjs.map +0 -1
- package/fesm2015/scrolling.mjs.map +0 -1
- package/fesm2015/stepper.mjs +0 -989
- package/fesm2015/stepper.mjs.map +0 -1
- package/fesm2015/table.mjs +0 -2356
- package/fesm2015/table.mjs.map +0 -1
- package/fesm2015/testing.mjs +0 -833
- package/fesm2015/testing.mjs.map +0 -1
- package/fesm2015/text-field.mjs +0 -461
- package/fesm2015/text-field.mjs.map +0 -1
- package/fesm2015/tree.mjs +0 -1303
- package/fesm2015/tree.mjs.map +0 -1
- package/fesm2020/a11y.mjs +0 -2476
- package/fesm2020/a11y.mjs.map +0 -1
- package/fesm2020/accordion.mjs +0 -414
- package/fesm2020/accordion.mjs.map +0 -1
- package/fesm2020/bidi.mjs +0 -192
- package/fesm2020/bidi.mjs.map +0 -1
- package/fesm2020/cdk.mjs +0 -30
- package/fesm2020/cdk.mjs.map +0 -1
- package/fesm2020/clipboard.mjs.map +0 -1
- package/fesm2020/coercion.mjs +0 -132
- package/fesm2020/coercion.mjs.map +0 -1
- package/fesm2020/collections.mjs +0 -535
- package/fesm2020/collections.mjs.map +0 -1
- package/fesm2020/dialog.mjs.map +0 -1
- package/fesm2020/drag-drop.mjs.map +0 -1
- package/fesm2020/keycodes.mjs +0 -167
- package/fesm2020/keycodes.mjs.map +0 -1
- package/fesm2020/layout.mjs +0 -337
- package/fesm2020/layout.mjs.map +0 -1
- package/fesm2020/listbox.mjs +0 -1164
- package/fesm2020/listbox.mjs.map +0 -1
- package/fesm2020/menu.mjs +0 -2615
- package/fesm2020/menu.mjs.map +0 -1
- package/fesm2020/observers.mjs +0 -325
- package/fesm2020/observers.mjs.map +0 -1
- package/fesm2020/overlay.mjs.map +0 -1
- package/fesm2020/platform.mjs +0 -383
- package/fesm2020/platform.mjs.map +0 -1
- package/fesm2020/portal.mjs.map +0 -1
- package/fesm2020/scrolling.mjs +0 -1591
- package/fesm2020/scrolling.mjs.map +0 -1
- package/fesm2020/stepper.mjs +0 -985
- package/fesm2020/stepper.mjs.map +0 -1
- package/fesm2020/table.mjs.map +0 -1
- package/fesm2020/testing.mjs +0 -797
- package/fesm2020/testing.mjs.map +0 -1
- package/fesm2020/text-field.mjs.map +0 -1
- package/fesm2020/tree.mjs +0 -1305
- package/fesm2020/tree.mjs.map +0 -1
- package/overlay/_index.import.scss +0 -13
- package/text-field/_index.import.scss +0 -2
|
@@ -1,985 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright Google LLC All Rights Reserved.
|
|
4
|
-
*
|
|
5
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
-
* found in the LICENSE file at https://angular.io/license
|
|
7
|
-
*/
|
|
8
|
-
import { ElementRef } from '@angular/core';
|
|
9
|
-
import { ConnectedOverlayPositionChange, validateHorizontalPosition, validateVerticalPosition, } from './connected-position';
|
|
10
|
-
import { Subscription, Subject } from 'rxjs';
|
|
11
|
-
import { isElementScrolledOutsideView, isElementClippedByScrolling } from './scroll-clip';
|
|
12
|
-
import { coerceCssPixelValue, coerceArray } from '@kato-lee/cdk/coercion';
|
|
13
|
-
// TODO: refactor clipping detection into a separate thing (part of scrolling module)
|
|
14
|
-
// TODO: doesn't handle both flexible width and height when it has to scroll along both axis.
|
|
15
|
-
/** Class to be added to the overlay bounding box. */
|
|
16
|
-
const boundingBoxClass = 'cdk-overlay-connected-position-bounding-box';
|
|
17
|
-
/** Regex used to split a string on its CSS units. */
|
|
18
|
-
const cssUnitPattern = /([A-Za-z%]+)$/;
|
|
19
|
-
/**
|
|
20
|
-
* A strategy for positioning overlays. Using this strategy, an overlay is given an
|
|
21
|
-
* implicit position relative some origin element. The relative position is defined in terms of
|
|
22
|
-
* a point on the origin element that is connected to a point on the overlay element. For example,
|
|
23
|
-
* a basic dropdown is connecting the bottom-left corner of the origin to the top-left corner
|
|
24
|
-
* of the overlay.
|
|
25
|
-
*/
|
|
26
|
-
export class FlexibleConnectedPositionStrategy {
|
|
27
|
-
constructor(connectedTo, _viewportRuler, _document, _platform, _overlayContainer) {
|
|
28
|
-
this._viewportRuler = _viewportRuler;
|
|
29
|
-
this._document = _document;
|
|
30
|
-
this._platform = _platform;
|
|
31
|
-
this._overlayContainer = _overlayContainer;
|
|
32
|
-
/** Last size used for the bounding box. Used to avoid resizing the overlay after open. */
|
|
33
|
-
this._lastBoundingBoxSize = { width: 0, height: 0 };
|
|
34
|
-
/** Whether the overlay was pushed in a previous positioning. */
|
|
35
|
-
this._isPushed = false;
|
|
36
|
-
/** Whether the overlay can be pushed on-screen on the initial open. */
|
|
37
|
-
this._canPush = true;
|
|
38
|
-
/** Whether the overlay can grow via flexible width/height after the initial open. */
|
|
39
|
-
this._growAfterOpen = false;
|
|
40
|
-
/** Whether the overlay's width and height can be constrained to fit within the viewport. */
|
|
41
|
-
this._hasFlexibleDimensions = true;
|
|
42
|
-
/** Whether the overlay position is locked. */
|
|
43
|
-
this._positionLocked = false;
|
|
44
|
-
/** Amount of space that must be maintained between the overlay and the edge of the viewport. */
|
|
45
|
-
this._viewportMargin = 0;
|
|
46
|
-
/** The Scrollable containers used to check scrollable view properties on position change. */
|
|
47
|
-
this._scrollables = [];
|
|
48
|
-
/** Ordered list of preferred positions, from most to least desirable. */
|
|
49
|
-
this._preferredPositions = [];
|
|
50
|
-
/** Subject that emits whenever the position changes. */
|
|
51
|
-
this._positionChanges = new Subject();
|
|
52
|
-
/** Subscription to viewport size changes. */
|
|
53
|
-
this._resizeSubscription = Subscription.EMPTY;
|
|
54
|
-
/** Default offset for the overlay along the x axis. */
|
|
55
|
-
this._offsetX = 0;
|
|
56
|
-
/** Default offset for the overlay along the y axis. */
|
|
57
|
-
this._offsetY = 0;
|
|
58
|
-
/** Keeps track of the CSS classes that the position strategy has applied on the overlay panel. */
|
|
59
|
-
this._appliedPanelClasses = [];
|
|
60
|
-
/** Observable sequence of position changes. */
|
|
61
|
-
this.positionChanges = this._positionChanges;
|
|
62
|
-
this.setOrigin(connectedTo);
|
|
63
|
-
}
|
|
64
|
-
/** Ordered list of preferred positions, from most to least desirable. */
|
|
65
|
-
get positions() {
|
|
66
|
-
return this._preferredPositions;
|
|
67
|
-
}
|
|
68
|
-
/** Attaches this position strategy to an overlay. */
|
|
69
|
-
attach(overlayRef) {
|
|
70
|
-
if (this._overlayRef &&
|
|
71
|
-
overlayRef !== this._overlayRef &&
|
|
72
|
-
(typeof ngDevMode === 'undefined' || ngDevMode)) {
|
|
73
|
-
throw Error('This position strategy is already attached to an overlay');
|
|
74
|
-
}
|
|
75
|
-
this._validatePositions();
|
|
76
|
-
overlayRef.hostElement.classList.add(boundingBoxClass);
|
|
77
|
-
this._overlayRef = overlayRef;
|
|
78
|
-
this._boundingBox = overlayRef.hostElement;
|
|
79
|
-
this._pane = overlayRef.overlayElement;
|
|
80
|
-
this._isDisposed = false;
|
|
81
|
-
this._isInitialRender = true;
|
|
82
|
-
this._lastPosition = null;
|
|
83
|
-
this._resizeSubscription.unsubscribe();
|
|
84
|
-
this._resizeSubscription = this._viewportRuler.change().subscribe(() => {
|
|
85
|
-
// When the window is resized, we want to trigger the next reposition as if it
|
|
86
|
-
// was an initial render, in order for the strategy to pick a new optimal position,
|
|
87
|
-
// otherwise position locking will cause it to stay at the old one.
|
|
88
|
-
this._isInitialRender = true;
|
|
89
|
-
this.apply();
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Updates the position of the overlay element, using whichever preferred position relative
|
|
94
|
-
* to the origin best fits on-screen.
|
|
95
|
-
*
|
|
96
|
-
* The selection of a position goes as follows:
|
|
97
|
-
* - If any positions fit completely within the viewport as-is,
|
|
98
|
-
* choose the first position that does so.
|
|
99
|
-
* - If flexible dimensions are enabled and at least one satisfies the given minimum width/height,
|
|
100
|
-
* choose the position with the greatest available size modified by the positions' weight.
|
|
101
|
-
* - If pushing is enabled, take the position that went off-screen the least and push it
|
|
102
|
-
* on-screen.
|
|
103
|
-
* - If none of the previous criteria were met, use the position that goes off-screen the least.
|
|
104
|
-
* @docs-private
|
|
105
|
-
*/
|
|
106
|
-
apply() {
|
|
107
|
-
// We shouldn't do anything if the strategy was disposed or we're on the server.
|
|
108
|
-
if (this._isDisposed || !this._platform.isBrowser) {
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
// If the position has been applied already (e.g. when the overlay was opened) and the
|
|
112
|
-
// consumer opted into locking in the position, re-use the old position, in order to
|
|
113
|
-
// prevent the overlay from jumping around.
|
|
114
|
-
if (!this._isInitialRender && this._positionLocked && this._lastPosition) {
|
|
115
|
-
this.reapplyLastPosition();
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
this._clearPanelClasses();
|
|
119
|
-
this._resetOverlayElementStyles();
|
|
120
|
-
this._resetBoundingBoxStyles();
|
|
121
|
-
// We need the bounding rects for the origin, the overlay and the container to determine how to position
|
|
122
|
-
// the overlay relative to the origin.
|
|
123
|
-
// We use the viewport rect to determine whether a position would go off-screen.
|
|
124
|
-
this._viewportRect = this._getNarrowedViewportRect();
|
|
125
|
-
this._originRect = this._getOriginRect();
|
|
126
|
-
this._overlayRect = this._pane.getBoundingClientRect();
|
|
127
|
-
this._containerRect = this._overlayContainer.getContainerElement().getBoundingClientRect();
|
|
128
|
-
const originRect = this._originRect;
|
|
129
|
-
const overlayRect = this._overlayRect;
|
|
130
|
-
const viewportRect = this._viewportRect;
|
|
131
|
-
const containerRect = this._containerRect;
|
|
132
|
-
// Positions where the overlay will fit with flexible dimensions.
|
|
133
|
-
const flexibleFits = [];
|
|
134
|
-
// Fallback if none of the preferred positions fit within the viewport.
|
|
135
|
-
let fallback;
|
|
136
|
-
// Go through each of the preferred positions looking for a good fit.
|
|
137
|
-
// If a good fit is found, it will be applied immediately.
|
|
138
|
-
for (let pos of this._preferredPositions) {
|
|
139
|
-
// Get the exact (x, y) coordinate for the point-of-origin on the origin element.
|
|
140
|
-
let originPoint = this._getOriginPoint(originRect, containerRect, pos);
|
|
141
|
-
// From that point-of-origin, get the exact (x, y) coordinate for the top-left corner of the
|
|
142
|
-
// overlay in this position. We use the top-left corner for calculations and later translate
|
|
143
|
-
// this into an appropriate (top, left, bottom, right) style.
|
|
144
|
-
let overlayPoint = this._getOverlayPoint(originPoint, overlayRect, pos);
|
|
145
|
-
// Calculate how well the overlay would fit into the viewport with this point.
|
|
146
|
-
let overlayFit = this._getOverlayFit(overlayPoint, overlayRect, viewportRect, pos);
|
|
147
|
-
// If the overlay, without any further work, fits into the viewport, use this position.
|
|
148
|
-
if (overlayFit.isCompletelyWithinViewport) {
|
|
149
|
-
this._isPushed = false;
|
|
150
|
-
this._applyPosition(pos, originPoint);
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
// If the overlay has flexible dimensions, we can use this position
|
|
154
|
-
// so long as there's enough space for the minimum dimensions.
|
|
155
|
-
if (this._canFitWithFlexibleDimensions(overlayFit, overlayPoint, viewportRect)) {
|
|
156
|
-
// Save positions where the overlay will fit with flexible dimensions. We will use these
|
|
157
|
-
// if none of the positions fit *without* flexible dimensions.
|
|
158
|
-
flexibleFits.push({
|
|
159
|
-
position: pos,
|
|
160
|
-
origin: originPoint,
|
|
161
|
-
overlayRect,
|
|
162
|
-
boundingBoxRect: this._calculateBoundingBoxRect(originPoint, pos),
|
|
163
|
-
});
|
|
164
|
-
continue;
|
|
165
|
-
}
|
|
166
|
-
// If the current preferred position does not fit on the screen, remember the position
|
|
167
|
-
// if it has more visible area on-screen than we've seen and move onto the next preferred
|
|
168
|
-
// position.
|
|
169
|
-
if (!fallback || fallback.overlayFit.visibleArea < overlayFit.visibleArea) {
|
|
170
|
-
fallback = { overlayFit, overlayPoint, originPoint, position: pos, overlayRect };
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
// If there are any positions where the overlay would fit with flexible dimensions, choose the
|
|
174
|
-
// one that has the greatest area available modified by the position's weight
|
|
175
|
-
if (flexibleFits.length) {
|
|
176
|
-
let bestFit = null;
|
|
177
|
-
let bestScore = -1;
|
|
178
|
-
for (const fit of flexibleFits) {
|
|
179
|
-
const score = fit.boundingBoxRect.width * fit.boundingBoxRect.height * (fit.position.weight || 1);
|
|
180
|
-
if (score > bestScore) {
|
|
181
|
-
bestScore = score;
|
|
182
|
-
bestFit = fit;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
this._isPushed = false;
|
|
186
|
-
this._applyPosition(bestFit.position, bestFit.origin);
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
// When none of the preferred positions fit within the viewport, take the position
|
|
190
|
-
// that went off-screen the least and attempt to push it on-screen.
|
|
191
|
-
if (this._canPush) {
|
|
192
|
-
// TODO(jelbourn): after pushing, the opening "direction" of the overlay might not make sense.
|
|
193
|
-
this._isPushed = true;
|
|
194
|
-
this._applyPosition(fallback.position, fallback.originPoint);
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
// All options for getting the overlay within the viewport have been exhausted, so go with the
|
|
198
|
-
// position that went off-screen the least.
|
|
199
|
-
this._applyPosition(fallback.position, fallback.originPoint);
|
|
200
|
-
}
|
|
201
|
-
detach() {
|
|
202
|
-
this._clearPanelClasses();
|
|
203
|
-
this._lastPosition = null;
|
|
204
|
-
this._previousPushAmount = null;
|
|
205
|
-
this._resizeSubscription.unsubscribe();
|
|
206
|
-
}
|
|
207
|
-
/** Cleanup after the element gets destroyed. */
|
|
208
|
-
dispose() {
|
|
209
|
-
if (this._isDisposed) {
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
// We can't use `_resetBoundingBoxStyles` here, because it resets
|
|
213
|
-
// some properties to zero, rather than removing them.
|
|
214
|
-
if (this._boundingBox) {
|
|
215
|
-
extendStyles(this._boundingBox.style, {
|
|
216
|
-
top: '',
|
|
217
|
-
left: '',
|
|
218
|
-
right: '',
|
|
219
|
-
bottom: '',
|
|
220
|
-
height: '',
|
|
221
|
-
width: '',
|
|
222
|
-
alignItems: '',
|
|
223
|
-
justifyContent: '',
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
if (this._pane) {
|
|
227
|
-
this._resetOverlayElementStyles();
|
|
228
|
-
}
|
|
229
|
-
if (this._overlayRef) {
|
|
230
|
-
this._overlayRef.hostElement.classList.remove(boundingBoxClass);
|
|
231
|
-
}
|
|
232
|
-
this.detach();
|
|
233
|
-
this._positionChanges.complete();
|
|
234
|
-
this._overlayRef = this._boundingBox = null;
|
|
235
|
-
this._isDisposed = true;
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* This re-aligns the overlay element with the trigger in its last calculated position,
|
|
239
|
-
* even if a position higher in the "preferred positions" list would now fit. This
|
|
240
|
-
* allows one to re-align the panel without changing the orientation of the panel.
|
|
241
|
-
*/
|
|
242
|
-
reapplyLastPosition() {
|
|
243
|
-
if (this._isDisposed || !this._platform.isBrowser) {
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
const lastPosition = this._lastPosition;
|
|
247
|
-
if (lastPosition) {
|
|
248
|
-
this._originRect = this._getOriginRect();
|
|
249
|
-
this._overlayRect = this._pane.getBoundingClientRect();
|
|
250
|
-
this._viewportRect = this._getNarrowedViewportRect();
|
|
251
|
-
this._containerRect = this._overlayContainer.getContainerElement().getBoundingClientRect();
|
|
252
|
-
const originPoint = this._getOriginPoint(this._originRect, this._containerRect, lastPosition);
|
|
253
|
-
this._applyPosition(lastPosition, originPoint);
|
|
254
|
-
}
|
|
255
|
-
else {
|
|
256
|
-
this.apply();
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
/**
|
|
260
|
-
* Sets the list of Scrollable containers that host the origin element so that
|
|
261
|
-
* on reposition we can evaluate if it or the overlay has been clipped or outside view. Every
|
|
262
|
-
* Scrollable must be an ancestor element of the strategy's origin element.
|
|
263
|
-
*/
|
|
264
|
-
withScrollableContainers(scrollables) {
|
|
265
|
-
this._scrollables = scrollables;
|
|
266
|
-
return this;
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* Adds new preferred positions.
|
|
270
|
-
* @param positions List of positions options for this overlay.
|
|
271
|
-
*/
|
|
272
|
-
withPositions(positions) {
|
|
273
|
-
this._preferredPositions = positions;
|
|
274
|
-
// If the last calculated position object isn't part of the positions anymore, clear
|
|
275
|
-
// it in order to avoid it being picked up if the consumer tries to re-apply.
|
|
276
|
-
if (positions.indexOf(this._lastPosition) === -1) {
|
|
277
|
-
this._lastPosition = null;
|
|
278
|
-
}
|
|
279
|
-
this._validatePositions();
|
|
280
|
-
return this;
|
|
281
|
-
}
|
|
282
|
-
/**
|
|
283
|
-
* Sets a minimum distance the overlay may be positioned to the edge of the viewport.
|
|
284
|
-
* @param margin Required margin between the overlay and the viewport edge in pixels.
|
|
285
|
-
*/
|
|
286
|
-
withViewportMargin(margin) {
|
|
287
|
-
this._viewportMargin = margin;
|
|
288
|
-
return this;
|
|
289
|
-
}
|
|
290
|
-
/** Sets whether the overlay's width and height can be constrained to fit within the viewport. */
|
|
291
|
-
withFlexibleDimensions(flexibleDimensions = true) {
|
|
292
|
-
this._hasFlexibleDimensions = flexibleDimensions;
|
|
293
|
-
return this;
|
|
294
|
-
}
|
|
295
|
-
/** Sets whether the overlay can grow after the initial open via flexible width/height. */
|
|
296
|
-
withGrowAfterOpen(growAfterOpen = true) {
|
|
297
|
-
this._growAfterOpen = growAfterOpen;
|
|
298
|
-
return this;
|
|
299
|
-
}
|
|
300
|
-
/** Sets whether the overlay can be pushed on-screen if none of the provided positions fit. */
|
|
301
|
-
withPush(canPush = true) {
|
|
302
|
-
this._canPush = canPush;
|
|
303
|
-
return this;
|
|
304
|
-
}
|
|
305
|
-
/**
|
|
306
|
-
* Sets whether the overlay's position should be locked in after it is positioned
|
|
307
|
-
* initially. When an overlay is locked in, it won't attempt to reposition itself
|
|
308
|
-
* when the position is re-applied (e.g. when the user scrolls away).
|
|
309
|
-
* @param isLocked Whether the overlay should locked in.
|
|
310
|
-
*/
|
|
311
|
-
withLockedPosition(isLocked = true) {
|
|
312
|
-
this._positionLocked = isLocked;
|
|
313
|
-
return this;
|
|
314
|
-
}
|
|
315
|
-
/**
|
|
316
|
-
* Sets the origin, relative to which to position the overlay.
|
|
317
|
-
* Using an element origin is useful for building components that need to be positioned
|
|
318
|
-
* relatively to a trigger (e.g. dropdown menus or tooltips), whereas using a point can be
|
|
319
|
-
* used for cases like contextual menus which open relative to the user's pointer.
|
|
320
|
-
* @param origin Reference to the new origin.
|
|
321
|
-
*/
|
|
322
|
-
setOrigin(origin) {
|
|
323
|
-
this._origin = origin;
|
|
324
|
-
return this;
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* Sets the default offset for the overlay's connection point on the x-axis.
|
|
328
|
-
* @param offset New offset in the X axis.
|
|
329
|
-
*/
|
|
330
|
-
withDefaultOffsetX(offset) {
|
|
331
|
-
this._offsetX = offset;
|
|
332
|
-
return this;
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* Sets the default offset for the overlay's connection point on the y-axis.
|
|
336
|
-
* @param offset New offset in the Y axis.
|
|
337
|
-
*/
|
|
338
|
-
withDefaultOffsetY(offset) {
|
|
339
|
-
this._offsetY = offset;
|
|
340
|
-
return this;
|
|
341
|
-
}
|
|
342
|
-
/**
|
|
343
|
-
* Configures that the position strategy should set a `transform-origin` on some elements
|
|
344
|
-
* inside the overlay, depending on the current position that is being applied. This is
|
|
345
|
-
* useful for the cases where the origin of an animation can change depending on the
|
|
346
|
-
* alignment of the overlay.
|
|
347
|
-
* @param selector CSS selector that will be used to find the target
|
|
348
|
-
* elements onto which to set the transform origin.
|
|
349
|
-
*/
|
|
350
|
-
withTransformOriginOn(selector) {
|
|
351
|
-
this._transformOriginSelector = selector;
|
|
352
|
-
return this;
|
|
353
|
-
}
|
|
354
|
-
/**
|
|
355
|
-
* Gets the (x, y) coordinate of a connection point on the origin based on a relative position.
|
|
356
|
-
*/
|
|
357
|
-
_getOriginPoint(originRect, containerRect, pos) {
|
|
358
|
-
let x;
|
|
359
|
-
if (pos.originX == 'center') {
|
|
360
|
-
// Note: when centering we should always use the `left`
|
|
361
|
-
// offset, otherwise the position will be wrong in RTL.
|
|
362
|
-
x = originRect.left + originRect.width / 2;
|
|
363
|
-
}
|
|
364
|
-
else {
|
|
365
|
-
const startX = this._isRtl() ? originRect.right : originRect.left;
|
|
366
|
-
const endX = this._isRtl() ? originRect.left : originRect.right;
|
|
367
|
-
x = pos.originX == 'start' ? startX : endX;
|
|
368
|
-
}
|
|
369
|
-
// When zooming in Safari the container rectangle contains negative values for the position
|
|
370
|
-
// and we need to re-add them to the calculated coordinates.
|
|
371
|
-
if (containerRect.left < 0) {
|
|
372
|
-
x -= containerRect.left;
|
|
373
|
-
}
|
|
374
|
-
let y;
|
|
375
|
-
if (pos.originY == 'center') {
|
|
376
|
-
y = originRect.top + originRect.height / 2;
|
|
377
|
-
}
|
|
378
|
-
else {
|
|
379
|
-
y = pos.originY == 'top' ? originRect.top : originRect.bottom;
|
|
380
|
-
}
|
|
381
|
-
// Normally the containerRect's top value would be zero, however when the overlay is attached to an input
|
|
382
|
-
// (e.g. in an autocomplete), mobile browsers will shift everything in order to put the input in the middle
|
|
383
|
-
// of the screen and to make space for the virtual keyboard. We need to account for this offset,
|
|
384
|
-
// otherwise our positioning will be thrown off.
|
|
385
|
-
// Additionally, when zooming in Safari this fixes the vertical position.
|
|
386
|
-
if (containerRect.top < 0) {
|
|
387
|
-
y -= containerRect.top;
|
|
388
|
-
}
|
|
389
|
-
return { x, y };
|
|
390
|
-
}
|
|
391
|
-
/**
|
|
392
|
-
* Gets the (x, y) coordinate of the top-left corner of the overlay given a given position and
|
|
393
|
-
* origin point to which the overlay should be connected.
|
|
394
|
-
*/
|
|
395
|
-
_getOverlayPoint(originPoint, overlayRect, pos) {
|
|
396
|
-
// Calculate the (overlayStartX, overlayStartY), the start of the
|
|
397
|
-
// potential overlay position relative to the origin point.
|
|
398
|
-
let overlayStartX;
|
|
399
|
-
if (pos.overlayX == 'center') {
|
|
400
|
-
overlayStartX = -overlayRect.width / 2;
|
|
401
|
-
}
|
|
402
|
-
else if (pos.overlayX === 'start') {
|
|
403
|
-
overlayStartX = this._isRtl() ? -overlayRect.width : 0;
|
|
404
|
-
}
|
|
405
|
-
else {
|
|
406
|
-
overlayStartX = this._isRtl() ? 0 : -overlayRect.width;
|
|
407
|
-
}
|
|
408
|
-
let overlayStartY;
|
|
409
|
-
if (pos.overlayY == 'center') {
|
|
410
|
-
overlayStartY = -overlayRect.height / 2;
|
|
411
|
-
}
|
|
412
|
-
else {
|
|
413
|
-
overlayStartY = pos.overlayY == 'top' ? 0 : -overlayRect.height;
|
|
414
|
-
}
|
|
415
|
-
// The (x, y) coordinates of the overlay.
|
|
416
|
-
return {
|
|
417
|
-
x: originPoint.x + overlayStartX,
|
|
418
|
-
y: originPoint.y + overlayStartY,
|
|
419
|
-
};
|
|
420
|
-
}
|
|
421
|
-
/** Gets how well an overlay at the given point will fit within the viewport. */
|
|
422
|
-
_getOverlayFit(point, rawOverlayRect, viewport, position) {
|
|
423
|
-
// Round the overlay rect when comparing against the
|
|
424
|
-
// viewport, because the viewport is always rounded.
|
|
425
|
-
const overlay = getRoundedBoundingClientRect(rawOverlayRect);
|
|
426
|
-
let { x, y } = point;
|
|
427
|
-
let offsetX = this._getOffset(position, 'x');
|
|
428
|
-
let offsetY = this._getOffset(position, 'y');
|
|
429
|
-
// Account for the offsets since they could push the overlay out of the viewport.
|
|
430
|
-
if (offsetX) {
|
|
431
|
-
x += offsetX;
|
|
432
|
-
}
|
|
433
|
-
if (offsetY) {
|
|
434
|
-
y += offsetY;
|
|
435
|
-
}
|
|
436
|
-
// How much the overlay would overflow at this position, on each side.
|
|
437
|
-
let leftOverflow = 0 - x;
|
|
438
|
-
let rightOverflow = x + overlay.width - viewport.width;
|
|
439
|
-
let topOverflow = 0 - y;
|
|
440
|
-
let bottomOverflow = y + overlay.height - viewport.height;
|
|
441
|
-
// Visible parts of the element on each axis.
|
|
442
|
-
let visibleWidth = this._subtractOverflows(overlay.width, leftOverflow, rightOverflow);
|
|
443
|
-
let visibleHeight = this._subtractOverflows(overlay.height, topOverflow, bottomOverflow);
|
|
444
|
-
let visibleArea = visibleWidth * visibleHeight;
|
|
445
|
-
return {
|
|
446
|
-
visibleArea,
|
|
447
|
-
isCompletelyWithinViewport: overlay.width * overlay.height === visibleArea,
|
|
448
|
-
fitsInViewportVertically: visibleHeight === overlay.height,
|
|
449
|
-
fitsInViewportHorizontally: visibleWidth == overlay.width,
|
|
450
|
-
};
|
|
451
|
-
}
|
|
452
|
-
/**
|
|
453
|
-
* Whether the overlay can fit within the viewport when it may resize either its width or height.
|
|
454
|
-
* @param fit How well the overlay fits in the viewport at some position.
|
|
455
|
-
* @param point The (x, y) coordinates of the overlay at some position.
|
|
456
|
-
* @param viewport The geometry of the viewport.
|
|
457
|
-
*/
|
|
458
|
-
_canFitWithFlexibleDimensions(fit, point, viewport) {
|
|
459
|
-
if (this._hasFlexibleDimensions) {
|
|
460
|
-
const availableHeight = viewport.bottom - point.y;
|
|
461
|
-
const availableWidth = viewport.right - point.x;
|
|
462
|
-
const minHeight = getPixelValue(this._overlayRef.getConfig().minHeight);
|
|
463
|
-
const minWidth = getPixelValue(this._overlayRef.getConfig().minWidth);
|
|
464
|
-
const verticalFit = fit.fitsInViewportVertically || (minHeight != null && minHeight <= availableHeight);
|
|
465
|
-
const horizontalFit = fit.fitsInViewportHorizontally || (minWidth != null && minWidth <= availableWidth);
|
|
466
|
-
return verticalFit && horizontalFit;
|
|
467
|
-
}
|
|
468
|
-
return false;
|
|
469
|
-
}
|
|
470
|
-
/**
|
|
471
|
-
* Gets the point at which the overlay can be "pushed" on-screen. If the overlay is larger than
|
|
472
|
-
* the viewport, the top-left corner will be pushed on-screen (with overflow occurring on the
|
|
473
|
-
* right and bottom).
|
|
474
|
-
*
|
|
475
|
-
* @param start Starting point from which the overlay is pushed.
|
|
476
|
-
* @param rawOverlayRect Dimensions of the overlay.
|
|
477
|
-
* @param scrollPosition Current viewport scroll position.
|
|
478
|
-
* @returns The point at which to position the overlay after pushing. This is effectively a new
|
|
479
|
-
* originPoint.
|
|
480
|
-
*/
|
|
481
|
-
_pushOverlayOnScreen(start, rawOverlayRect, scrollPosition) {
|
|
482
|
-
// If the position is locked and we've pushed the overlay already, reuse the previous push
|
|
483
|
-
// amount, rather than pushing it again. If we were to continue pushing, the element would
|
|
484
|
-
// remain in the viewport, which goes against the expectations when position locking is enabled.
|
|
485
|
-
if (this._previousPushAmount && this._positionLocked) {
|
|
486
|
-
return {
|
|
487
|
-
x: start.x + this._previousPushAmount.x,
|
|
488
|
-
y: start.y + this._previousPushAmount.y,
|
|
489
|
-
};
|
|
490
|
-
}
|
|
491
|
-
// Round the overlay rect when comparing against the
|
|
492
|
-
// viewport, because the viewport is always rounded.
|
|
493
|
-
const overlay = getRoundedBoundingClientRect(rawOverlayRect);
|
|
494
|
-
const viewport = this._viewportRect;
|
|
495
|
-
// Determine how much the overlay goes outside the viewport on each
|
|
496
|
-
// side, which we'll use to decide which direction to push it.
|
|
497
|
-
const overflowRight = Math.max(start.x + overlay.width - viewport.width, 0);
|
|
498
|
-
const overflowBottom = Math.max(start.y + overlay.height - viewport.height, 0);
|
|
499
|
-
const overflowTop = Math.max(viewport.top - scrollPosition.top - start.y, 0);
|
|
500
|
-
const overflowLeft = Math.max(viewport.left - scrollPosition.left - start.x, 0);
|
|
501
|
-
// Amount by which to push the overlay in each axis such that it remains on-screen.
|
|
502
|
-
let pushX = 0;
|
|
503
|
-
let pushY = 0;
|
|
504
|
-
// If the overlay fits completely within the bounds of the viewport, push it from whichever
|
|
505
|
-
// direction is goes off-screen. Otherwise, push the top-left corner such that its in the
|
|
506
|
-
// viewport and allow for the trailing end of the overlay to go out of bounds.
|
|
507
|
-
if (overlay.width <= viewport.width) {
|
|
508
|
-
pushX = overflowLeft || -overflowRight;
|
|
509
|
-
}
|
|
510
|
-
else {
|
|
511
|
-
pushX = start.x < this._viewportMargin ? viewport.left - scrollPosition.left - start.x : 0;
|
|
512
|
-
}
|
|
513
|
-
if (overlay.height <= viewport.height) {
|
|
514
|
-
pushY = overflowTop || -overflowBottom;
|
|
515
|
-
}
|
|
516
|
-
else {
|
|
517
|
-
pushY = start.y < this._viewportMargin ? viewport.top - scrollPosition.top - start.y : 0;
|
|
518
|
-
}
|
|
519
|
-
this._previousPushAmount = { x: pushX, y: pushY };
|
|
520
|
-
return {
|
|
521
|
-
x: start.x + pushX,
|
|
522
|
-
y: start.y + pushY,
|
|
523
|
-
};
|
|
524
|
-
}
|
|
525
|
-
/**
|
|
526
|
-
* Applies a computed position to the overlay and emits a position change.
|
|
527
|
-
* @param position The position preference
|
|
528
|
-
* @param originPoint The point on the origin element where the overlay is connected.
|
|
529
|
-
*/
|
|
530
|
-
_applyPosition(position, originPoint) {
|
|
531
|
-
this._setTransformOrigin(position);
|
|
532
|
-
this._setOverlayElementStyles(originPoint, position);
|
|
533
|
-
this._setBoundingBoxStyles(originPoint, position);
|
|
534
|
-
if (position.panelClass) {
|
|
535
|
-
this._addPanelClasses(position.panelClass);
|
|
536
|
-
}
|
|
537
|
-
// Save the last connected position in case the position needs to be re-calculated.
|
|
538
|
-
this._lastPosition = position;
|
|
539
|
-
// Notify that the position has been changed along with its change properties.
|
|
540
|
-
// We only emit if we've got any subscriptions, because the scroll visibility
|
|
541
|
-
// calculations can be somewhat expensive.
|
|
542
|
-
if (this._positionChanges.observers.length) {
|
|
543
|
-
const scrollableViewProperties = this._getScrollVisibility();
|
|
544
|
-
const changeEvent = new ConnectedOverlayPositionChange(position, scrollableViewProperties);
|
|
545
|
-
this._positionChanges.next(changeEvent);
|
|
546
|
-
}
|
|
547
|
-
this._isInitialRender = false;
|
|
548
|
-
}
|
|
549
|
-
/** Sets the transform origin based on the configured selector and the passed-in position. */
|
|
550
|
-
_setTransformOrigin(position) {
|
|
551
|
-
if (!this._transformOriginSelector) {
|
|
552
|
-
return;
|
|
553
|
-
}
|
|
554
|
-
const elements = this._boundingBox.querySelectorAll(this._transformOriginSelector);
|
|
555
|
-
let xOrigin;
|
|
556
|
-
let yOrigin = position.overlayY;
|
|
557
|
-
if (position.overlayX === 'center') {
|
|
558
|
-
xOrigin = 'center';
|
|
559
|
-
}
|
|
560
|
-
else if (this._isRtl()) {
|
|
561
|
-
xOrigin = position.overlayX === 'start' ? 'right' : 'left';
|
|
562
|
-
}
|
|
563
|
-
else {
|
|
564
|
-
xOrigin = position.overlayX === 'start' ? 'left' : 'right';
|
|
565
|
-
}
|
|
566
|
-
for (let i = 0; i < elements.length; i++) {
|
|
567
|
-
elements[i].style.transformOrigin = `${xOrigin} ${yOrigin}`;
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
/**
|
|
571
|
-
* Gets the position and size of the overlay's sizing container.
|
|
572
|
-
*
|
|
573
|
-
* This method does no measuring and applies no styles so that we can cheaply compute the
|
|
574
|
-
* bounds for all positions and choose the best fit based on these results.
|
|
575
|
-
*/
|
|
576
|
-
_calculateBoundingBoxRect(origin, position) {
|
|
577
|
-
const viewport = this._viewportRect;
|
|
578
|
-
const isRtl = this._isRtl();
|
|
579
|
-
let height, top, bottom;
|
|
580
|
-
if (position.overlayY === 'top') {
|
|
581
|
-
// Overlay is opening "downward" and thus is bound by the bottom viewport edge.
|
|
582
|
-
top = origin.y;
|
|
583
|
-
height = viewport.height - top + this._viewportMargin;
|
|
584
|
-
}
|
|
585
|
-
else if (position.overlayY === 'bottom') {
|
|
586
|
-
// Overlay is opening "upward" and thus is bound by the top viewport edge. We need to add
|
|
587
|
-
// the viewport margin back in, because the viewport rect is narrowed down to remove the
|
|
588
|
-
// margin, whereas the `origin` position is calculated based on its `ClientRect`.
|
|
589
|
-
bottom = viewport.height - origin.y + this._viewportMargin * 2;
|
|
590
|
-
height = viewport.height - bottom + this._viewportMargin;
|
|
591
|
-
}
|
|
592
|
-
else {
|
|
593
|
-
// If neither top nor bottom, it means that the overlay is vertically centered on the
|
|
594
|
-
// origin point. Note that we want the position relative to the viewport, rather than
|
|
595
|
-
// the page, which is why we don't use something like `viewport.bottom - origin.y` and
|
|
596
|
-
// `origin.y - viewport.top`.
|
|
597
|
-
const smallestDistanceToViewportEdge = Math.min(viewport.bottom - origin.y + viewport.top, origin.y);
|
|
598
|
-
const previousHeight = this._lastBoundingBoxSize.height;
|
|
599
|
-
height = smallestDistanceToViewportEdge * 2;
|
|
600
|
-
top = origin.y - smallestDistanceToViewportEdge;
|
|
601
|
-
if (height > previousHeight && !this._isInitialRender && !this._growAfterOpen) {
|
|
602
|
-
top = origin.y - previousHeight / 2;
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
// The overlay is opening 'right-ward' (the content flows to the right).
|
|
606
|
-
const isBoundedByRightViewportEdge = (position.overlayX === 'start' && !isRtl) || (position.overlayX === 'end' && isRtl);
|
|
607
|
-
// The overlay is opening 'left-ward' (the content flows to the left).
|
|
608
|
-
const isBoundedByLeftViewportEdge = (position.overlayX === 'end' && !isRtl) || (position.overlayX === 'start' && isRtl);
|
|
609
|
-
let width, left, right;
|
|
610
|
-
if (isBoundedByLeftViewportEdge) {
|
|
611
|
-
right = viewport.width - origin.x + this._viewportMargin;
|
|
612
|
-
width = origin.x - this._viewportMargin;
|
|
613
|
-
}
|
|
614
|
-
else if (isBoundedByRightViewportEdge) {
|
|
615
|
-
left = origin.x;
|
|
616
|
-
width = viewport.right - origin.x;
|
|
617
|
-
}
|
|
618
|
-
else {
|
|
619
|
-
// If neither start nor end, it means that the overlay is horizontally centered on the
|
|
620
|
-
// origin point. Note that we want the position relative to the viewport, rather than
|
|
621
|
-
// the page, which is why we don't use something like `viewport.right - origin.x` and
|
|
622
|
-
// `origin.x - viewport.left`.
|
|
623
|
-
const smallestDistanceToViewportEdge = Math.min(viewport.right - origin.x + viewport.left, origin.x);
|
|
624
|
-
const previousWidth = this._lastBoundingBoxSize.width;
|
|
625
|
-
width = smallestDistanceToViewportEdge * 2;
|
|
626
|
-
left = origin.x - smallestDistanceToViewportEdge;
|
|
627
|
-
if (width > previousWidth && !this._isInitialRender && !this._growAfterOpen) {
|
|
628
|
-
left = origin.x - previousWidth / 2;
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
return { top: top, left: left, bottom: bottom, right: right, width, height };
|
|
632
|
-
}
|
|
633
|
-
/**
|
|
634
|
-
* Sets the position and size of the overlay's sizing wrapper. The wrapper is positioned on the
|
|
635
|
-
* origin's connection point and stretches to the bounds of the viewport.
|
|
636
|
-
*
|
|
637
|
-
* @param origin The point on the origin element where the overlay is connected.
|
|
638
|
-
* @param position The position preference
|
|
639
|
-
*/
|
|
640
|
-
_setBoundingBoxStyles(origin, position) {
|
|
641
|
-
const boundingBoxRect = this._calculateBoundingBoxRect(origin, position);
|
|
642
|
-
// It's weird if the overlay *grows* while scrolling, so we take the last size into account
|
|
643
|
-
// when applying a new size.
|
|
644
|
-
if (!this._isInitialRender && !this._growAfterOpen) {
|
|
645
|
-
boundingBoxRect.height = Math.min(boundingBoxRect.height, this._lastBoundingBoxSize.height);
|
|
646
|
-
boundingBoxRect.width = Math.min(boundingBoxRect.width, this._lastBoundingBoxSize.width);
|
|
647
|
-
}
|
|
648
|
-
const styles = {};
|
|
649
|
-
if (this._hasExactPosition()) {
|
|
650
|
-
styles.top = styles.left = '0';
|
|
651
|
-
styles.bottom = styles.right = styles.maxHeight = styles.maxWidth = '';
|
|
652
|
-
styles.width = styles.height = '100%';
|
|
653
|
-
}
|
|
654
|
-
else {
|
|
655
|
-
const maxHeight = this._overlayRef.getConfig().maxHeight;
|
|
656
|
-
const maxWidth = this._overlayRef.getConfig().maxWidth;
|
|
657
|
-
styles.height = coerceCssPixelValue(boundingBoxRect.height);
|
|
658
|
-
styles.top = coerceCssPixelValue(boundingBoxRect.top);
|
|
659
|
-
styles.bottom = coerceCssPixelValue(boundingBoxRect.bottom);
|
|
660
|
-
styles.width = coerceCssPixelValue(boundingBoxRect.width);
|
|
661
|
-
styles.left = coerceCssPixelValue(boundingBoxRect.left);
|
|
662
|
-
styles.right = coerceCssPixelValue(boundingBoxRect.right);
|
|
663
|
-
// Push the pane content towards the proper direction.
|
|
664
|
-
if (position.overlayX === 'center') {
|
|
665
|
-
styles.alignItems = 'center';
|
|
666
|
-
}
|
|
667
|
-
else {
|
|
668
|
-
styles.alignItems = position.overlayX === 'end' ? 'flex-end' : 'flex-start';
|
|
669
|
-
}
|
|
670
|
-
if (position.overlayY === 'center') {
|
|
671
|
-
styles.justifyContent = 'center';
|
|
672
|
-
}
|
|
673
|
-
else {
|
|
674
|
-
styles.justifyContent = position.overlayY === 'bottom' ? 'flex-end' : 'flex-start';
|
|
675
|
-
}
|
|
676
|
-
if (maxHeight) {
|
|
677
|
-
styles.maxHeight = coerceCssPixelValue(maxHeight);
|
|
678
|
-
}
|
|
679
|
-
if (maxWidth) {
|
|
680
|
-
styles.maxWidth = coerceCssPixelValue(maxWidth);
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
this._lastBoundingBoxSize = boundingBoxRect;
|
|
684
|
-
extendStyles(this._boundingBox.style, styles);
|
|
685
|
-
}
|
|
686
|
-
/** Resets the styles for the bounding box so that a new positioning can be computed. */
|
|
687
|
-
_resetBoundingBoxStyles() {
|
|
688
|
-
extendStyles(this._boundingBox.style, {
|
|
689
|
-
top: '0',
|
|
690
|
-
left: '0',
|
|
691
|
-
right: '0',
|
|
692
|
-
bottom: '0',
|
|
693
|
-
height: '',
|
|
694
|
-
width: '',
|
|
695
|
-
alignItems: '',
|
|
696
|
-
justifyContent: '',
|
|
697
|
-
});
|
|
698
|
-
}
|
|
699
|
-
/** Resets the styles for the overlay pane so that a new positioning can be computed. */
|
|
700
|
-
_resetOverlayElementStyles() {
|
|
701
|
-
extendStyles(this._pane.style, {
|
|
702
|
-
top: '',
|
|
703
|
-
left: '',
|
|
704
|
-
bottom: '',
|
|
705
|
-
right: '',
|
|
706
|
-
position: '',
|
|
707
|
-
transform: '',
|
|
708
|
-
});
|
|
709
|
-
}
|
|
710
|
-
/** Sets positioning styles to the overlay element. */
|
|
711
|
-
_setOverlayElementStyles(originPoint, position) {
|
|
712
|
-
const styles = {};
|
|
713
|
-
const hasExactPosition = this._hasExactPosition();
|
|
714
|
-
const hasFlexibleDimensions = this._hasFlexibleDimensions;
|
|
715
|
-
const config = this._overlayRef.getConfig();
|
|
716
|
-
if (hasExactPosition) {
|
|
717
|
-
const scrollPosition = this._viewportRuler.getViewportScrollPosition();
|
|
718
|
-
extendStyles(styles, this._getExactOverlayY(position, originPoint, scrollPosition));
|
|
719
|
-
extendStyles(styles, this._getExactOverlayX(position, originPoint, scrollPosition));
|
|
720
|
-
}
|
|
721
|
-
else {
|
|
722
|
-
styles.position = 'static';
|
|
723
|
-
}
|
|
724
|
-
// Use a transform to apply the offsets. We do this because the `center` positions rely on
|
|
725
|
-
// being in the normal flex flow and setting a `top` / `left` at all will completely throw
|
|
726
|
-
// off the position. We also can't use margins, because they won't have an effect in some
|
|
727
|
-
// cases where the element doesn't have anything to "push off of". Finally, this works
|
|
728
|
-
// better both with flexible and non-flexible positioning.
|
|
729
|
-
let transformString = '';
|
|
730
|
-
let offsetX = this._getOffset(position, 'x');
|
|
731
|
-
let offsetY = this._getOffset(position, 'y');
|
|
732
|
-
if (offsetX) {
|
|
733
|
-
transformString += `translateX(${offsetX}px) `;
|
|
734
|
-
}
|
|
735
|
-
if (offsetY) {
|
|
736
|
-
transformString += `translateY(${offsetY}px)`;
|
|
737
|
-
}
|
|
738
|
-
styles.transform = transformString.trim();
|
|
739
|
-
// If a maxWidth or maxHeight is specified on the overlay, we remove them. We do this because
|
|
740
|
-
// we need these values to both be set to "100%" for the automatic flexible sizing to work.
|
|
741
|
-
// The maxHeight and maxWidth are set on the boundingBox in order to enforce the constraint.
|
|
742
|
-
// Note that this doesn't apply when we have an exact position, in which case we do want to
|
|
743
|
-
// apply them because they'll be cleared from the bounding box.
|
|
744
|
-
if (config.maxHeight) {
|
|
745
|
-
if (hasExactPosition) {
|
|
746
|
-
styles.maxHeight = coerceCssPixelValue(config.maxHeight);
|
|
747
|
-
}
|
|
748
|
-
else if (hasFlexibleDimensions) {
|
|
749
|
-
styles.maxHeight = '';
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
if (config.maxWidth) {
|
|
753
|
-
if (hasExactPosition) {
|
|
754
|
-
styles.maxWidth = coerceCssPixelValue(config.maxWidth);
|
|
755
|
-
}
|
|
756
|
-
else if (hasFlexibleDimensions) {
|
|
757
|
-
styles.maxWidth = '';
|
|
758
|
-
}
|
|
759
|
-
}
|
|
760
|
-
extendStyles(this._pane.style, styles);
|
|
761
|
-
}
|
|
762
|
-
/** Gets the exact top/bottom for the overlay when not using flexible sizing or when pushing. */
|
|
763
|
-
_getExactOverlayY(position, originPoint, scrollPosition) {
|
|
764
|
-
// Reset any existing styles. This is necessary in case the
|
|
765
|
-
// preferred position has changed since the last `apply`.
|
|
766
|
-
let styles = { top: '', bottom: '' };
|
|
767
|
-
let overlayPoint = this._getOverlayPoint(originPoint, this._overlayRect, position);
|
|
768
|
-
if (this._isPushed) {
|
|
769
|
-
overlayPoint = this._pushOverlayOnScreen(overlayPoint, this._overlayRect, scrollPosition);
|
|
770
|
-
}
|
|
771
|
-
// We want to set either `top` or `bottom` based on whether the overlay wants to appear
|
|
772
|
-
// above or below the origin and the direction in which the element will expand.
|
|
773
|
-
if (position.overlayY === 'bottom') {
|
|
774
|
-
// When using `bottom`, we adjust the y position such that it is the distance
|
|
775
|
-
// from the bottom of the viewport rather than the top.
|
|
776
|
-
const documentHeight = this._document.documentElement.clientHeight;
|
|
777
|
-
styles.bottom = `${documentHeight - (overlayPoint.y + this._overlayRect.height)}px`;
|
|
778
|
-
}
|
|
779
|
-
else {
|
|
780
|
-
styles.top = coerceCssPixelValue(overlayPoint.y);
|
|
781
|
-
}
|
|
782
|
-
return styles;
|
|
783
|
-
}
|
|
784
|
-
/** Gets the exact left/right for the overlay when not using flexible sizing or when pushing. */
|
|
785
|
-
_getExactOverlayX(position, originPoint, scrollPosition) {
|
|
786
|
-
// Reset any existing styles. This is necessary in case the preferred position has
|
|
787
|
-
// changed since the last `apply`.
|
|
788
|
-
let styles = { left: '', right: '' };
|
|
789
|
-
let overlayPoint = this._getOverlayPoint(originPoint, this._overlayRect, position);
|
|
790
|
-
if (this._isPushed) {
|
|
791
|
-
overlayPoint = this._pushOverlayOnScreen(overlayPoint, this._overlayRect, scrollPosition);
|
|
792
|
-
}
|
|
793
|
-
// We want to set either `left` or `right` based on whether the overlay wants to appear "before"
|
|
794
|
-
// or "after" the origin, which determines the direction in which the element will expand.
|
|
795
|
-
// For the horizontal axis, the meaning of "before" and "after" change based on whether the
|
|
796
|
-
// page is in RTL or LTR.
|
|
797
|
-
let horizontalStyleProperty;
|
|
798
|
-
if (this._isRtl()) {
|
|
799
|
-
horizontalStyleProperty = position.overlayX === 'end' ? 'left' : 'right';
|
|
800
|
-
}
|
|
801
|
-
else {
|
|
802
|
-
horizontalStyleProperty = position.overlayX === 'end' ? 'right' : 'left';
|
|
803
|
-
}
|
|
804
|
-
// When we're setting `right`, we adjust the x position such that it is the distance
|
|
805
|
-
// from the right edge of the viewport rather than the left edge.
|
|
806
|
-
if (horizontalStyleProperty === 'right') {
|
|
807
|
-
const documentWidth = this._document.documentElement.clientWidth;
|
|
808
|
-
styles.right = `${documentWidth - (overlayPoint.x + this._overlayRect.width)}px`;
|
|
809
|
-
}
|
|
810
|
-
else {
|
|
811
|
-
styles.left = coerceCssPixelValue(overlayPoint.x);
|
|
812
|
-
}
|
|
813
|
-
return styles;
|
|
814
|
-
}
|
|
815
|
-
/**
|
|
816
|
-
* Gets the view properties of the trigger and overlay, including whether they are clipped
|
|
817
|
-
* or completely outside the view of any of the strategy's scrollables.
|
|
818
|
-
*/
|
|
819
|
-
_getScrollVisibility() {
|
|
820
|
-
// Note: needs fresh rects since the position could've changed.
|
|
821
|
-
const originBounds = this._getOriginRect();
|
|
822
|
-
const overlayBounds = this._pane.getBoundingClientRect();
|
|
823
|
-
// TODO(jelbourn): instead of needing all of the client rects for these scrolling containers
|
|
824
|
-
// every time, we should be able to use the scrollTop of the containers if the size of those
|
|
825
|
-
// containers hasn't changed.
|
|
826
|
-
const scrollContainerBounds = this._scrollables.map(scrollable => {
|
|
827
|
-
return scrollable.getElementRef().nativeElement.getBoundingClientRect();
|
|
828
|
-
});
|
|
829
|
-
return {
|
|
830
|
-
isOriginClipped: isElementClippedByScrolling(originBounds, scrollContainerBounds),
|
|
831
|
-
isOriginOutsideView: isElementScrolledOutsideView(originBounds, scrollContainerBounds),
|
|
832
|
-
isOverlayClipped: isElementClippedByScrolling(overlayBounds, scrollContainerBounds),
|
|
833
|
-
isOverlayOutsideView: isElementScrolledOutsideView(overlayBounds, scrollContainerBounds),
|
|
834
|
-
};
|
|
835
|
-
}
|
|
836
|
-
/** Subtracts the amount that an element is overflowing on an axis from its length. */
|
|
837
|
-
_subtractOverflows(length, ...overflows) {
|
|
838
|
-
return overflows.reduce((currentValue, currentOverflow) => {
|
|
839
|
-
return currentValue - Math.max(currentOverflow, 0);
|
|
840
|
-
}, length);
|
|
841
|
-
}
|
|
842
|
-
/** Narrows the given viewport rect by the current _viewportMargin. */
|
|
843
|
-
_getNarrowedViewportRect() {
|
|
844
|
-
// We recalculate the viewport rect here ourselves, rather than using the ViewportRuler,
|
|
845
|
-
// because we want to use the `clientWidth` and `clientHeight` as the base. The difference
|
|
846
|
-
// being that the client properties don't include the scrollbar, as opposed to `innerWidth`
|
|
847
|
-
// and `innerHeight` that do. This is necessary, because the overlay container uses
|
|
848
|
-
// 100% `width` and `height` which don't include the scrollbar either.
|
|
849
|
-
const width = this._document.documentElement.clientWidth;
|
|
850
|
-
const height = this._document.documentElement.clientHeight;
|
|
851
|
-
const scrollPosition = this._viewportRuler.getViewportScrollPosition();
|
|
852
|
-
return {
|
|
853
|
-
top: scrollPosition.top + this._viewportMargin,
|
|
854
|
-
left: scrollPosition.left + this._viewportMargin,
|
|
855
|
-
right: scrollPosition.left + width - this._viewportMargin,
|
|
856
|
-
bottom: scrollPosition.top + height - this._viewportMargin,
|
|
857
|
-
width: width - 2 * this._viewportMargin,
|
|
858
|
-
height: height - 2 * this._viewportMargin,
|
|
859
|
-
};
|
|
860
|
-
}
|
|
861
|
-
/** Whether the we're dealing with an RTL context */
|
|
862
|
-
_isRtl() {
|
|
863
|
-
return this._overlayRef.getDirection() === 'rtl';
|
|
864
|
-
}
|
|
865
|
-
/** Determines whether the overlay uses exact or flexible positioning. */
|
|
866
|
-
_hasExactPosition() {
|
|
867
|
-
return !this._hasFlexibleDimensions || this._isPushed;
|
|
868
|
-
}
|
|
869
|
-
/** Retrieves the offset of a position along the x or y axis. */
|
|
870
|
-
_getOffset(position, axis) {
|
|
871
|
-
if (axis === 'x') {
|
|
872
|
-
// We don't do something like `position['offset' + axis]` in
|
|
873
|
-
// order to avoid breaking minifiers that rename properties.
|
|
874
|
-
return position.offsetX == null ? this._offsetX : position.offsetX;
|
|
875
|
-
}
|
|
876
|
-
return position.offsetY == null ? this._offsetY : position.offsetY;
|
|
877
|
-
}
|
|
878
|
-
/** Validates that the current position match the expected values. */
|
|
879
|
-
_validatePositions() {
|
|
880
|
-
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
881
|
-
if (!this._preferredPositions.length) {
|
|
882
|
-
throw Error('FlexibleConnectedPositionStrategy: At least one position is required.');
|
|
883
|
-
}
|
|
884
|
-
// TODO(crisbeto): remove these once Angular's template type
|
|
885
|
-
// checking is advanced enough to catch these cases.
|
|
886
|
-
this._preferredPositions.forEach(pair => {
|
|
887
|
-
validateHorizontalPosition('originX', pair.originX);
|
|
888
|
-
validateVerticalPosition('originY', pair.originY);
|
|
889
|
-
validateHorizontalPosition('overlayX', pair.overlayX);
|
|
890
|
-
validateVerticalPosition('overlayY', pair.overlayY);
|
|
891
|
-
});
|
|
892
|
-
}
|
|
893
|
-
}
|
|
894
|
-
/** Adds a single CSS class or an array of classes on the overlay panel. */
|
|
895
|
-
_addPanelClasses(cssClasses) {
|
|
896
|
-
if (this._pane) {
|
|
897
|
-
coerceArray(cssClasses).forEach(cssClass => {
|
|
898
|
-
if (cssClass !== '' && this._appliedPanelClasses.indexOf(cssClass) === -1) {
|
|
899
|
-
this._appliedPanelClasses.push(cssClass);
|
|
900
|
-
this._pane.classList.add(cssClass);
|
|
901
|
-
}
|
|
902
|
-
});
|
|
903
|
-
}
|
|
904
|
-
}
|
|
905
|
-
/** Clears the classes that the position strategy has applied from the overlay panel. */
|
|
906
|
-
_clearPanelClasses() {
|
|
907
|
-
if (this._pane) {
|
|
908
|
-
this._appliedPanelClasses.forEach(cssClass => {
|
|
909
|
-
this._pane.classList.remove(cssClass);
|
|
910
|
-
});
|
|
911
|
-
this._appliedPanelClasses = [];
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
/** Returns the ClientRect of the current origin. */
|
|
915
|
-
_getOriginRect() {
|
|
916
|
-
const origin = this._origin;
|
|
917
|
-
if (origin instanceof ElementRef) {
|
|
918
|
-
return origin.nativeElement.getBoundingClientRect();
|
|
919
|
-
}
|
|
920
|
-
// Check for Element so SVG elements are also supported.
|
|
921
|
-
if (origin instanceof Element) {
|
|
922
|
-
return origin.getBoundingClientRect();
|
|
923
|
-
}
|
|
924
|
-
const width = origin.width || 0;
|
|
925
|
-
const height = origin.height || 0;
|
|
926
|
-
// If the origin is a point, return a client rect as if it was a 0x0 element at the point.
|
|
927
|
-
return {
|
|
928
|
-
top: origin.y,
|
|
929
|
-
bottom: origin.y + height,
|
|
930
|
-
left: origin.x,
|
|
931
|
-
right: origin.x + width,
|
|
932
|
-
height,
|
|
933
|
-
width,
|
|
934
|
-
};
|
|
935
|
-
}
|
|
936
|
-
}
|
|
937
|
-
/** Shallow-extends a stylesheet object with another stylesheet object. */
|
|
938
|
-
function extendStyles(destination, source) {
|
|
939
|
-
for (let key in source) {
|
|
940
|
-
if (source.hasOwnProperty(key)) {
|
|
941
|
-
destination[key] = source[key];
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
return destination;
|
|
945
|
-
}
|
|
946
|
-
/**
|
|
947
|
-
* Extracts the pixel value as a number from a value, if it's a number
|
|
948
|
-
* or a CSS pixel string (e.g. `1337px`). Otherwise returns null.
|
|
949
|
-
*/
|
|
950
|
-
function getPixelValue(input) {
|
|
951
|
-
if (typeof input !== 'number' && input != null) {
|
|
952
|
-
const [value, units] = input.split(cssUnitPattern);
|
|
953
|
-
return !units || units === 'px' ? parseFloat(value) : null;
|
|
954
|
-
}
|
|
955
|
-
return input || null;
|
|
956
|
-
}
|
|
957
|
-
/**
|
|
958
|
-
* Gets a version of an element's bounding `ClientRect` where all the values are rounded down to
|
|
959
|
-
* the nearest pixel. This allows us to account for the cases where there may be sub-pixel
|
|
960
|
-
* deviations in the `ClientRect` returned by the browser (e.g. when zoomed in with a percentage
|
|
961
|
-
* size, see #21350).
|
|
962
|
-
*/
|
|
963
|
-
function getRoundedBoundingClientRect(clientRect) {
|
|
964
|
-
return {
|
|
965
|
-
top: Math.floor(clientRect.top),
|
|
966
|
-
right: Math.floor(clientRect.right),
|
|
967
|
-
bottom: Math.floor(clientRect.bottom),
|
|
968
|
-
left: Math.floor(clientRect.left),
|
|
969
|
-
width: Math.floor(clientRect.width),
|
|
970
|
-
height: Math.floor(clientRect.height),
|
|
971
|
-
};
|
|
972
|
-
}
|
|
973
|
-
export const STANDARD_DROPDOWN_BELOW_POSITIONS = [
|
|
974
|
-
{ originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top' },
|
|
975
|
-
{ originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom' },
|
|
976
|
-
{ originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top' },
|
|
977
|
-
{ originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom' },
|
|
978
|
-
];
|
|
979
|
-
export const STANDARD_DROPDOWN_ADJACENT_POSITIONS = [
|
|
980
|
-
{ originX: 'end', originY: 'top', overlayX: 'start', overlayY: 'top' },
|
|
981
|
-
{ originX: 'end', originY: 'bottom', overlayX: 'start', overlayY: 'bottom' },
|
|
982
|
-
{ originX: 'start', originY: 'top', overlayX: 'end', overlayY: 'top' },
|
|
983
|
-
{ originX: 'start', originY: 'bottom', overlayX: 'end', overlayY: 'bottom' },
|
|
984
|
-
];
|
|
985
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmxleGlibGUtY29ubmVjdGVkLXBvc2l0aW9uLXN0cmF0ZWd5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2Nkay9vdmVybGF5L3Bvc2l0aW9uL2ZsZXhpYmxlLWNvbm5lY3RlZC1wb3NpdGlvbi1zdHJhdGVneS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFHSCxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBRXpDLE9BQU8sRUFDTCw4QkFBOEIsRUFHOUIsMEJBQTBCLEVBQzFCLHdCQUF3QixHQUN6QixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFBYSxZQUFZLEVBQUUsT0FBTyxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBRXZELE9BQU8sRUFBQyw0QkFBNEIsRUFBRSwyQkFBMkIsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUN4RixPQUFPLEVBQUMsbUJBQW1CLEVBQUUsV0FBVyxFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFJdkUscUZBQXFGO0FBQ3JGLDZGQUE2RjtBQUU3RixxREFBcUQ7QUFDckQsTUFBTSxnQkFBZ0IsR0FBRyw2Q0FBNkMsQ0FBQztBQUV2RSxxREFBcUQ7QUFDckQsTUFBTSxjQUFjLEdBQUcsZUFBZSxDQUFDO0FBY3ZDOzs7Ozs7R0FNRztBQUNILE1BQU0sT0FBTyxpQ0FBaUM7SUE2RjVDLFlBQ0UsV0FBb0QsRUFDNUMsY0FBNkIsRUFDN0IsU0FBbUIsRUFDbkIsU0FBbUIsRUFDbkIsaUJBQW1DO1FBSG5DLG1CQUFjLEdBQWQsY0FBYyxDQUFlO1FBQzdCLGNBQVMsR0FBVCxTQUFTLENBQVU7UUFDbkIsY0FBUyxHQUFULFNBQVMsQ0FBVTtRQUNuQixzQkFBaUIsR0FBakIsaUJBQWlCLENBQWtCO1FBM0Y3QywwRkFBMEY7UUFDbEYseUJBQW9CLEdBQUcsRUFBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUMs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dGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgR29vZ2xlIExMQyBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cblxuaW1wb3J0IHtQb3NpdGlvblN0cmF0ZWd5fSBmcm9tICcuL3Bvc2l0aW9uLXN0cmF0ZWd5JztcbmltcG9ydCB7RWxlbWVudFJlZn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1ZpZXdwb3J0UnVsZXIsIENka1Njcm9sbGFibGUsIFZpZXdwb3J0U2Nyb2xsUG9zaXRpb259IGZyb20gJ0Bhbmd1bGFyL2Nkay9zY3JvbGxpbmcnO1xuaW1wb3J0IHtcbiAgQ29ubmVjdGVkT3ZlcmxheVBvc2l0aW9uQ2hhbmdlLFxuICBDb25uZWN0aW9uUG9zaXRpb25QYWlyLFxuICBTY3JvbGxpbmdWaXNpYmlsaXR5LFxuICB2YWxpZGF0ZUhvcml6b250YWxQb3NpdGlvbixcbiAgdmFsaWRhdGVWZXJ0aWNhbFBvc2l0aW9uLFxufSBmcm9tICcuL2Nvbm5lY3RlZC1wb3NpdGlvbic7XG5pbXBvcnQge09ic2VydmFibGUsIFN1YnNjcmlwdGlvbiwgU3ViamVjdH0gZnJvbSAncnhqcyc7XG5pbXBvcnQge092ZXJsYXlSZWZlcmVuY2V9IGZyb20gJy4uL292ZXJsYXktcmVmZXJlbmNlJztcbmltcG9ydCB7aXNFbGVtZW50U2Nyb2xsZWRPdXRzaWRlVmlldywgaXNFbGVtZW50Q2xpcHBlZEJ5U2Nyb2xsaW5nfSBmcm9tICcuL3Njcm9sbC1jbGlwJztcbmltcG9ydCB7Y29lcmNlQ3NzUGl4ZWxWYWx1ZSwgY29lcmNlQXJyYXl9IGZyb20gJ0Bhbmd1bGFyL2Nkay9jb2VyY2lvbic7XG5pbXBvcnQge1BsYXRmb3JtfSBmcm9tICdAYW5ndWxhci9jZGsvcGxhdGZvcm0nO1xuaW1wb3J0IHtPdmVybGF5Q29udGFpbmVyfSBmcm9tICcuLi9vdmVybGF5LWNvbnRhaW5lcic7XG5cbi8vIFRPRE86IHJlZmFjdG9yIGNsaXBwaW5nIGRldGVjdGlvbiBpbnRvIGEgc2VwYXJhdGUgdGhpbmcgKHBhcnQgb2Ygc2Nyb2xsaW5nIG1vZHVsZSlcbi8vIFRPRE86IGRvZXNuJ3QgaGFuZGxlIGJvdGggZmxleGlibGUgd2lkdGggYW5kIGhlaWdodCB3aGVuIGl0IGhhcyB0byBzY3JvbGwgYWxvbmcgYm90aCBheGlzLlxuXG4vKiogQ2xhc3MgdG8gYmUgYWRkZWQgdG8gdGhlIG92ZXJsYXkgYm91bmRpbmcgYm94LiAqL1xuY29uc3QgYm91bmRpbmdCb3hDbGFzcyA9ICdjZGstb3ZlcmxheS1jb25uZWN0ZWQtcG9zaXRpb24tYm91bmRpbmctYm94JztcblxuLyoqIFJlZ2V4IHVzZWQgdG8gc3BsaXQgYSBzdHJpbmcgb24gaXRzIENTUyB1bml0cy4gKi9cbmNvbnN0IGNzc1VuaXRQYXR0ZXJuID0gLyhbQS1aYS16JV0rKSQvO1xuXG4vKiogUG9zc2libGUgdmFsdWVzIHRoYXQgY2FuIGJlIHNldCBhcyB0aGUgb3JpZ2luIG9mIGEgRmxleGlibGVDb25uZWN0ZWRQb3NpdGlvblN0cmF0ZWd5LiAqL1xuZXhwb3J0IHR5cGUgRmxleGlibGVDb25uZWN0ZWRQb3NpdGlvblN0cmF0ZWd5T3JpZ2luID1cbiAgfCBFbGVtZW50UmVmXG4gIHwgRWxlbWVudFxuICB8IChQb2ludCAmIHtcbiAgICAgIHdpZHRoPzogbnVtYmVyO1xuICAgICAgaGVpZ2h0PzogbnVtYmVyO1xuICAgIH0pO1xuXG4vKiogRXF1aXZhbGVudCBvZiBgQ2xpZW50UmVjdGAgd2l0aG91dCBzb21lIG9mIHRoZSBwcm9wZXJ0aWVzIHdlIGRvbid0IGNhcmUgYWJvdXQuICovXG50eXBlIERpbWVuc2lvbnMgPSBPbWl0PENsaWVudFJlY3QsICd4JyB8ICd5JyB8ICd0b0pTT04nPjtcblxuLyoqXG4gKiBBIHN0cmF0ZWd5IGZvciBwb3NpdGlvbmluZyBvdmVybGF5cy4gVXNpbmcgdGhpcyBzdHJhdGVneSwgYW4gb3ZlcmxheSBpcyBnaXZlbiBhblxuICogaW1wbGljaXQgcG9zaXRpb24gcmVsYXRpdmUgc29tZSBvcmlnaW4gZWxlbWVudC4gVGhlIHJlbGF0aXZlIHBvc2l0aW9uIGlzIGRlZmluZWQgaW4gdGVybXMgb2ZcbiAqIGEgcG9pbnQgb24gdGhlIG9yaWdpbiBlbGVtZW50IHRoYXQgaXMgY29ubmVjdGVkIHRvIGEgcG9pbnQgb24gdGhlIG92ZXJsYXkgZWxlbWVudC4gRm9yIGV4YW1wbGUsXG4gKiBhIGJhc2ljIGRyb3Bkb3duIGlzIGNvbm5lY3RpbmcgdGhlIGJvdHRvbS1sZWZ0IGNvcm5lciBvZiB0aGUgb3JpZ2luIHRvIHRoZSB0b3AtbGVmdCBjb3JuZXJcbiAqIG9mIHRoZSBvdmVybGF5LlxuICovXG5leHBvcnQgY2xhc3MgRmxleGlibGVDb25uZWN0ZWRQb3NpdGlvblN0cmF0ZWd5IGltcGxlbWVudHMgUG9zaXRpb25TdHJhdGVneSB7XG4gIC8qKiBUaGUgb3ZlcmxheSB0byB3aGljaCB0aGlzIHN0cmF0ZWd5IGlzIGF0dGFjaGVkLiAqL1xuICBwcml2YXRlIF9vdmVybGF5UmVmOiBPdmVybGF5UmVmZXJlbmNlO1xuXG4gIC8qKiBXaGV0aGVyIHdlJ3JlIHBlcmZvcm1pbmcgdGhlIHZlcnkgZmlyc3QgcG9zaXRpb25pbmcgb2YgdGhlIG92ZXJsYXkuICovXG4gIHByaXZhdGUgX2lzSW5pdGlhbFJlbmRlcjogYm9vbGVhbjtcblxuICAvKiogTGFzdCBzaXplIHVzZWQgZm9yIHRoZSBib3VuZGluZyBib3guIFVzZWQgdG8gYXZvaWQgcmVzaXppbmcgdGhlIG92ZXJsYXkgYWZ0ZXIgb3Blbi4gKi9cbiAgcHJpdmF0ZSBfbGFzdEJvdW5kaW5nQm94U2l6ZSA9IHt3aWR0aDogMCwgaGVpZ2h0OiAwfTtcblxuICAvKiogV2hldGhlciB0aGUgb3ZlcmxheSB3YXMgcHVzaGVkIGluIGEgcHJldmlvdXMgcG9zaXRpb25pbmcuICovXG4gIHByaXZhdGUgX2lzUHVzaGVkID0gZmFsc2U7XG5cbiAgLyoqIFdoZXRoZXIgdGhlIG92ZXJsYXkgY2FuIGJlIHB1c2hlZCBvbi1zY3JlZW4gb24gdGhlIGluaXRpYWwgb3Blbi4gKi9cbiAgcHJpdmF0ZSBfY2FuUHVzaCA9IHRydWU7XG5cbiAgLyoqIFdoZXRoZXIgdGhlIG92ZXJsYXkgY2FuIGdyb3cgdmlhIGZsZXhpYmxlIHdpZHRoL2hlaWdodCBhZnRlciB0aGUgaW5pdGlhbCBvcGVuLiAqL1xuICBwcml2YXRlIF9ncm93QWZ0ZXJPcGVuID0gZmFsc2U7XG5cbiAgLyoqIFdoZXRoZXIgdGhlIG92ZXJsYXkncyB3aWR0aCBhbmQgaGVpZ2h0IGNhbiBiZSBjb25zdHJhaW5lZCB0byBmaXQgd2l0aGluIHRoZSB2aWV3cG9ydC4gKi9cbiAgcHJpdmF0ZSBfaGFzRmxleGlibGVEaW1lbnNpb25zID0gdHJ1ZTtcblxuICAvKiogV2hldGhlciB0aGUgb3ZlcmxheSBwb3NpdGlvbiBpcyBsb2NrZWQuICovXG4gIHByaXZhdGUgX3Bvc2l0aW9uTG9ja2VkID0gZmFsc2U7XG5cbiAgLyoqIENhY2hlZCBvcmlnaW4gZGltZW5zaW9ucyAqL1xuICBwcml2YXRlIF9vcmlnaW5SZWN0OiBEaW1lbnNpb25zO1xuXG4gIC8qKiBDYWNoZWQgb3ZlcmxheSBkaW1lbnNpb25zICovXG4gIHByaXZhdGUgX292ZXJsYXlSZWN0OiBEaW1lbnNpb25zO1xuXG4gIC8qKiBDYWNoZWQgdmlld3BvcnQgZGltZW5zaW9ucyAqL1xuICBwcml2YXRlIF92aWV3cG9ydFJlY3Q6IERpbWVuc2lvbnM7XG5cbiAgLyoqIENhY2hlZCBjb250YWluZXIgZGltZW5zaW9ucyAqL1xuICBwcml2YXRlIF9jb250YWluZXJSZWN0OiBEaW1lbnNpb25zO1xuXG4gIC8qKiBBbW91bnQgb2Ygc3BhY2UgdGhhdCBtdXN0IGJlIG1haW50YWluZWQgYmV0d2VlbiB0aGUgb3ZlcmxheSBhbmQgdGhlIGVkZ2Ugb2YgdGhlIHZpZXdwb3J0LiAqL1xuICBwcml2YXRlIF92aWV3cG9ydE1hcmdpbiA9IDA7XG5cbiAgLyoqIFRoZSBTY3JvbGxhYmxlIGNvbnRhaW5lcnMgdXNlZCB0byBjaGVjayBzY3JvbGxhYmxlIHZpZXcgcHJvcGVydGllcyBvbiBwb3NpdGlvbiBjaGFuZ2UuICovXG4gIHByaXZhdGUgX3Njcm9sbGFibGVzOiBDZGtTY3JvbGxhYmxlW10gPSBbXTtcblxuICAvKiogT3JkZXJlZCBsaXN0IG9mIHByZWZlcnJlZCBwb3NpdGlvbnMsIGZyb20gbW9zdCB0byBsZWFzdCBkZXNpcmFibGUuICovXG4gIF9wcmVmZXJyZWRQb3NpdGlvbnM6IENvbm5lY3Rpb25Qb3NpdGlvblBhaXJbXSA9IFtdO1xuXG4gIC8qKiBUaGUgb3JpZ2luIGVsZW1lbnQgYWdhaW5zdCB3aGljaCB0aGUgb3ZlcmxheSB3aWxsIGJlIHBvc2l0aW9uZWQuICovXG4gIHByaXZhdGUgX29yaWdpbjogRmxleGlibGVDb25uZWN0ZWRQb3NpdGlvblN0cmF0ZWd5T3JpZ2luO1xuXG4gIC8qKiBUaGUgb3ZlcmxheSBwYW5lIGVsZW1lbnQuICovXG4gIHByaXZhdGUgX3BhbmU6IEhUTUxFbGVtZW50O1xuXG4gIC8qKiBXaGV0aGVyIHRoZSBzdHJhdGVneSBoYXMgYmVlbiBkaXNwb3NlZCBvZiBhbHJlYWR5LiAqL1xuICBwcml2YXRlIF9pc0Rpc3Bvc2VkOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBQYXJlbnQgZWxlbWVudCBmb3IgdGhlIG92ZXJsYXkgcGFuZWwgdXNlZCB0byBjb25zdHJhaW4gdGhlIG92ZXJsYXkgcGFuZWwncyBzaXplIHRvIGZpdFxuICAgKiB3aXRoaW4gdGhlIHZpZXdwb3J0LlxuICAgKi9cbiAgcHJpdmF0ZSBfYm91bmRpbmdCb3g6IEhUTUxFbGVtZW50IHwgbnVsbDtcblxuICAvKiogVGhlIGxhc3QgcG9zaXRpb24gdG8gaGF2ZSBiZWVuIGNhbGN1bGF0ZWQgYXMgdGhlIGJlc3QgZml0IHBvc2l0aW9uLiAqL1xuICBwcml2YXRlIF9sYXN0UG9zaXRpb246IENvbm5lY3RlZFBvc2l0aW9uIHwgbnVsbDtcblxuICAvKiogU3ViamVjdCB0aGF0IGVtaXRzIHdoZW5ldmVyIHRoZSBwb3NpdGlvbiBjaGFuZ2VzLiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IF9wb3NpdGlvbkNoYW5nZXMgPSBuZXcgU3ViamVjdDxDb25uZWN0ZWRPdmVybGF5UG9zaXRpb25DaGFuZ2U+KCk7XG5cbiAgLyoqIFN1YnNjcmlwdGlvbiB0byB2aWV3cG9ydCBzaXplIGNoYW5nZXMuICovXG4gIHByaXZhdGUgX3Jlc2l6ZVN1YnNjcmlwdGlvbiA9IFN1YnNjcmlwdGlvbi5FTVBUWTtcblxuICAvKiogRGVmYXVsdCBvZmZzZXQgZm9yIHRoZSBvdmVybGF5IGFsb25nIHRoZSB4IGF4aXMuICovXG4gIHByaXZhdGUgX29mZnNldFggPSAwO1xuXG4gIC8qKiBEZWZhdWx0IG9mZnNldCBmb3IgdGhlIG92ZXJsYXkgYWxvbmcgdGhlIHkgYXhpcy4gKi9cbiAgcHJpdmF0ZSBfb2Zmc2V0WSA9IDA7XG5cbiAgLyoqIFNlbGVjdG9yIHRvIGJlIHVzZWQgd2hlbiBmaW5kaW5nIHRoZSBlbGVtZW50cyBvbiB3aGljaCB0byBzZXQgdGhlIHRyYW5zZm9ybSBvcmlnaW4uICovXG4gIHByaXZhdGUgX3RyYW5zZm9ybU9yaWdpblNlbGVjdG9yOiBzdHJpbmc7XG5cbiAgLyoqIEtlZXBzIHRyYWNrIG9mIHRoZSBDU1MgY2xhc3NlcyB0aGF0IHRoZSBwb3NpdGlvbiBzdHJhdGVneSBoYXMgYXBwbGllZCBvbiB0aGUgb3ZlcmxheSBwYW5lbC4gKi9cbiAgcHJpdmF0ZSBfYXBwbGllZFBhbmVsQ2xhc3Nlczogc3RyaW5nW10gPSBbXTtcblxuICAvKiogQW1vdW50IGJ5IHdoaWNoIHRoZSBvdmVybGF5IHdhcyBwdXNoZWQgaW4gZWFjaCBheGlzIGR1cmluZyB0aGUgbGFzdCB0aW1lIGl0IHdhcyBwb3NpdGlvbmVkLiAqL1xuICBwcml2YXRlIF9wcmV2aW91c1B1c2hBbW91bnQ6IHt4OiBudW1iZXI7IHk6IG51bWJlcn0gfCBudWxsO1xuXG4gIC8qKiBPYnNlcnZhYmxlIHNlcXVlbmNlIG9mIHBvc2l0aW9uIGNoYW5nZXMuICovXG4gIHBvc2l0aW9uQ2hhbmdlczogT2JzZXJ2YWJsZTxDb25uZWN0ZWRPdmVybGF5UG9zaXRpb25DaGFuZ2U+ID0gdGhpcy5fcG9zaXRpb25DaGFuZ2VzO1xuXG4gIC8qKiBPcmRlcmVkIGxpc3Qgb2YgcHJlZmVycmVkIHBvc2l0aW9ucywgZnJvbSBtb3N0IHRvIGxlYXN0IGRlc2lyYWJsZS4gKi9cbiAgZ2V0IHBvc2l0aW9ucygpOiBDb25uZWN0aW9uUG9zaXRpb25QYWlyW10ge1xuICAgIHJldHVybiB0aGlzLl9wcmVmZXJyZWRQb3NpdGlvbnM7XG4gIH1cblxuICBjb25zdHJ1Y3RvcihcbiAgICBjb25uZWN0ZWRUbzogRmxleGlibGVDb25uZWN0ZWRQb3NpdGlvblN0cmF0ZWd5T3JpZ2luLFxuICAgIHByaXZhdGUgX3ZpZXdwb3J0UnVsZXI6IFZpZXdwb3J0UnVsZXIsXG4gICAgcHJpdmF0ZSBfZG9jdW1lbnQ6IERvY3VtZW50LFxuICAgIHByaXZhdGUgX3BsYXRmb3JtOiBQbGF0Zm9ybSxcbiAgICBwcml2YXRlIF9vdmVybGF5Q29udGFpbmVyOiBPdmVybGF5Q29udGFpbmVyLFxuICApIHtcbiAgICB0aGlzLnNldE9yaWdpbihjb25uZWN0ZWRUbyk7XG4gIH1cblxuICAvKiogQXR0YWNoZXMgdGhpcyBwb3NpdGlvbiBzdHJhdGVneSB0byBhbiBvdmVybGF5LiAqL1xuICBhdHRhY2gob3ZlcmxheVJlZjogT3ZlcmxheVJlZmVyZW5jZSk6IHZvaWQge1xuICAgIGlmIChcbiAgICAgIHRoaXMuX292ZXJsYXlSZWYgJiZcbiAgICAgIG92ZXJsYXlSZWYgIT09IHRoaXMuX292ZXJsYXlSZWYgJiZcbiAgICAgICh0eXBlb2YgbmdEZXZNb2RlID09PSAndW5kZWZpbmVkJyB8fCBuZ0Rldk1vZGUpXG4gICAgKSB7XG4gICAgICB0aHJvdyBFcnJvcignVGhpcyBwb3NpdGlvbiBzdHJhdGVneSBpcyBhbHJlYWR5IGF0dGFjaGVkIHRvIGFuIG92ZXJsYXknKTtcbiAgICB9XG5cbiAgICB0aGlzLl92YWxpZGF0ZVBvc2l0aW9ucygpO1xuXG4gICAgb3ZlcmxheVJlZi5ob3N0RWxlbWVudC5jbGFzc0xpc3QuYWRkKGJvdW5kaW5nQm94Q2xhc3MpO1xuXG4gICAgdGhpcy5fb3ZlcmxheVJlZiA9IG92ZXJsYXlSZWY7XG4gICAgdGhpcy5fYm91bmRpbmdCb3ggPSBvdmVybGF5UmVmLmhvc3RFbGVtZW50O1xuICAgIHRoaXMuX3BhbmUgPSBvdmVybGF5UmVmLm92ZXJsYXlFbGVtZW50O1xuICAgIHRoaXMuX2lzRGlzcG9zZWQgPSBmYWxzZTtcbiAgICB0aGlzLl9pc0luaXRpYWxSZW5kZXIgPSB0cnVlO1xuICAgIHRoaXMuX2xhc3RQb3NpdGlvbiA9IG51bGw7XG4gICAgdGhpcy5fcmVzaXplU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5fcmVzaXplU3Vic2NyaXB0aW9uID0gdGhpcy5fdmlld3BvcnRSdWxlci5jaGFuZ2UoKS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgLy8gV2hlbiB0aGUgd2luZG93IGlzIHJlc2l6ZWQsIHdlIHdhbnQgdG8gdHJpZ2dlciB0aGUgbmV4dCByZXBvc2l0aW9uIGFzIGlmIGl0XG4gICAgICAvLyB3YXMgYW4gaW5pdGlhbCByZW5kZXIsIGluIG9yZGVyIGZvciB0aGUgc3RyYXRlZ3kgdG8gcGljayBhIG5ldyBvcHRpbWFsIHBvc2l0aW9uLFxuICAgICAgLy8gb3RoZXJ3aXNlIHBvc2l0aW9uIGxvY2tpbmcgd2lsbCBjYXVzZSBpdCB0byBzdGF5IGF0IHRoZSBvbGQgb25lLlxuICAgICAgdGhpcy5faXNJbml0aWFsUmVuZGVyID0gdHJ1ZTtcbiAgICAgIHRoaXMuYXBwbHkoKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGVzIHRoZSBwb3NpdGlvbiBvZiB0aGUgb3ZlcmxheSBlbGVtZW50LCB1c2luZyB3aGljaGV2ZXIgcHJlZmVycmVkIHBvc2l0aW9uIHJlbGF0aXZlXG4gICAqIHRvIHRoZSBvcmlnaW4gYmVzdCBmaXRzIG9uLXNjcmVlbi5cbiAgICpcbiAgICogVGhlIHNlbGVjdGlvbiBvZiBhIHBvc2l0aW9uIGdvZXMgYXMgZm9sbG93czpcbiAgICogIC0gSWYgYW55IHBvc2l0aW9ucyBmaXQgY29tcGxldGVseSB3aXRoaW4gdGhlIHZpZXdwb3J0IGFzLWlzLFxuICAgKiAgICAgIGNob29zZSB0aGUgZmlyc3QgcG9zaXRpb24gdGhhdCBkb2VzIHNvLlxuICAgKiAgLSBJZiBmbGV4aWJsZSBkaW1lbnNpb25zIGFyZSBlbmFibGVkIGFuZCBhdCBsZWFzdCBvbmUgc2F0aXNmaWVzIHRoZSBnaXZlbiBtaW5pbXVtIHdpZHRoL2hlaWdodCxcbiAgICogICAgICBjaG9vc2UgdGhlIHBvc2l0aW9uIHdpdGggdGhlIGdyZWF0ZXN0IGF2YWlsYWJsZSBzaXplIG1vZGlmaWVkIGJ5IHRoZSBwb3NpdGlvbnMnIHdlaWdodC5cbiAgICogIC0gSWYgcHVzaGluZyBpcyBlbmFibGVkLCB0YWtlIHRoZSBwb3NpdGlvbiB0aGF0IHdlbnQgb2ZmLXNjcmVlbiB0aGUgbGVhc3QgYW5kIHB1c2ggaXRcbiAgICogICAgICBvbi1zY3JlZW4uXG4gICAqICAtIElmIG5vbmUgb2YgdGhlIHByZXZpb3VzIGNyaXRlcmlhIHdlcmUgbWV0LCB1c2UgdGhlIHBvc2l0aW9uIHRoYXQgZ29lcyBvZmYtc2NyZWVuIHRoZSBsZWFzdC5cbiAgICogQGRvY3MtcHJpdmF0ZVxuICAgKi9cbiAgYXBwbHkoKTogdm9pZCB7XG4gICAgLy8gV2Ugc2hvdWxkbid0IGRvIGFueXRoaW5nIGlmIHRoZSBzdHJhdGVneSB3YXMgZGlzcG9zZWQgb3Igd2UncmUgb24gdGhlIHNlcnZlci5cbiAgICBpZiAodGhpcy5faXNEaXNwb3NlZCB8fCAhdGhpcy5fcGxhdGZvcm0uaXNCcm93c2VyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gSWYgdGhlIHBvc2l0aW9uIGhhcyBiZWVuIGFwcGxpZWQgYWxyZWFkeSAoZS5nLiB3aGVuIHRoZSBvdmVybGF5IHdhcyBvcGVuZWQpIGFuZCB0aGVcbiAgICAvLyBjb25zdW1lciBvcHRlZCBpbnRvIGxvY2tpbmcgaW4gdGhlIHBvc2l0aW9uLCByZS11c2UgdGhlIG9sZCBwb3NpdGlvbiwgaW4gb3JkZXIgdG9cbiAgICAvLyBwcmV2ZW50IHRoZSBvdmVybGF5IGZyb20ganVtcGluZyBhcm91bmQuXG4gICAgaWYgKCF0aGlzLl9pc0luaXRpYWxSZW5kZXIgJiYgdGhpcy5fcG9zaXRpb25Mb2NrZWQgJiYgdGhpcy5fbGFzdFBvc2l0aW9uKSB7XG4gICAgICB0aGlzLnJlYXBwbHlMYXN0UG9zaXRpb24oKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9jbGVhclBhbmVsQ2xhc3NlcygpO1xuICAgIHRoaXMuX3Jlc2V0T3ZlcmxheUVsZW1lbnRTdHlsZXMoKTtcbiAgICB0aGlzLl9yZXNldEJvdW5kaW5nQm94U3R5bGVzKCk7XG5cbiAgICAvLyBXZSBuZWVkIHRoZSBib3VuZGluZyByZWN0cyBmb3IgdGhlIG9yaWdpbiwgdGhlIG92ZXJsYXkgYW5kIHRoZSBjb250YWluZXIgdG8gZGV0ZXJtaW5lIGhvdyB0byBwb3NpdGlvblxuICAgIC8vIHRoZSBvdmVybGF5IHJlbGF0aXZlIHRvIHRoZSBvcmlnaW4uXG4gICAgLy8gV2UgdXNlIHRoZSB2aWV3cG9ydCByZWN0IHRvIGRldGVybWluZSB3aGV0aGVyIGEgcG9zaXRpb24gd291bGQgZ28gb2ZmLXNjcmVlbi5cbiAgICB0aGlzLl92aWV3cG9ydFJlY3QgPSB0aGlzLl9nZXROYXJyb3dlZFZpZXdwb3J0UmVjdCgpO1xuICAgIHRoaXMuX29yaWdpblJlY3QgPSB0aGlzLl9nZXRPcmlnaW5SZWN0KCk7XG4gICAgdGhpcy5fb3ZlcmxheVJlY3QgPSB0aGlzLl9wYW5lLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIHRoaXMuX2NvbnRhaW5lclJlY3QgPSB0aGlzLl9vdmVybGF5Q29udGFpbmVyLmdldENvbnRhaW5lckVsZW1lbnQoKS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgIGNvbnN0IG9yaWdpblJlY3QgPSB0aGlzLl9vcmlnaW5SZWN0O1xuICAgIGNvbnN0IG92ZXJsYXlSZWN0ID0gdGhpcy5fb3ZlcmxheVJlY3Q7XG4gICAgY29uc3Qgdmlld3BvcnRSZWN0ID0gdGhpcy5fdmlld3BvcnRSZWN0O1xuICAgIGNvbnN0IGNvbnRhaW5lclJlY3QgPSB0aGlzLl9jb250YWluZXJSZWN0O1xuXG4gICAgLy8gUG9zaXRpb25zIHdoZXJlIHRoZSBvdmVybGF5IHdpbGwgZml0IHdpdGggZmxleGlibGUgZGltZW5zaW9ucy5cbiAgICBjb25zdCBmbGV4aWJsZUZpdHM6IEZsZXhpYmxlRml0W10gPSBbXTtcblxuICAgIC8vIEZhbGxiYWNrIGlmIG5vbmUgb2YgdGhlIHByZWZlcnJlZCBwb3NpdGlvbnMgZml0IHdpdGhpbiB0aGUgdmlld3BvcnQuXG4gICAgbGV0IGZhbGxiYWNrOiBGYWxsYmFja1Bvc2l0aW9uIHwgdW5kZWZpbmVkO1xuXG4gICAgLy8gR28gdGhyb3VnaCBlYWNoIG9mIHRoZSBwcmVmZXJyZWQgcG9zaXRpb25zIGxvb2tpbmcgZm9yIGEgZ29vZCBmaXQuXG4gICAgLy8gSWYgYSBnb29kIGZpdCBpcyBmb3VuZCwgaXQgd2lsbCBiZSBhcHBsaWVkIGltbWVkaWF0ZWx5LlxuICAgIGZvciAobGV0IHBvcyBvZiB0aGlzLl9wcmVmZXJyZWRQb3NpdGlvbnMpIHtcbiAgICAgIC8vIEdldCB0aGUgZXhhY3QgKHgsIHkpIGNvb3JkaW5hdGUgZm9yIHRoZSBwb2ludC1vZi1vcmlnaW4gb24gdGhlIG9yaWdpbiBlbGVtZW50LlxuICAgICAgbGV0IG9yaWdpblBvaW50ID0gdGhpcy5fZ2V0T3JpZ2luUG9pbnQob3JpZ2luUmVjdCwgY29udGFpbmVyUmVjdCwgcG9zKTtcblxuICAgICAgLy8gRnJvbSB0aGF0IHBvaW50LW9mLW9yaWdpbiwgZ2V0IHRoZSBleGFjdCAoeCwgeSkgY29vcmRpbmF0ZSBmb3IgdGhlIHRvcC1sZWZ0IGNvcm5lciBvZiB0aGVcbiAgICAgIC8vIG92ZXJsYXkgaW4gdGhpcyBwb3NpdGlvbi4gV2UgdXNlIHRoZSB0b3AtbGVmdCBjb3JuZXIgZm9yIGNhbGN1bGF0aW9ucyBhbmQgbGF0ZXIgdHJhbnNsYXRlXG4gICAgICAvLyB0aGlzIGludG8gYW4gYXBwcm9wcmlhdGUgKHRvcCwgbGVmdCwgYm90dG9tLCByaWdodCkgc3R5bGUuXG4gICAgICBsZXQgb3ZlcmxheVBvaW50ID0gdGhpcy5fZ2V0T3ZlcmxheVBvaW50KG9yaWdpblBvaW50LCBvdmVybGF5UmVjdCwgcG9zKTtcblxuICAgICAgLy8gQ2FsY3VsYXRlIGhvdyB3ZWxsIHRoZSBvdmVybGF5IHdvdWxkIGZpdCBpbnRvIHRoZSB2aWV3cG9ydCB3aXRoIHRoaXMgcG9pbnQuXG4gICAgICBsZXQgb3ZlcmxheUZpdCA9IHRoaXMuX2dldE92ZXJsYXlGaXQob3ZlcmxheVBvaW50LCBvdmVybGF5UmVjdCwgdmlld3BvcnRSZWN0LCBwb3MpO1xuXG4gICAgICAvLyBJZiB0aGUgb3ZlcmxheSwgd2l0aG91dCBhbnkgZnVydGhlciB3b3JrLCBmaXRzIGludG8gdGhlIHZpZXdwb3J0LCB1c2UgdGhpcyBwb3NpdGlvbi5cbiAgICAgIGlmIChvdmVybGF5Rml0LmlzQ29tcGxldGVseVdpdGhpblZpZXdwb3J0KSB7XG4gICAgICAgIHRoaXMuX2lzUHVzaGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuX2FwcGx5UG9zaXRpb24ocG9zLCBvcmlnaW5Qb2ludCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgLy8gSWYgdGhlIG92ZXJsYXkgaGFzIGZsZXhpYmxlIGRpbWVuc2lvbnMsIHdlIGNhbiB1c2UgdGhpcyBwb3NpdGlvblxuICAgICAgLy8gc28gbG9uZyBhcyB0aGVyZSdzIGVub3VnaCBzcGFjZSBmb3IgdGhlIG1pbmltdW0gZGltZW5zaW9ucy5cbiAgICAgIGlmICh0aGlzLl9jYW5GaXRXaXRoRmxleGlibGVEaW1lbnNpb25zKG92ZXJsYXlGaXQsIG92ZXJsYXlQb2ludCwgdmlld3BvcnRSZWN0KSkge1xuICAgICAgICAvLyBTYXZlIHBvc2l0aW9ucyB3aGVyZSB0aGUgb3ZlcmxheSB3aWxsIGZpdCB3aXRoIGZsZXhpYmxlIGRpbWVuc2lvbnMuIFdlIHdpbGwgdXNlIHRoZXNlXG4gICAgICAgIC8vIGlmIG5vbmUgb2YgdGhlIHBvc2l0aW9ucyBmaXQgKndpdGhvdXQqIGZsZXhpYmxlIGRpbWVuc2lvbnMuXG4gICAgICAgIGZsZXhpYmxlRml0cy5wdXNoKHtcbiAgICAgICAgICBwb3NpdGlvbjogcG9zLFxuICAgICAgICAgIG9yaWdpbjogb3JpZ2luUG9pbnQsXG4gICAgICAgICAgb3ZlcmxheVJlY3QsXG4gICAgICAgICAgYm91bmRpbmdCb3hSZWN0OiB0aGlzLl9jYWxjdWxhdGVCb3VuZGluZ0JveFJlY3Qob3JpZ2luUG9pbnQsIHBvcyksXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBJZiB0aGUgY3VycmVudCBwcmVmZXJyZWQgcG9zaXRpb24gZG9lcyBub3QgZml0IG9uIHRoZSBzY3JlZW4sIHJlbWVtYmVyIHRoZSBwb3NpdGlvblxuICAgICAgLy8gaWYgaXQgaGFzIG1vcmUgdmlzaWJsZSBhcmVhIG9uLXNjcmVlbiB0aGFuIHdlJ3ZlIHNlZW4gYW5kIG1vdmUgb250byB0aGUgbmV4dCBwcmVmZXJyZWRcbiAgICAgIC8vIHBvc2l0aW9uLlxuICAgICAgaWYgKCFmYWxsYmFjayB8fCBmYWxsYmFjay5vdmVybGF5Rml0LnZpc2libGVBcmVhIDwgb3ZlcmxheUZpdC52aXNpYmxlQXJlYSkge1xuICAgICAgICBmYWxsYmFjayA9IHtvdmVybGF5Rml0LCBvdmVybGF5UG9pbnQsIG9yaWdpblBvaW50LCBwb3NpdGlvbjogcG9zLCBvdmVybGF5UmVjdH07XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gSWYgdGhlcmUgYXJlIGFueSBwb3NpdGlvbnMgd2hlcmUgdGhlIG92ZXJsYXkgd291bGQgZml0IHdpdGggZmxleGlibGUgZGltZW5zaW9ucywgY2hvb3NlIHRoZVxuICAgIC8vIG9uZSB0aGF0IGhhcyB0aGUgZ3JlYXRlc3QgYXJlYSBhdmFpbGFibGUgbW9kaWZpZWQgYnkgdGhlIHBvc2l0aW9uJ3Mgd2VpZ2h0XG4gICAgaWYgKGZsZXhpYmxlRml0cy5sZW5ndGgpIHtcbiAgICAgIGxldCBiZXN0Rml0OiBGbGV4aWJsZUZpdCB8IG51bGwgPSBudWxsO1xuICAgICAgbGV0IGJlc3RTY29yZSA9IC0xO1xuICAgICAgZm9yIChjb25zdCBmaXQgb2YgZmxleGlibGVGaXRzKSB7XG4gICAgICAgIGNvbnN0IHNjb3JlID1cbiAgICAgICAgICBmaXQuYm91bmRpbmdCb3hSZWN0LndpZHRoICogZml0LmJvdW5kaW5nQm94UmVjdC5oZWlnaHQgKiAoZml0LnBvc2l0aW9uLndlaWdodCB8fCAxKTtcbiAgICAgICAgaWYgKHNjb3JlID4gYmVzdFNjb3JlKSB7XG4gICAgICAgICAgYmVzdFNjb3JlID0gc2NvcmU7XG4gICAgICAgICAgYmVzdEZpdCA9IGZpdDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB0aGlzLl9pc1B1c2hlZCA9IGZhbHNlO1xuICAgICAgdGhpcy5fYXBwbHlQb3NpdGlvbihiZXN0Rml0IS5wb3NpdGlvbiwgYmVzdEZpdCEub3JpZ2luKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBXaGVuIG5vbmUgb2YgdGhlIHByZWZlcnJlZCBwb3NpdGlvbnMgZml0IHdpdGhpbiB0aGUgdmlld3BvcnQsIHRha2UgdGhlIHBvc2l0aW9uXG4gICAgLy8gdGhhdCB3ZW50IG9mZi1zY3JlZW4gdGhlIGxlYXN0IGFuZCBhdHRlbXB0IHRvIHB1c2ggaXQgb24tc2NyZWVuLlxuICAgIGlmICh0aGlzLl9jYW5QdXNoKSB7XG4gICAgICAvLyBUT0RPKGplbGJvdXJuKTogYWZ0ZXIgcHVzaGluZywgdGhlIG9wZW5pbmcgXCJkaXJlY3Rpb25cIiBvZiB0aGUgb3ZlcmxheSBtaWdodCBub3QgbWFrZSBzZW5zZS5cbiAgICAgIHRoaXMuX2lzUHVzaGVkID0gdHJ1ZTtcbiAgICAgIHRoaXMuX2FwcGx5UG9zaXRpb24oZmFsbGJhY2shLnBvc2l0aW9uLCBmYWxsYmFjayEub3JpZ2luUG9pbnQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIEFsbCBvcHRpb25zIGZvciBnZXR0aW5nIHRoZSBvdmVybGF5IHdpdGhpbiB0aGUgdmlld3BvcnQgaGF2ZSBiZWVuIGV4aGF1c3RlZCwgc28gZ28gd2l0aCB0aGVcbiAgICAvLyBwb3NpdGlvbiB0aGF0IHdlbnQgb2ZmLXNjcmVlbiB0aGUgbGVhc3QuXG4gICAgdGhpcy5fYXBwbHlQb3NpdGlvbihmYWxsYmFjayEucG9zaXRpb24sIGZhbGxiYWNrIS5vcmlnaW5Qb2ludCk7XG4gIH1cblxuICBkZXRhY2goKTogdm9pZCB7XG4gICAgdGhpcy5fY2xlYXJQYW5lbENsYXNzZXMoKTtcbiAgICB0aGlzLl9sYXN0UG9zaXRpb24gPSBudWxsO1xuICAgIHRoaXMuX3ByZXZpb3VzUHVzaEFtb3VudCA9IG51bGw7XG4gICAgdGhpcy5fcmVzaXplU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gIH1cblxuICAvKiogQ2xlYW51cCBhZnRlciB0aGUgZWxlbWVudCBnZXRzIGRlc3Ryb3llZC4gKi9cbiAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5faXNEaXNwb3NlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFdlIGNhbid0IHVzZSBgX3Jlc2V0Qm91bmRpbmdCb3hTdHlsZXNgIGhlcmUsIGJlY2F1c2UgaXQgcmVzZXRzXG4gICAgLy8gc29tZSBwcm9wZXJ0aWVzIHRvIHplcm8sIHJhdGhlciB0aGFuIHJlbW92aW5nIHRoZW0uXG4gICAgaWYgKHRoaXMuX2JvdW5kaW5nQm94KSB7XG4gICAgICBleHRlbmRTdHlsZXModGhpcy5fYm91bmRpbmdCb3guc3R5bGUsIHtcbiAgICAgICAgdG9wOiAnJyxcbiAgICAgICAgbGVmdDogJycsXG4gICAgICAgIHJpZ2h0OiAnJyxcbiAgICAgICAgYm90dG9tOiAnJyxcbiAgICAgICAgaGVpZ2h0OiAnJyxcbiAgICAgICAgd2lkdGg6ICcnLFxuICAgICAgICBhbGlnbkl0ZW1zOiAnJyxcbiAgICAgICAganVzdGlmeUNvbnRlbnQ6ICcnLFxuICAgICAgfSBhcyBDU1NTdHlsZURlY2xhcmF0aW9uKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fcGFuZSkge1xuICAgICAgdGhpcy5fcmVzZXRPdmVybGF5RWxlbWVudFN0eWxlcygpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9vdmVybGF5UmVmKSB7XG4gICAgICB0aGlzLl9vdmVybGF5UmVmLmhvc3RFbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoYm91bmRpbmdCb3hDbGFzcyk7XG4gICAgfVxuXG4gICAgdGhpcy5kZXRhY2goKTtcbiAgICB0aGlzLl9wb3NpdGlvbkNoYW5nZXMuY29tcGxldGUoKTtcbiAgICB0aGlzLl9vdmVybGF5UmVmID0gdGhpcy5fYm91bmRpbmdCb3ggPSBudWxsITtcbiAgICB0aGlzLl9pc0Rpc3Bvc2VkID0gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIHJlLWFsaWducyB0aGUgb3ZlcmxheSBlbGVtZW50IHdpdGggdGhlIHRyaWdnZXIgaW4gaXRzIGxhc3QgY2FsY3VsYXRlZCBwb3NpdGlvbixcbiAgICogZXZlbiBpZiBhIHBvc2l0aW9uIGhpZ2hlciBpbiB0aGUgXCJwcmVmZXJyZWQgcG9zaXRpb25zXCIgbGlzdCB3b3VsZCBub3cgZml0LiBUaGlzXG4gICAqIGFsbG93cyBvbmUgdG8gcmUtYWxpZ24gdGhlIHBhbmVsIHdpdGhvdXQgY2hhbmdpbmcgdGhlIG9yaWVudGF0aW9uIG9mIHRoZSBwYW5lbC5cbiAgICovXG4gIHJlYXBwbHlMYXN0UG9zaXRpb24oKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuX2lzRGlzcG9zZWQgfHwgIXRoaXMuX3BsYXRmb3JtLmlzQnJvd3Nlcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGxhc3RQb3NpdGlvbiA9IHRoaXMuX2xhc3RQb3NpdGlvbjtcblxuICAgIGlmIChsYXN0UG9zaXRpb24pIHtcbiAgICAgIHRoaXMuX29yaWdpblJlY3QgPSB0aGlzLl9nZXRPcmlnaW5SZWN0KCk7XG4gICAgICB0aGlzLl9vdmVybGF5UmVjdCA9IHRoaXMuX3BhbmUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICB0aGlzLl92aWV3cG9ydFJlY3QgPSB0aGlzLl9nZXROYXJyb3dlZFZpZXdwb3J0UmVjdCgpO1xuICAgICAgdGhpcy5fY29udGFpbmVyUmVjdCA9IHRoaXMuX292ZXJsYXlDb250YWluZXIuZ2V0Q29udGFpbmVyRWxlbWVudCgpLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG4gICAgICBjb25zdCBvcmlnaW5Qb2ludCA9IHRoaXMuX2dldE9yaWdpblBvaW50KHRoaXMuX29yaWdpblJlY3QsIHRoaXMuX2NvbnRhaW5lclJlY3QsIGxhc3RQb3NpdGlvbik7XG4gICAgICB0aGlzLl9hcHBseVBvc2l0aW9uKGxhc3RQb3NpdGlvbiwgb3JpZ2luUG9pbnQpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFwcGx5KCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIGxpc3Qgb2YgU2Nyb2xsYWJsZSBjb250YWluZXJzIHRoYXQgaG9zdCB0aGUgb3JpZ2luIGVsZW1lbnQgc28gdGhhdFxuICAgKiBvbiByZXBvc2l0aW9uIHdlIGNhbiBldmFsdWF0ZSBpZiBpdCBvciB0aGUgb3ZlcmxheSBoYXMgYmVlbiBjbGlwcGVkIG9yIG91dHNpZGUgdmlldy4gRXZlcnlcbiAgICogU2Nyb2xsYWJsZSBtdXN0IGJlIGFuIGFuY2VzdG9yIGVsZW1lbnQgb2YgdGhlIHN0cmF0ZWd5J3Mgb3JpZ2luIGVsZW1lbnQuXG4gICAqL1xuICB3aXRoU2Nyb2xsYWJsZUNvbnRhaW5lcnMoc2Nyb2xsYWJsZXM6IENka1Njcm9sbGFibGVbXSk6IHRoaXMge1xuICAgIHRoaXMuX3Njcm9sbGFibGVzID0gc2Nyb2xsYWJsZXM7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBuZXcgcHJlZmVycmVkIHBvc2l0aW9ucy5cbiAgICogQHBhcmFtIHBvc2l0aW9ucyBMaXN0IG9mIHBvc2l0aW9ucyBvcHRpb25zIGZvciB0aGlzIG92ZXJsYXkuXG4gICAqL1xuICB3aXRoUG9zaXRpb25zKHBvc2l0aW9uczogQ29ubmVjdGVkUG9zaXRpb25bXSk6IHRoaXMge1xuICAgIHRoaXMuX3ByZWZlcnJlZFBvc2l0aW9ucyA9IHBvc2l0aW9ucztcblxuICAgIC8vIElmIHRoZSBsYXN0IGNhbGN1bGF0ZWQgcG9zaXRpb24gb2JqZWN0IGlzbid0IHBhcnQgb2YgdGhlIHBvc2l0aW9ucyBhbnltb3JlLCBjbGVhclxuICAgIC8vIGl0IGluIG9yZGVyIHRvIGF2b2lkIGl0IGJlaW5nIHBpY2tlZCB1cCBpZiB0aGUgY29uc3VtZXIgdHJpZXMgdG8gcmUtYXBwbHkuXG4gICAgaWYgKHBvc2l0aW9ucy5pbmRleE9mKHRoaXMuX2xhc3RQb3NpdGlvbiEpID09PSAtMSkge1xuICAgICAgdGhpcy5fbGFzdFBvc2l0aW9uID0gbnVsbDtcbiAgICB9XG5cbiAgICB0aGlzLl92YWxpZGF0ZVBvc2l0aW9ucygpO1xuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBhIG1pbmltdW0gZGlzdGFuY2UgdGhlIG92ZXJsYXkgbWF5IGJlIHBvc2l0aW9uZWQgdG8gdGhlIGVkZ2Ugb2YgdGhlIHZpZXdwb3J0LlxuICAgKiBAcGFyYW0gbWFyZ2luIFJlcXVpcmVkIG1hcmdpbiBiZXR3ZWVuIHRoZSBvdmVybGF5IGFuZCB0aGUgdmlld3BvcnQgZWRnZSBpbiBwaXhlbHMuXG4gICAqL1xuICB3aXRoVmlld3BvcnRNYXJnaW4obWFyZ2luOiBudW1iZXIpOiB0aGlzIHtcbiAgICB0aGlzLl92aWV3cG9ydE1hcmdpbiA9IG1hcmdpbjtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKiBTZXRzIHdoZXRoZXIgdGhlIG92ZXJsYXkncyB3aWR0aCBhbmQgaGVpZ2h0IGNhbiBiZSBjb25zdHJhaW5lZCB0byBmaXQgd2l0aGluIHRoZSB2aWV3cG9ydC4gKi9cbiAgd2l0aEZsZXhpYmxlRGltZW5zaW9ucyhmbGV4aWJsZURpbWVuc2lvbnMgPSB0cnVlKTogdGhpcyB7XG4gICAgdGhpcy5faGFzRmxleGlibGVEaW1lbnNpb25zID0gZmxleGlibGVEaW1lbnNpb25zO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqIFNldHMgd2hldGhlciB0aGUgb3ZlcmxheSBjYW4gZ3JvdyBhZnRlciB0aGUgaW5pdGlhbCBvcGVuIHZpYSBmbGV4aWJsZSB3aWR0aC9oZWlnaHQuICovXG4gIHdpdGhHcm93QWZ0ZXJPcGVuKGdyb3dBZnRlck9wZW4gPSB0cnVlKTogdGhpcyB7XG4gICAgdGhpcy5fZ3Jvd0FmdGVyT3BlbiA9IGdyb3dBZnRlck9wZW47XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKiogU2V0cyB3aGV0aGVyIHRoZSBvdmVybGF5IGNhbiBiZSBwdXNoZWQgb24tc2NyZWVuIGlmIG5vbmUgb2YgdGhlIHByb3ZpZGVkIHBvc2l0aW9ucyBmaXQuICovXG4gIHdpdGhQdXNoKGNhblB1c2ggPSB0cnVlKTogdGhpcyB7XG4gICAgdGhpcy5fY2FuUHVzaCA9IGNhblB1c2g7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB3aGV0aGVyIHRoZSBvdmVybGF5J3MgcG9zaXRpb24gc2hvdWxkIGJlIGxvY2tlZCBpbiBhZnRlciBpdCBpcyBwb3NpdGlvbmVkXG4gICAqIGluaXRpYWxseS4gV2hlbiBhbiBvdmVybGF5IGlzIGxvY2tlZCBpbiwgaXQgd29uJ3QgYXR0ZW1wdCB0byByZXBvc2l0aW9uIGl0c2VsZlxuICAgKiB3aGVuIHRoZSBwb3NpdGlvbiBpcyByZS1hcHBsaWVkIChlLmcuIHdoZW4gdGhlIHVzZXIgc2Nyb2xscyBhd2F5KS5cbiAgICogQHBhcmFtIGlzTG9ja2VkIFdoZXRoZXIgdGhlIG92ZXJsYXkgc2hvdWxkIGxvY2tlZCBpbi5cbiAgICovXG4gIHdpdGhMb2NrZWRQb3NpdGlvbihpc0xvY2tlZCA9IHRydWUpOiB0aGlzIHtcbiAgICB0aGlzLl9wb3NpdGlvbkxvY2tlZCA9IGlzTG9ja2VkO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIG9yaWdpbiwgcmVsYXRpdmUgdG8gd2hpY2ggdG8gcG9zaXRpb24gdGhlIG92ZXJsYXkuXG4gICAqIFVzaW5nIGFuIGVsZW1lbnQgb3JpZ2luIGlzIHVzZWZ1bCBmb3IgYnVpbGRpbmcgY29tcG9uZW50cyB0aGF0IG5lZWQgdG8gYmUgcG9zaXRpb25lZFxuICAgKiByZWxhdGl2ZWx5IHRvIGEgdHJpZ2dlciAoZS5nLiBkcm9wZG93biBtZW51cyBvciB0b29sdGlwcyksIHdoZXJlYXMgdXNpbmcgYSBwb2ludCBjYW4gYmVcbiAgICogdXNlZCBmb3IgY2FzZXMgbGlrZSBjb250ZXh0dWFsIG1lbnVzIHdoaWNoIG9wZW4gcmVsYXRpdmUgdG8gdGhlIHVzZXIncyBwb2ludGVyLlxuICAgKiBAcGFyYW0gb3JpZ2luIFJlZmVyZW5jZSB0byB0aGUgbmV3IG9yaWdpbi5cbiAgICovXG4gIHNldE9yaWdpbihvcmlnaW46IEZsZXhpYmxlQ29ubmVjdGVkUG9zaXRpb25TdHJhdGVneU9yaWdpbik6IHRoaXMge1xuICAgIHRoaXMuX29yaWdpbiA9IG9yaWdpbjtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBkZWZhdWx0IG9mZnNldCBmb3IgdGhlIG92ZXJsYXkncyBjb25uZWN0aW9uIHBvaW50IG9uIHRoZSB4LWF4aXMuXG4gICAqIEBwYXJhbSBvZmZzZXQgTmV3IG9mZnNldCBpbiB0aGUgWCBheGlzLlxuICAgKi9cbiAgd2l0aERlZmF1bHRPZmZzZXRYKG9mZnNldDogbnVtYmVyKTogdGhpcyB7XG4gICAgdGhpcy5fb2Zmc2V0WCA9IG9mZnNldDtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBkZWZhdWx0IG9mZnNldCBmb3IgdGhlIG92ZXJsYXkncyBjb25uZWN0aW9uIHBvaW50IG9uIHRoZSB5LWF4aXMuXG4gICAqIEBwYXJhbSBvZmZzZXQgTmV3IG9mZnNldCBpbiB0aGUgWSBheGlzLlxuICAgKi9cbiAgd2l0aERlZmF1bHRPZmZzZXRZKG9mZnNldDogbnVtYmVyKTogdGhpcyB7XG4gICAgdGhpcy5fb2Zmc2V0WSA9IG9mZnNldDtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBDb25maWd1cmVzIHRoYXQgdGhlIHBvc2l0aW9uIHN0cmF0ZWd5IHNob3VsZCBzZXQgYSBgdHJhbnNmb3JtLW9yaWdpbmAgb24gc29tZSBlbGVtZW50c1xuICAgKiBpbnNpZGUgdGhlIG92ZXJsYXksIGRlcGVuZGluZyBvbiB0aGUgY3VycmVudCBwb3NpdGlvbiB0aGF0IGlzIGJlaW5nIGFwcGxpZWQuIFRoaXMgaXNcbiAgICogdXNlZnVsIGZvciB0aGUgY2FzZXMgd2hlcmUgdGhlIG9yaWdpbiBvZiBhbiBhbmltYXRpb24gY2FuIGNoYW5nZSBkZXBlbmRpbmcgb24gdGhlXG4gICAqIGFsaWdubWVudCBvZiB0aGUgb3ZlcmxheS5cbiAgICogQHBhcmFtIHNlbGVjdG9yIENTUyBzZWxlY3RvciB0aGF0IHdpbGwgYmUgdXNlZCB0byBmaW5kIHRoZSB0YXJnZXRcbiAgICogICAgZWxlbWVudHMgb250byB3aGljaCB0byBzZXQgdGhlIHRyYW5zZm9ybSBvcmlnaW4uXG4gICAqL1xuICB3aXRoVHJhbnNmb3JtT3JpZ2luT24oc2VsZWN0b3I6IHN0cmluZyk6IHRoaXMge1xuICAgIHRoaXMuX3RyYW5zZm9ybU9yaWdpblNlbGVjdG9yID0gc2VsZWN0b3I7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgKHgsIHkpIGNvb3JkaW5hdGUgb2YgYSBjb25uZWN0aW9uIHBvaW50IG9uIHRoZSBvcmlnaW4gYmFzZWQgb24gYSByZWxhdGl2ZSBwb3NpdGlvbi5cbiAgICovXG4gIHByaXZhdGUgX2dldE9yaWdpblBvaW50KFxuICAgIG9yaWdpblJlY3Q6IERpbWVuc2lvbnMsXG4gICAgY29udGFpbmVyUmVjdDogRGltZW5zaW9ucyxcbiAgICBwb3M6IENvbm5lY3RlZFBvc2l0aW9uLFxuICApOiBQb2ludCB7XG4gICAgbGV0IHg6IG51bWJlcjtcbiAgICBpZiAocG9zLm9yaWdpblggPT0gJ2NlbnRlcicpIHtcbiAgICAgIC8vIE5vdGU6IHdoZW4gY2VudGVyaW5nIHdlIHNob3VsZCBhbHdheXMgdXNlIHRoZSBgbGVmdGBcbiAgICAgIC8vIG9mZnNldCwgb3RoZXJ3aXNlIHRoZSBwb3NpdGlvbiB3aWxsIGJlIHdyb25nIGluIFJUTC5cbiAgICAgIHggPSBvcmlnaW5SZWN0LmxlZnQgKyBvcmlnaW5SZWN0LndpZHRoIC8gMjtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3Qgc3RhcnRYID0gdGhpcy5faXNSdGwoKSA/IG9yaWdpblJlY3QucmlnaHQgOiBvcmlnaW5SZWN0LmxlZnQ7XG4gICAgICBjb25zdCBlbmRYID0gdGhpcy5faXNSdGwoKSA/IG9yaWdpblJlY3QubGVmdCA6IG9yaWdpblJlY3QucmlnaHQ7XG4gICAgICB4ID0gcG9zLm9yaWdpblggPT0gJ3N0YXJ0JyA/IHN0YXJ0WCA6IGVuZFg7XG4gICAgfVxuXG4gICAgLy8gV2hlbiB6b29taW5nIGluIFNhZmFyaSB0aGUgY29udGFpbmVyIHJlY3RhbmdsZSBjb250YWlucyBuZWdhdGl2ZSB2YWx1ZXMgZm9yIHRoZSBwb3NpdGlvblxuICAgIC8vIGFuZCB3ZSBuZWVkIHRvIHJlLWFkZCB0aGVtIHRvIHRoZSBjYWxjdWxhdGVkIGNvb3JkaW5hdGVzLlxuICAgIGlmIChjb250YWluZXJSZWN0LmxlZnQgPCAwKSB7XG4gICAgICB4IC09IGNvbnRhaW5lclJlY3QubGVmdDtcbiAgICB9XG5cbiAgICBsZXQgeTogbnVtYmVyO1xuICAgIGlmIChwb3Mub3JpZ2luWSA9PSAnY2VudGVyJykge1xuICAgICAgeSA9IG9yaWdpblJlY3QudG9wICsgb3JpZ2luUmVjdC5oZWlnaHQgLyAyO1xuICAgIH0gZWxzZSB7XG4gICAgICB5ID0gcG9zLm9yaWdpblkgPT0gJ3RvcCcgPyBvcmlnaW5SZWN0LnRvcCA6IG9yaWdpblJlY3QuYm90dG9tO1xuICAgIH1cblxuICAgIC8vIE5vcm1hbGx5IHRoZSBjb250YWluZXJSZWN0J3MgdG9wIHZhbHVlIHdvdWxkIGJlIHplcm8sIGhvd2V2ZXIgd2hlbiB0aGUgb3ZlcmxheSBpcyBhdHRhY2hlZCB0byBhbiBpbnB1dFxuICAgIC8vIChlLmcuIGluIGFuIGF1dG9jb21wbGV0ZSksIG1vYmlsZSBicm93c2VycyB3aWxsIHNoaWZ0IGV2ZXJ5dGhpbmcgaW4gb3JkZXIgdG8gcHV0IHRoZSBpbnB1dCBpbiB0aGUgbWlkZGxlXG4gICAgLy8gb2YgdGhlIHNjcmVlbiBhbmQgdG8gbWFrZSBzcGFjZSBmb3IgdGhlIHZpcnR1YWwga2V5Ym9hcmQuIFdlIG5lZWQgdG8gYWNjb3VudCBmb3IgdGhpcyBvZmZzZXQsXG4gICAgLy8gb3RoZXJ3aXNlIG91ciBwb3NpdGlvbmluZyB3aWxsIGJlIHRocm93biBvZmYuXG4gICAgLy8gQWRkaXRpb25hbGx5LCB3aGVuIHpvb21pbmcgaW4gU2FmYXJpIHRoaXMgZml4ZXMgdGhlIHZlcnRpY2FsIHBvc2l0aW9uLlxuICAgIGlmIChjb250YWluZXJSZWN0LnRvcCA8IDApIHtcbiAgICAgIHkgLT0gY29udGFpbmVyUmVjdC50b3A7XG4gICAgfVxuXG4gICAgcmV0dXJuIHt4LCB5fTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSAoeCwgeSkgY29vcmRpbmF0ZSBvZiB0aGUgdG9wLWxlZnQgY29ybmVyIG9mIHRoZSBvdmVybGF5IGdpdmVuIGEgZ2l2ZW4gcG9zaXRpb24gYW5kXG4gICAqIG9yaWdpbiBwb2ludCB0byB3aGljaCB0aGUgb3ZlcmxheSBzaG91bGQgYmUgY29ubmVjdGVkLlxuICAgKi9cbiAgcHJpdmF0ZSBfZ2V0T3ZlcmxheVBvaW50KFxuICAgIG9yaWdpblBvaW50OiBQb2ludCxcbiAgICBvdmVybGF5UmVjdDogRGltZW5zaW9ucyxcbiAgICBwb3M6IENvbm5lY3RlZFBvc2l0aW9uLFxuICApOiBQb2ludCB7XG4gICAgLy8gQ2FsY3VsYXRlIHRoZSAob3ZlcmxheVN0YXJ0WCwgb3ZlcmxheVN0YXJ0WSksIHRoZSBzdGFydCBvZiB0aGVcbiAgICAvLyBwb3RlbnRpYWwgb3ZlcmxheSBwb3NpdGlvbiByZWxhdGl2ZSB0byB0aGUgb3JpZ2luIHBvaW50LlxuICAgIGxldCBvdmVybGF5U3RhcnRYOiBudW1iZXI7XG4gICAgaWYgKHBvcy5vdmVybGF5WCA9PSAnY2VudGVyJykge1xuICAgICAgb3ZlcmxheVN0YXJ0WCA9IC1vdmVybGF5UmVjdC53aWR0aCAvIDI7XG4gICAgfSBlbHNlIGlmIChwb3Mub3ZlcmxheVggPT09ICdzdGFydCcpIHtcbiAgICAgIG92ZXJsYXlTdGFydFggPSB0aGlzLl9pc1J0bCgpID8gLW92ZXJsYXlSZWN0LndpZHRoIDogMDtcbiAgICB9IGVsc2Uge1xuICAgICAgb3ZlcmxheVN0YXJ0WCA9IHRoaXMuX2lzUnRsKCkgPyAwIDogLW92ZXJsYXlSZWN0LndpZHRoO1xuICAgIH1cblxuICAgIGxldCBvdmVybGF5U3RhcnRZOiBudW1iZXI7XG4gICAgaWYgKHBvcy5vdmVybGF5WSA9PSAnY2VudGVyJykge1xuICAgICAgb3ZlcmxheVN0YXJ0WSA9IC1vdmVybGF5UmVjdC5oZWlnaHQgLyAyO1xuICAgIH0gZWxzZSB7XG4gICAgICBvdmVybGF5U3RhcnRZID0gcG9zLm92ZXJsYXlZID09ICd0b3AnID8gMCA6IC1vdmVybGF5UmVjdC5oZWlnaHQ7XG4gICAgfVxuXG4gICAgLy8gVGhlICh4LCB5KSBjb29yZGluYXRlcyBvZiB0aGUgb3ZlcmxheS5cbiAgICByZXR1cm4ge1xuICAgICAgeDogb3JpZ2luUG9pbnQueCArIG92ZXJsYXlTdGFydFgsXG4gICAgICB5OiBvcmlnaW5Qb2ludC55ICsgb3ZlcmxheVN0YXJ0WSxcbiAgICB9O1xuICB9XG5cbiAgLyoqIEdldHMgaG93IHdlbGwgYW4gb3ZlcmxheSBhdCB0aGUgZ2l2ZW4gcG9pbnQgd2lsbCBmaXQgd2l0aGluIHRoZSB2aWV3cG9ydC4gKi9cbiAgcHJpdmF0ZSBfZ2V0T3ZlcmxheUZpdChcbiAgICBwb2ludDogUG9pbnQsXG4gICAgcmF3T3ZlcmxheVJlY3Q6IERpbWVuc2lvbnMsXG4gICAgdmlld3BvcnQ6IERpbWVuc2lvbnMsXG4gICAgcG9zaXRpb246IENvbm5lY3RlZFBvc2l0aW9uLFxuICApOiBPdmVybGF5Rml0IHtcbiAgICAvLyBSb3VuZCB0aGUgb3ZlcmxheSByZWN0IHdoZW4gY29tcGFyaW5nIGFnYWluc3QgdGhlXG4gICAgLy8gdmlld3BvcnQsIGJlY2F1c2UgdGhlIHZpZXdwb3J0IGlzIGFsd2F5cyByb3VuZGVkLlxuICAgIGNvbnN0IG92ZXJsYXkgPSBnZXRSb3VuZGVkQm91bmRpbmdDbGllbnRSZWN0KHJhd092ZXJsYXlSZWN0KTtcbiAgICBsZXQge3gsIHl9ID0gcG9pbnQ7XG4gICAgbGV0IG9mZnNldFggPSB0aGlzLl9nZXRPZmZzZXQocG9zaXRpb24sICd4Jyk7XG4gICAgbGV0IG9mZnNldFkgPSB0aGlzLl9nZXRPZmZzZXQocG9zaXRpb24sICd5Jyk7XG5cbiAgICAvLyBBY2NvdW50IGZvciB0aGUgb2Zmc2V0cyBzaW5jZSB0aGV5IGNvdWxkIHB1c2ggdGhlIG92ZXJsYXkgb3V0IG9mIHRoZSB2aWV3cG9ydC5cbiAgICBpZiAob2Zmc2V0WCkge1xuICAgICAgeCArPSBvZmZzZXRYO1xuICAgIH1cblxuICAgIGlmIChvZmZzZXRZKSB7XG4gICAgICB5ICs9IG9mZnNldFk7XG4gICAgfVxuXG4gICAgLy8gSG93IG11Y2ggdGhlIG92ZXJsYXkgd291bGQgb3ZlcmZsb3cgYXQgdGhpcyBwb3NpdGlvbiwgb24gZWFjaCBzaWRlLlxuICAgIGxldCBsZWZ0T3ZlcmZsb3cgPSAwIC0geDtcbiAgICBsZXQgcmlnaHRPdmVyZmxvdyA9IHggKyBvdmVybGF5LndpZHRoIC0gdmlld3BvcnQud2lkdGg7XG4gICAgbGV0IHRvcE92ZXJmbG93ID0gMCAtIHk7XG4gICAgbGV0IGJvdHRvbU92ZXJmbG93ID0geSArIG92ZXJsYXkuaGVpZ2h0IC0gdmlld3BvcnQuaGVpZ2h0O1xuXG4gICAgLy8gVmlzaWJsZSBwYXJ0cyBvZiB0aGUgZWxlbWVudCBvbiBlYWNoIGF4aXMuXG4gICAgbGV0IHZpc2libGVXaWR0aCA9IHRoaXMuX3N1YnRyYWN0T3ZlcmZsb3dzKG92ZXJsYXkud2lkdGgsIGxlZnRPdmVyZmxvdywgcmlnaHRPdmVyZmxvdyk7XG4gICAgbGV0IHZpc2libGVIZWlnaHQgPSB0aGlzLl9zdWJ0cmFjdE92ZXJmbG93cyhvdmVybGF5LmhlaWdodCwgdG9wT3ZlcmZsb3csIGJvdHRvbU92ZXJmbG93KTtcbiAgICBsZXQgdmlzaWJsZUFyZWEgPSB2aXNpYmxlV2lkdGggKiB2aXNpYmxlSGVpZ2h0O1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHZpc2libGVBcmVhLFxuICAgICAgaXNDb21wbGV0ZWx5V2l0aGluVmlld3BvcnQ6IG92ZXJsYXkud2lkdGggKiBvdmVybGF5LmhlaWdodCA9PT0gdmlzaWJsZUFyZWEsXG4gICAgICBmaXRzSW5WaWV3cG9ydFZlcnRpY2FsbHk6IHZpc2libGVIZWlnaHQgPT09IG92ZXJsYXkuaGVpZ2h0LFxuICAgICAgZml0c0luVmlld3BvcnRIb3Jpem9udGFsbHk6IHZpc2libGVXaWR0aCA9PSBvdmVybGF5LndpZHRoLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogV2hldGhlciB0aGUgb3ZlcmxheSBjYW4gZml0IHdpdGhpbiB0aGUgdmlld3BvcnQgd2hlbiBpdCBtYXkgcmVzaXplIGVpdGhlciBpdHMgd2lkdGggb3IgaGVpZ2h0LlxuICAgKiBAcGFyYW0gZml0IEhvdyB3ZWxsIHRoZSBvdmVybGF5IGZpdHMgaW4gdGhlIHZpZXdwb3J0IGF0IHNvbWUgcG9zaXRpb24uXG4gICAqIEBwYXJhbSBwb2ludCBUaGUgKHgsIHkpIGNvb3JkaW5hdGVzIG9mIHRoZSBvdmVybGF5IGF0IHNvbWUgcG9zaXRpb24uXG4gICAqIEBwYXJhbSB2aWV3cG9ydCBUaGUgZ2VvbWV0cnkgb2YgdGhlIHZpZXdwb3J0LlxuICAgKi9cbiAgcHJpdmF0ZSBfY2FuRml0V2l0aEZsZXhpYmxlRGltZW5zaW9ucyhmaXQ6IE92ZXJsYXlGaXQsIHBvaW50OiBQb2ludCwgdmlld3BvcnQ6IERpbWVuc2lvbnMpIHtcbiAgICBpZiAodGhpcy5faGFzRmxleGlibGVEaW1lbnNpb25zKSB7XG4gICAgICBjb25zdCBhdmFpbGFibGVIZWlnaHQgPSB2aWV3cG9ydC5ib3R0b20gLSBwb2ludC55O1xuICAgICAgY29uc3QgYXZhaWxhYmxlV2lkdGggPSB2aWV3cG9ydC5yaWdodCAtIHBvaW50Lng7XG4gICAgICBjb25zdCBtaW5IZWlnaHQgPSBnZXRQaXhlbFZhbHVlKHRoaXMuX292ZXJsYXlSZWYuZ2V0Q29uZmlnKCkubWluSGVpZ2h0KTtcbiAgICAgIGNvbnN0IG1pbldpZHRoID0gZ2V0UGl4ZWxWYWx1ZSh0aGlzLl9vdmVybGF5UmVmLmdldENvbmZpZygpLm1pbldpZHRoKTtcblxuICAgICAgY29uc3QgdmVydGljYWxGaXQgPVxuICAgICAgICBmaXQuZml0c0luVmlld3BvcnRWZXJ0aWNhbGx5IHx8IChtaW5IZWlnaHQgIT0gbnVsbCAmJiBtaW5IZWlnaHQgPD0gYXZhaWxhYmxlSGVpZ2h0KTtcbiAgICAgIGNvbnN0IGhvcml6b250YWxGaXQgPVxuICAgICAgICBmaXQuZml0c0luVmlld3BvcnRIb3Jpem9udGFsbHkgfHwgKG1pbldpZHRoICE9IG51bGwgJiYgbWluV2lkdGggPD0gYXZhaWxhYmxlV2lkdGgpO1xuXG4gICAgICByZXR1cm4gdmVydGljYWxGaXQgJiYgaG9yaXpvbnRhbEZpdDtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIHBvaW50IGF0IHdoaWNoIHRoZSBvdmVybGF5IGNhbiBiZSBcInB1c2hlZFwiIG9uLXNjcmVlbi4gSWYgdGhlIG92ZXJsYXkgaXMgbGFyZ2VyIHRoYW5cbiAgICogdGhlIHZpZXdwb3J0LCB0aGUgdG9wLWxlZnQgY29ybmVyIHdpbGwgYmUgcHVzaGVkIG9uLXNjcmVlbiAod2l0aCBvdmVyZmxvdyBvY2N1cnJpbmcgb24gdGhlXG4gICAqIHJpZ2h0IGFuZCBib3R0b20pLlxuICAgKlxuICAgKiBAcGFyYW0gc3RhcnQgU3RhcnRpbmcgcG9pbnQgZnJvbSB3aGljaCB0aGUgb3ZlcmxheSBpcyBwdXNoZWQuXG4gICAqIEBwYXJhbSByYXdPdmVybGF5UmVjdCBEaW1lbnNpb25zIG9mIHRoZSBvdmVybGF5LlxuICAgKiBAcGFyYW0gc2Nyb2xsUG9zaXRpb24gQ3VycmVudCB2aWV3cG9ydCBzY3JvbGwgcG9zaXRpb24uXG4gICAqIEByZXR1cm5zIFRoZSBwb2ludCBhdCB3aGljaCB0byBwb3NpdGlvbiB0aGUgb3ZlcmxheSBhZnRlciBwdXNoaW5nLiBUaGlzIGlzIGVmZmVjdGl2ZWx5IGEgbmV3XG4gICAqICAgICBvcmlnaW5Qb2ludC5cbiAgICovXG4gIHByaXZhdGUgX3B1c2hPdmVybGF5T25TY3JlZW4oXG4gICAgc3RhcnQ6IFBvaW50LFxuICAgIHJhd092ZXJsYXlSZWN0OiBEaW1lbnNpb25zLFxuICAgIHNjcm9sbFBvc2l0aW9uOiBWaWV3cG9ydFNjcm9sbFBvc2l0aW9uLFxuICApOiBQb2ludCB7XG4gICAgLy8gSWYgdGhlIHBvc2l0aW9uIGlzIGxvY2tlZCBhbmQgd2UndmUgcHVzaGVkIHRoZSBvdmVybGF5IGFscmVhZHksIHJldXNlIHRoZSBwcmV2aW91cyBwdXNoXG4gICAgLy8gYW1vdW50LCByYXRoZXIgdGhhbiBwdXNoaW5nIGl0IGFnYWluLiBJZiB3ZSB3ZXJlIHRvIGNvbnRpbnVlIHB1c2hpbmcsIHRoZSBlbGVtZW50IHdvdWxkXG4gICAgLy8gcmVtYWluIGluIHRoZSB2aWV3cG9ydCwgd2hpY2ggZ29lcyBhZ2FpbnN0IHRoZSBleHBlY3RhdGlvbnMgd2hlbiBwb3NpdGlvbiBsb2NraW5nIGlzIGVuYWJsZWQuXG4gICAgaWYgKHRoaXMuX3ByZXZpb3VzUHVzaEFtb3VudCAmJiB0aGlzLl9wb3NpdGlvbkxvY2tlZCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgeDogc3RhcnQueCArIHRoaXMuX3ByZXZpb3VzUHVzaEFtb3VudC54LFxuICAgICAgICB5OiBzdGFydC55ICsgdGhpcy5fcHJldmlvdXNQdXNoQW1vdW50LnksXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIFJvdW5kIHRoZSBvdmVybGF5IHJlY3Qgd2hlbiBjb21wYXJpbmcgYWdhaW5zdCB0aGVcbiAgICAvLyB2aWV3cG9ydCwgYmVjYXVzZSB0aGUgdmlld3BvcnQgaXMgYWx3YXlzIHJvdW5kZWQuXG4gICAgY29uc3Qgb3ZlcmxheSA9IGdldFJvdW5kZWRCb3VuZGluZ0NsaWVudFJlY3QocmF3T3ZlcmxheVJlY3QpO1xuICAgIGNvbnN0IHZpZXdwb3J0ID0gdGhpcy5fdmlld3BvcnRSZWN0O1xuXG4gICAgLy8gRGV0ZXJtaW5lIGhvdyBtdWNoIHRoZSBvdmVybGF5IGdvZXMgb3V0c2lkZSB0aGUgdmlld3BvcnQgb24gZWFjaFxuICAgIC8vIHNpZGUsIHdoaWNoIHdlJ2xsIHVzZSB0byBkZWNpZGUgd2hpY2ggZGlyZWN0aW9uIHRvIHB1c2ggaXQuXG4gICAgY29uc3Qgb3ZlcmZsb3dSaWdodCA9IE1hdGgubWF4KHN0YXJ0LnggKyBvdmVybGF5LndpZHRoIC0gdmlld3BvcnQud2lkdGgsIDApO1xuICAgIGNvbnN0IG92ZXJmbG93Qm90dG9tID0gTWF0aC5tYXgoc3RhcnQueSArIG92ZXJsYXkuaGVpZ2h0IC0gdmlld3BvcnQuaGVpZ2h0LCAwKTtcbiAgICBjb25zdCBvdmVyZmxvd1RvcCA9IE1hdGgubWF4KHZpZXdwb3J0LnRvcCAtIHNjcm9sbFBvc2l0aW9uLnRvcCAtIHN0YXJ0LnksIDApO1xuICAgIGNvbnN0IG92ZXJmbG93TGVmdCA9IE1hdGgubWF4KHZpZXdwb3J0LmxlZnQgLSBzY3JvbGxQb3NpdGlvbi5sZWZ0IC0gc3RhcnQueCwgMCk7XG5cbiAgICAvLyBBbW91bnQgYnkgd2hpY2ggdG8gcHVzaCB0aGUgb3ZlcmxheSBpbiBlYWNoIGF4aXMgc3VjaCB0aGF0IGl0IHJlbWFpbnMgb24tc2NyZWVuLlxuICAgIGxldCBwdXNoWCA9IDA7XG4gICAgbGV0IHB1c2hZID0gMDtcblxuICAgIC8vIElmIHRoZSBvdmVybGF5IGZpdHMgY29tcGxldGVseSB3aXRoaW4gdGhlIGJvdW5kcyBvZiB0aGUgdmlld3BvcnQsIHB1c2ggaXQgZnJvbSB3aGljaGV2ZXJcbiAgICAvLyBkaXJlY3Rpb24gaXMgZ29lcyBvZmYtc2NyZWVuLiBPdGhlcndpc2UsIHB1c2ggdGhlIHRvcC1sZWZ0IGNvcm5lciBzdWNoIHRoYXQgaXRzIGluIHRoZVxuICAgIC8vIHZpZXdwb3J0IGFuZCBhbGxvdyBmb3IgdGhlIHRyYWlsaW5nIGVuZCBvZiB0aGUgb3ZlcmxheSB0byBnbyBvdXQgb2YgYm91bmRzLlxuICAgIGlmIChvdmVybGF5LndpZHRoIDw9IHZpZXdwb3J0LndpZHRoKSB7XG4gICAgICBwdXNoWCA9IG92ZXJmbG93TGVmdCB8fCAtb3ZlcmZsb3dSaWdodDtcbiAgICB9IGVsc2Uge1xuICAgICAgcHVzaFggPSBzdGFydC54IDwgdGhpcy5fdmlld3BvcnRNYXJnaW4gPyB2aWV3cG9ydC5sZWZ0IC0gc2Nyb2xsUG9zaXRpb24ubGVmdCAtIHN0YXJ0LnggOiAwO1xuICAgIH1cblxuICAgIGlmIChvdmVybGF5LmhlaWdodCA8PSB2aWV3cG9ydC5oZWlnaHQpIHtcbiAgICAgIHB1c2hZID0gb3ZlcmZsb3dUb3AgfHwgLW92ZXJmbG93Qm90dG9tO1xuICAgIH0gZWxzZSB7XG4gICAgICBwdXNoWSA9IHN0YXJ0LnkgPCB0aGlzLl92aWV3cG9ydE1hcmdpbiA/IHZpZXdwb3J0LnRvcCAtIHNjcm9sbFBvc2l0aW9uLnRvcCAtIHN0YXJ0LnkgOiAwO1xuICAgIH1cblxuICAgIHRoaXMuX3ByZXZpb3VzUHVzaEFtb3VudCA9IHt4OiBwdXNoWCwgeTogcHVzaFl9O1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHg6IHN0YXJ0LnggKyBwdXNoWCxcbiAgICAgIHk6IHN0YXJ0LnkgKyBwdXNoWSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEFwcGxpZXMgYSBjb21wdXRlZCBwb3NpdGlvbiB0byB0aGUgb3ZlcmxheSBhbmQgZW1pdHMgYSBwb3NpdGlvbiBjaGFuZ2UuXG4gICAqIEBwYXJhbSBwb3NpdGlvbiBUaGUgcG9zaXRpb24gcHJlZmVyZW5jZVxuICAgKiBAcGFyYW0gb3JpZ2luUG9pbnQgVGhlIHBvaW50IG9uIHRoZSBvcmlnaW4gZWxlbWVudCB3aGVyZSB0aGUgb3ZlcmxheSBpcyBjb25uZWN0ZWQuXG4gICAqL1xuICBwcml2YXRlIF9hcHBseVBvc2l0aW9uKHBvc2l0aW9uOiBDb25uZWN0ZWRQb3NpdGlvbiwgb3JpZ2luUG9pbnQ6IFBvaW50KSB7XG4gICAgdGhpcy5fc2V0VHJhbnNmb3JtT3JpZ2luKHBvc2l0aW9uKTtcbiAgICB0aGlzLl9zZXRPdmVybGF5RWxlbWVudFN0eWxlcyhvcmlnaW5Qb2ludCwgcG9zaXRpb24pO1xuICAgIHRoaXMuX3NldEJvdW5kaW5nQm94U3R5bGVzKG9yaWdpblBvaW50LCBwb3NpdGlvbik7XG5cbiAgICBpZiAocG9zaXRpb24ucGFuZWxDbGFzcykge1xuICAgICAgdGhpcy5fYWRkUGFuZWxDbGFzc2VzKHBvc2l0aW9uLnBhbmVsQ2xhc3MpO1xuICAgIH1cblxuICAgIC8vIFNhdmUgdGhlIGxhc3QgY29ubmVjdGVkIHBvc2l0aW9uIGluIGNhc2UgdGhlIHBvc2l0aW9uIG5lZWRzIHRvIGJlIHJlLWNhbGN1bGF0ZWQuXG4gICAgdGhpcy5fbGFzdFBvc2l0aW9uID0gcG9zaXRpb247XG5cbiAgICAvLyBOb3RpZnkgdGhhdCB0aGUgcG9zaXRpb24gaGFzIGJlZW4gY2hhbmdlZCBhbG9uZyB3aXRoIGl0cyBjaGFuZ2UgcHJvcGVydGllcy5cbiAgICAvLyBXZSBvbmx5IGVtaXQgaWYgd2UndmUgZ290IGFueSBzdWJzY3JpcHRpb25zLCBiZWNhdXNlIHRoZSBzY3JvbGwgdmlzaWJpbGl0eVxuICAgIC8vIGNhbGN1bGF0aW9ucyBjYW4gYmUgc29tZXdoYXQgZXhwZW5zaXZlLlxuICAgIGlmICh0aGlzLl9wb3NpdGlvbkNoYW5nZXMub2JzZXJ2ZXJzLmxlbmd0aCkge1xuICAgICAgY29uc3Qgc2Nyb2xsYWJsZVZpZXdQcm9wZXJ0aWVzID0gdGhpcy5fZ2V0U2Nyb2xsVmlzaWJpbGl0eSgpO1xuICAgICAgY29uc3QgY2hhbmdlRXZlbnQgPSBuZXcgQ29ubmVjdGVkT3ZlcmxheVBvc2l0aW9uQ2hhbmdlKHBvc2l0aW9uLCBzY3JvbGxhYmxlVmlld1Byb3BlcnRpZXMpO1xuICAgICAgdGhpcy5fcG9zaXRpb25DaGFuZ2VzLm5leHQoY2hhbmdlRXZlbnQpO1xuICAgIH1cblxuICAgIHRoaXMuX2lzSW5pdGlhbFJlbmRlciA9IGZhbHNlO1xuICB9XG5cbiAgLyoqIFNldHMgdGhlIHRyYW5zZm9ybSBvcmlnaW4gYmFzZWQgb24gdGhlIGNvbmZpZ3VyZWQgc2VsZWN0b3IgYW5kIHRoZSBwYXNzZWQtaW4gcG9zaXRpb24uICAqL1xuICBwcml2YXRlIF9zZXRUcmFuc2Zvcm1PcmlnaW4ocG9zaXRpb246IENvbm5lY3RlZFBvc2l0aW9uKSB7XG4gICAgaWYgKCF0aGlzLl90cmFuc2Zvcm1PcmlnaW5TZWxlY3Rvcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGVsZW1lbnRzOiBOb2RlTGlzdE9mPEhUTUxFbGVtZW50PiA9IHRoaXMuX2JvdW5kaW5nQm94IS5xdWVyeVNlbGVjdG9yQWxsKFxuICAgICAgdGhpcy5fdHJhbnNmb3JtT3JpZ2luU2VsZWN0b3IsXG4gICAgKTtcbiAgICBsZXQgeE9yaWdpbjogJ2xlZnQnIHwgJ3JpZ2h0JyB8ICdjZW50ZXInO1xuICAgIGxldCB5T3JpZ2luOiAndG9wJyB8ICdib3R0b20nIHwgJ2NlbnRlcicgPSBwb3NpdGlvbi5vdmVybGF5WTtcblxuICAgIGlmIChwb3NpdGlvbi5vdmVybGF5WCA9PT0gJ2NlbnRlcicpIHtcbiAgICAgIHhPcmlnaW4gPSAnY2VudGVyJztcbiAgICB9IGVsc2UgaWYgKHRoaXMuX2lzUnRsKCkpIHtcbiAgICAgIHhPcmlnaW4gPSBwb3NpdGlvbi5vdmVybGF5WCA9PT0gJ3N0YXJ0JyA/ICdyaWdodCcgOiAnbGVmdCc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHhPcmlnaW4gPSBwb3NpdGlvbi5vdmVybGF5WCA9PT0gJ3N0YXJ0JyA/ICdsZWZ0JyA6ICdyaWdodCc7XG4gICAgfVxuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBlbGVtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgZWxlbWVudHNbaV0uc3R5bGUudHJhbnNmb3JtT3JpZ2luID0gYCR7eE9yaWdpbn0gJHt5T3JpZ2lufWA7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIHBvc2l0aW9uIGFuZCBzaXplIG9mIHRoZSBvdmVybGF5J3Mgc2l6aW5nIGNvbnRhaW5lci5cbiAgICpcbiAgICogVGhpcyBtZXRob2QgZG9lcyBubyBtZWFzdXJpbmcgYW5kIGFwcGxpZXMgbm8gc3R5bGVzIHNvIHRoYXQgd2UgY2FuIGNoZWFwbHkgY29tcHV0ZSB0aGVcbiAgICogYm91bmRzIGZvciBhbGwgcG9zaXRpb25zIGFuZCBjaG9vc2UgdGhlIGJlc3QgZml0IGJhc2VkIG9uIHRoZXNlIHJlc3VsdHMuXG4gICAqL1xuICBwcml2YXRlIF9jYWxjdWxhdGVCb3VuZGluZ0JveFJlY3Qob3JpZ2luOiBQb2ludCwgcG9zaXRpb246IENvbm5lY3RlZFBvc2l0aW9uKTogQm91bmRpbmdCb3hSZWN0IHtcbiAgICBjb25zdCB2aWV3cG9ydCA9IHRoaXMuX3ZpZXdwb3J0UmVjdDtcbiAgICBjb25zdCBpc1J0bCA9IHRoaXMuX2lzUnRsKCk7XG4gICAgbGV0IGhlaWdodDogbnVtYmVyLCB0b3A6IG51bWJlciwgYm90dG9tOiBudW1iZXI7XG5cbiAgICBpZiAocG9zaXRpb24ub3ZlcmxheVkgPT09ICd0b3AnKSB7XG4gICAgICAvLyBPdmVybGF5IGlzIG9wZW5pbmcgXCJkb3dud2FyZFwiIGFuZCB0aHVzIGlzIGJvdW5kIGJ5IHRoZSBib3R0b20gdmlld3BvcnQgZWRnZS5cbiAgICAgIHRvcCA9IG9yaWdpbi55O1xuICAgICAgaGVpZ2h0ID0gdmlld3BvcnQuaGVpZ2h0IC0gdG9wICsgdGhpcy5fdmlld3BvcnRNYXJnaW47XG4gICAgfSBlbHNlIGlmIChwb3NpdGlvbi5vdmVybGF5WSA9PT0gJ2JvdHRvbScpIHtcbiAgICAgIC8vIE92ZXJsYXkgaXMgb3BlbmluZyBcInVwd2FyZFwiIGFuZCB0aHVzIGlzIGJvdW5kIGJ5IHRoZSB0b3Agdmlld3BvcnQgZWRnZS4gV2UgbmVlZCB0byBhZGRcbiAgICAgIC8vIHRoZSB2aWV3cG9ydCBtYXJnaW4gYmFjayBpbiwgYmVjYXVzZSB0aGUgdmlld3BvcnQgcmVjdCBpcyBuYXJyb3dlZCBkb3duIHRvIHJlbW92ZSB0aGVcbiAgICAgIC8vIG1hcmdpbiwgd2hlcmVhcyB0aGUgYG9yaWdpbmAgcG9zaXRpb24gaXMgY2FsY3VsYXRlZCBiYXNlZCBvbiBpdHMgYENsaWVudFJlY3RgLlxuICAgICAgYm90dG9tID0gdmlld3BvcnQuaGVpZ2h0IC0gb3JpZ2luLnkgKyB0aGlzLl92aWV3cG9ydE1hcmdpbiAqIDI7XG4gICAgICBoZWlnaHQgPSB2aWV3cG9ydC5oZWlnaHQgLSBib3R0b20gKyB0aGlzLl92aWV3cG9ydE1hcmdpbjtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gSWYgbmVpdGhlciB0b3Agbm9yIGJvdHRvbSwgaXQgbWVhbnMgdGhhdCB0aGUgb3ZlcmxheSBpcyB2ZXJ0aWNhbGx5IGNlbnRlcmVkIG9uIHRoZVxuICAgICAgLy8gb3JpZ2luIHBvaW50LiBOb3RlIHRoYXQgd2Ugd2FudCB0aGUgcG9zaXRpb24gcmVsYXRpdmUgdG8gdGhlIHZpZXdwb3J0LCByYXRoZXIgdGhhblxuICAgICAgLy8gdGhlIHBhZ2UsIHdoaWNoIGlzIHdoeSB3ZSBkb24ndCB1c2Ugc29tZXRoaW5nIGxpa2UgYHZpZXdwb3J0LmJvdHRvbSAtIG9yaWdpbi55YCBhbmRcbiAgICAgIC8vIGBvcmlnaW4ueSAtIHZpZXdwb3J0LnRvcGAuXG4gICAgICBjb25zdCBzbWFsbGVzdERpc3RhbmNlVG9WaWV3cG9ydEVkZ2UgPSBNYXRoLm1pbihcbiAgICAgICAgdmlld3BvcnQuYm90dG9tIC0gb3JpZ2luLnkgKyB2aWV3cG9ydC50b3AsXG4gICAgICAgIG9yaWdpbi55LFxuICAgICAgKTtcblxuICAgICAgY29uc3QgcHJldmlvdXNIZWlnaHQgPSB0aGlzLl9sYXN0Qm91bmRpbmdCb3hTaXplLmhlaWdodDtcblxuICAgICAgaGVpZ2h0ID0gc21hbGxlc3REaXN0YW5jZVRvVmlld3BvcnRFZGdlICogMjtcbiAgICAgIHRvcCA9IG9yaWdpbi55IC0gc21hbGxlc3REaXN0YW5jZVRvVmlld3BvcnRFZGdlO1xuXG4gICAgICBpZiAoaGVpZ2h0ID4gcHJldmlvdXNIZWlnaHQgJiYgIXRoaXMuX2lzSW5pdGlhbFJlbmRlciAmJiAhdGhpcy5fZ3Jvd0FmdGVyT3Blbikge1xuICAgICAgICB0b3AgPSBvcmlnaW4ueSAtIHByZXZpb3VzSGVpZ2h0IC8gMjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBUaGUgb3ZlcmxheSBpcyBvcGVuaW5nICdyaWdodC13YXJkJyAodGhlIGNvbnRlbnQgZmxvd3MgdG8gdGhlIHJpZ2h0KS5cbiAgICBjb25zdCBpc0JvdW5kZWRCeVJpZ2h0Vmlld3BvcnRFZGdlID1cbiAgICAgIChwb3NpdGlvbi5vdmVybGF5WCA9PT0gJ3N0YXJ0JyAmJiAhaXNSdGwpIHx8IChwb3NpdGlvbi5vdmVybGF5WCA9PT0gJ2VuZCcgJiYgaXNSdGwpO1xuXG4gICAgLy8gVGhlIG92ZXJsYXkgaXMgb3BlbmluZyAnbGVmdC13YXJkJyAodGhlIGNvbnRlbnQgZmxvd3MgdG8gdGhlIGxlZnQpLlxuICAgIGNvbnN0IGlzQm91bmRlZEJ5TGVmdFZpZXdwb3J0RWRnZSA9XG4gICAgICAocG9zaXRpb24ub3ZlcmxheVggPT09ICdlbmQnICYmICFpc1J0bCkgfHwgKHBvc2l0aW9uLm92ZXJsYXlYID09PSAnc3RhcnQnICYmIGlzUnRsKTtcblxuICAgIGxldCB3aWR0aDogbnVtYmVyLCBsZWZ0OiBudW1iZXIsIHJpZ2h0OiBudW1iZXI7XG5cbiAgICBpZiAoaXNCb3VuZGVkQnlMZWZ0Vmlld3BvcnRFZGdlKSB7XG4gICAgICByaWdodCA9IHZpZXdwb3J0LndpZHRoIC0gb3JpZ2luLnggKyB0aGlzLl92aWV3cG9ydE1hcmdpbjtcbiAgICAgIHdpZHRoID0gb3JpZ2luLnggLSB0aGlzLl92aWV3cG9ydE1hcmdpbjtcbiAgICB9IGVsc2UgaWYgKGlzQm91bmRlZEJ5UmlnaHRWaWV3cG9ydEVkZ2UpIHtcbiAgICAgIGxlZnQgPSBvcmlnaW4ueDtcbiAgICAgIHdpZHRoID0gdmlld3BvcnQucmlnaHQgLSBvcmlnaW4ueDtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gSWYgbmVpdGhlciBzdGFydCBub3IgZW5kLCBpdCBtZWFucyB0aGF0IHRoZSBvdmVybGF5IGlzIGhvcml6b250YWxseSBjZW50ZXJlZCBvbiB0aGVcbiAgICAgIC8vIG9yaWdpbiBwb2ludC4gTm90ZSB0aGF0IHdlIHdhbnQgdGhlIHBvc2l0aW9uIHJlbGF0aXZlIHRvIHRoZSB2aWV3cG9ydCwgcmF0aGVyIHRoYW5cbiAgICAgIC8vIHRoZSBwYWdlLCB3aGljaCBpcyB3aHkgd2UgZG9uJ3QgdXNlIHNvbWV0aGluZyBsaWtlIGB2aWV3cG9ydC5yaWdodCAtIG9yaWdpbi54YCBhbmRcbiAgICAgIC8vIGBvcmlnaW4ueCAtIHZpZXdwb3J0LmxlZnRgLlxuICAgICAgY29uc3Qgc21hbGxlc3REaXN0YW5jZVRvVmlld3BvcnRFZGdlID0gTWF0aC5taW4oXG4gICAgICAgIHZpZXdwb3J0LnJpZ2h0IC0gb3JpZ2luLnggKyB2aWV3cG9ydC5sZWZ0LFxuICAgICAgICBvcmlnaW4ueCxcbiAgICAgICk7XG4gICAgICBjb25zdCBwcmV2aW91c1dpZHRoID0gdGhpcy5fbGFzdEJvdW5kaW5nQm94U2l6ZS53aWR0aDtcblxuICAgICAgd2lkdGggPSBzbWFsbGVzdERpc3RhbmNlVG9WaWV3cG9ydEVkZ2UgKiAyO1xuICAgICAgbGVmdCA9IG9yaWdpbi54IC0gc21hbGxlc3REaXN0YW5jZVRvVmlld3BvcnRFZGdlO1xuXG4gICAgICBpZiAod2lkdGggPiBwcmV2aW91c1dpZHRoICYmICF0aGlzLl9pc0luaXRpYWxSZW5kZXIgJiYgIXRoaXMuX2dyb3dBZnRlck9wZW4pIHtcbiAgICAgICAgbGVmdCA9IG9yaWdpbi54IC0gcHJldmlvdXNXaWR0aCAvIDI7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHt0b3A6IHRvcCEsIGxlZnQ6IGxlZnQhLCBib3R0b206IGJvdHRvbSEsIHJpZ2h0OiByaWdodCEsIHdpZHRoLCBoZWlnaHR9O1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIHBvc2l0aW9uIGFuZCBzaXplIG9mIHRoZSBvdmVybGF5J3Mgc2l6aW5nIHdyYXBwZXIuIFRoZSB3cmFwcGVyIGlzIHBvc2l0aW9uZWQgb24gdGhlXG4gICAqIG9yaWdpbidzIGNvbm5lY3Rpb24gcG9pbnQgYW5kIHN0cmV0Y2hlcyB0byB0aGUgYm91bmRzIG9mIHRoZSB2aWV3cG9ydC5cbiAgICpcbiAgICogQHBhcmFtIG9yaWdpbiBUaGUgcG9pbnQgb24gdGhlIG9yaWdpbiBlbGVtZW50IHdoZXJlIHRoZSBvdmVybGF5IGlzIGNvbm5lY3RlZC5cbiAgICogQHBhcmFtIHBvc2l0aW9uIFRoZSBwb3NpdGlvbiBwcmVmZXJlbmNlXG4gICAqL1xuICBwcml2YXRlIF9zZXRCb3VuZGluZ0JveFN0eWxlcyhvcmlnaW46IFBvaW50LCBwb3NpdGlvbjogQ29ubmVjdGVkUG9zaXRpb24pOiB2b2lkIHtcbiAgICBjb25zdCBib3VuZGluZ0JveFJlY3QgPSB0aGlzLl9jYWxjdWxhdGVCb3VuZGluZ0JveFJlY3Qob3JpZ2luLCBwb3NpdGlvbik7XG5cbiAgICAvLyBJdCdzIHdlaXJkIGlmIHRoZSBvdmVybGF5ICpncm93cyogd2hpbGUgc2Nyb2xsaW5nLCBzbyB3ZSB0YWtlIHRoZSBsYXN0IHNpemUgaW50byBhY2NvdW50XG4gICAgLy8gd2hlbiBhcHBseWluZyBhIG5ldyBzaXplLlxuICAgIGlmICghdGhpcy5faXNJbml0aWFsUmVuZGVyICYmICF0aGlzLl9ncm93QWZ0ZXJPcGVuKSB7XG4gICAgICBib3VuZGluZ0JveFJlY3QuaGVpZ2h0ID0gTWF0aC5taW4oYm91bmRpbmdCb3hSZWN0LmhlaWdodCwgdGhpcy5fbGFzdEJvdW5kaW5nQm94U2l6ZS5oZWlnaHQpO1xuICAgICAgYm91bmRpbmdCb3hSZWN0LndpZHRoID0gTWF0aC5taW4oYm91bmRpbmdCb3hSZWN0LndpZHRoLCB0aGlzLl9sYXN0Qm91bmRpbmdCb3hTaXplLndpZHRoKTtcbiAgICB9XG5cbiAgICBjb25zdCBzdHlsZXMgPSB7fSBhcyBDU1NTdHlsZURlY2xhcmF0aW9uO1xuXG4gICAgaWYgKHRoaXMuX2hhc0V4YWN0UG9zaXRpb24oKSkge1xuICAgICAgc3R5bGVzLnRvcCA9IHN0eWxlcy5sZWZ0ID0gJzAnO1xuICAgICAgc3R5bGVzLmJvdHRvbSA9IHN0eWxlcy5yaWdodCA9IHN0eWxlcy5tYXhIZWlnaHQgPSBzdHlsZXMubWF4V2lkdGggPSAnJztcbiAgICAgIHN0eWxlcy53aWR0aCA9IHN0eWxlcy5oZWlnaHQgPSAnMTAwJSc7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IG1heEhlaWdodCA9IHRoaXMuX292ZXJsYXlSZWYuZ2V0Q29uZmlnKCkubWF4SGVpZ2h0O1xuICAgICAgY29uc3QgbWF4V2lkdGggPSB0aGlzLl9vdmVybGF5UmVmLmdldENvbmZpZygpLm1heFdpZHRoO1xuXG4gICAgICBzdHlsZXMuaGVpZ2h0ID0gY29lcmNlQ3NzUGl4ZWxWYWx1ZShib3VuZGluZ0JveFJlY3QuaGVpZ2h0KTtcbiAgICAgIHN0eWxlcy50b3AgPSBjb2VyY2VDc3NQaXhlbFZhbHVlKGJvdW5kaW5nQm94UmVjdC50b3ApO1xuICAgICAgc3R5bGVzLmJvdHRvbSA9IGNvZXJjZUNzc1BpeGVsVmFsdWUoYm91bmRpbmdCb3hSZWN0LmJvdHRvbSk7XG4gICAgICBzdHlsZXMud2lkdGggPSBjb2VyY2VDc3NQaXhlbFZhbHVlKGJvdW5kaW5nQm94UmVjdC53aWR0aCk7XG4gICAgICBzdHlsZXMubGVmdCA9IGNvZXJjZUNzc1BpeGVsVmFsdWUoYm91bmRpbmdCb3hSZWN0LmxlZnQpO1xuICAgICAgc3R5bGVzLnJpZ2h0ID0gY29lcmNlQ3NzUGl4ZWxWYWx1ZShib3VuZGluZ0JveFJlY3QucmlnaHQpO1xuXG4gICAgICAvLyBQdXNoIHRoZSBwYW5lIGNvbnRlbnQgdG93YXJkcyB0aGUgcHJvcGVyIGRpcmVjdGlvbi5cbiAgICAgIGlmIChwb3NpdGlvbi5vdmVybGF5WCA9PT0gJ2NlbnRlcicpIHtcbiAgICAgICAgc3R5bGVzLmFsaWduSXRlbXMgPSAnY2VudGVyJztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0eWxlcy5hbGlnbkl0ZW1zID0gcG9zaXRpb24ub3ZlcmxheVggPT09ICdlbmQnID8gJ2ZsZXgtZW5kJyA6ICdmbGV4LXN0YXJ0JztcbiAgICAgIH1cblxuICAgICAgaWYgKHBvc2l0aW9uLm92ZXJsYXlZID09PSAnY2VudGVyJykge1xuICAgICAgICBzdHlsZXMuanVzdGlmeUNvbnRlbnQgPSAnY2VudGVyJztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0eWxlcy5qdXN0aWZ5Q29udGVudCA9IHBvc2l0aW9uLm92ZXJsYXlZID09PSAnYm90dG9tJyA/ICdmbGV4LWVuZCcgOiAnZmxleC1zdGFydCc7XG4gICAgICB9XG5cbiAgICAgIGlmIChtYXhIZWlnaHQpIHtcbiAgICAgICAgc3R5bGVzLm1heEhlaWdodCA9IGNvZXJjZUNzc1BpeGVsVmFsdWUobWF4SGVpZ2h0KTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1heFdpZHRoKSB7XG4gICAgICAgIHN0eWxlcy5tYXhXaWR0aCA9IGNvZXJjZUNzc1BpeGVsVmFsdWUobWF4V2lkdGgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuX2xhc3RCb3VuZGluZ0JveFNpemUgPSBib3VuZGluZ0JveFJlY3Q7XG5cbiAgICBleHRlbmRTdHlsZXModGhpcy5fYm91bmRpbmdCb3ghLnN0eWxlLCBzdHlsZXMpO1xuICB9XG5cbiAgLyoqIFJlc2V0cyB0aGUgc3R5bGVzIGZvciB0aGUgYm91bmRpbmcgYm94IHNvIHRoYXQgYSBuZXcgcG9zaXRpb25pbmcgY2FuIGJlIGNvbXB1dGVkLiAqL1xuICBwcml2YXRlIF9yZXNldEJvdW5kaW5nQm94U3R5bGVzKCkge1xuICAgIGV4dGVuZFN0eWxlcyh0aGlzLl9ib3VuZGluZ0JveCEuc3R5bGUsIHtcbiAgICAgIHRvcDogJzAnLFxuICAgICAgbGVmdDogJzAnLFxuICAgICAgcmlnaHQ6ICcwJyxcbiAgICAgIGJvdHRvbTogJzAnLFxuICAgICAgaGVpZ2h0OiAnJyxcbiAgICAgIHdpZHRoOiAnJyxcbiAgICAgIGFsaWduSXRlbXM6ICcnLFxuICAgICAganVzdGlmeUNvbnRlbnQ6ICcnLFxuICAgIH0gYXMgQ1NTU3R5bGVEZWNsYXJhdGlvbik7XG4gIH1cblxuICAvKiogUmVzZXRzIHRoZSBzdHlsZXMgZm9yIHRoZSBvdmVybGF5IHBhbmUgc28gdGhhdCBhIG5ldyBwb3NpdGlvbmluZyBjYW4gYmUgY29tcHV0ZWQuICovXG4gIHByaXZhdGUgX3Jlc2V0T3ZlcmxheUVsZW1lbnRTdHlsZXMoKSB7XG4gICAgZXh0ZW5kU3R5bGVzKHRoaXMuX3BhbmUuc3R5bGUsIHtcbiAgICAgIHRvcDogJycsXG4gICAgICBsZWZ0OiAnJyxcbiAgICAgIGJvdHRvbTogJycsXG4gICAgICByaWdodDogJycsXG4gICAgICBwb3NpdGlvbjogJycsXG4gICAgICB0cmFuc2Zvcm06ICcnLFxuICAgIH0gYXMgQ1NTU3R5bGVEZWNsYXJhdGlvbik7XG4gIH1cblxuICAvKiogU2V0cyBwb3NpdGlvbmluZyBzdHlsZXMgdG8gdGhlIG92ZXJsYXkgZWxlbWVudC4gKi9cbiAgcHJpdmF0ZSBfc2V0T3ZlcmxheUVsZW1lbnRTdHlsZXMob3JpZ2luUG9pbnQ6IFBvaW50LCBwb3NpdGlvbjogQ29ubmVjdGVkUG9zaXRpb24pOiB2b2lkIHtcbiAgICBjb25zdCBzdHlsZXMgPSB7fSBhcyBDU1NTdHlsZURlY2xhcmF0aW9uO1xuICAgIGNvbnN0IGhhc0V4YWN0UG9zaXRpb24gPSB0aGlzLl9oYXNFeGFjdFBvc2l0aW9uKCk7XG4gICAgY29uc3QgaGFzRmxleGlibGVEaW1lbnNpb25zID0gdGhpcy5faGFzRmxleGlibGVEaW1lbnNpb25zO1xuICAgIGNvbnN0IGNvbmZpZyA9IHRoaXMuX292ZXJsYXlSZWYuZ2V0Q29uZmlnKCk7XG5cbiAgICBpZiAoaGFzRXhhY3RQb3NpdGlvbikge1xuICAgICAgY29uc3Qgc2Nyb2xsUG9zaXRpb24gPSB0aGlzLl92aWV3cG9ydFJ1bGVyLmdldFZpZXdwb3J0U2Nyb2xsUG9zaXRpb24oKTtcbiAgICAgIGV4dGVuZFN0eWxlcyhzdHlsZXMsIHRoaXMuX2dldEV4YWN0T3ZlcmxheVkocG9zaXRpb24sIG9yaWdpblBvaW50LCBzY3JvbGxQb3NpdGlvbikpO1xuICAgICAgZXh0ZW5kU3R5bGVzKHN0eWxlcywgdGhpcy5fZ2V0RXhhY3RPdmVybGF5WChwb3NpdGlvbiwgb3JpZ2luUG9pbnQsIHNjcm9sbFBvc2l0aW9uKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0eWxlcy5wb3NpdGlvbiA9ICdzdGF0aWMnO1xuICAgIH1cblxuICAgIC8vIFVzZSBhIHRyYW5zZm9ybSB0byBhcHBseSB0aGUgb2Zmc2V0cy4gV2UgZG8gdGhpcyBiZWNhdXNlIHRoZSBgY2VudGVyYCBwb3NpdGlvbnMgcmVseSBvblxuICAgIC8vIGJlaW5nIGluIHRoZSBub3JtYWwgZmxleCBmbG93IGFuZCBzZXR0aW5nIGEgYHRvcGAgLyBgbGVmdGAgYXQgYWxsIHdpbGwgY29tcGxldGVseSB0aHJvd1xuICAgIC8vIG9mZiB0aGUgcG9zaXRpb24uIFdlIGFsc28gY2FuJ3QgdXNlIG1hcmdpbnMsIGJlY2F1c2UgdGhleSB3b24ndCBoYXZlIGFuIGVmZmVjdCBpbiBzb21lXG4gICAgLy8gY2FzZXMgd2hlcmUgdGhlIGVsZW1lbnQgZG9lc24ndCBoYXZlIGFueXRoaW5nIHRvIFwicHVzaCBvZmYgb2ZcIi4gRmluYWxseSwgdGhpcyB3b3Jrc1xuICAgIC8vIGJldHRlciBib3RoIHdpdGggZmxleGlibGUgYW5kIG5vbi1mbGV4aWJsZSBwb3NpdGlvbmluZy5cbiAgICBsZXQgdHJhbnNmb3JtU3RyaW5nID0gJyc7XG4gICAgbGV0IG9mZnNldFggPSB0aGlzLl9nZXRPZmZzZXQocG9zaXRpb24sICd4Jyk7XG4gICAgbGV0IG9mZnNldFkgPSB0aGlzLl9nZXRPZmZzZXQocG9zaXRpb24sICd5Jyk7XG5cbiAgICBpZiAob2Zmc2V0WCkge1xuICAgICAgdHJhbnNmb3JtU3RyaW5nICs9IGB0cmFuc2xhdGVYKCR7b2Zmc2V0WH1weCkgYDtcbiAgICB9XG5cbiAgICBpZiAob2Zmc2V0WSkge1xuICAgICAgdHJhbnNmb3JtU3RyaW5nICs9IGB0cmFuc2xhdGVZKCR7b2Zmc2V0WX1weClgO1xuICAgIH1cblxuICAgIHN0eWxlcy50cmFuc2Zvcm0gPSB0cmFuc2Zvcm1TdHJpbmcudHJpbSgpO1xuXG4gICAgLy8gSWYgYSBtYXhXaWR0aCBvciBtYXhIZWlnaHQgaXMgc3BlY2lmaWVkIG9uIHRoZSBvdmVybGF5LCB3ZSByZW1vdmUgdGhlbS4gV2UgZG8gdGhpcyBiZWNhdXNlXG4gICAgLy8gd2UgbmVlZCB0aGVzZSB2YWx1ZXMgdG8gYm90aCBiZSBzZXQgdG8gXCIxMDAlXCIgZm9yIHRoZSBhdXRvbWF0aWMgZmxleGlibGUgc2l6aW5nIHRvIHdvcmsuXG4gICAgLy8gVGhlIG1heEhlaWdodCBhbmQgbWF4V2lkdGggYXJlIHNldCBvbiB0aGUgYm91bmRpbmdCb3ggaW4gb3JkZXIgdG8gZW5mb3JjZSB0aGUgY29uc3RyYWludC5cbiAgICAvLyBOb3RlIHRoYXQgdGhpcyBkb2Vzbid0IGFwcGx5IHdoZW4gd2UgaGF2ZSBhbiBleGFjdCBwb3NpdGlvbiwgaW4gd2hpY2ggY2FzZSB3ZSBkbyB3YW50IHRvXG4gICAgLy8gYXBwbHkgdGhlbSBiZWNhdXNlIHRoZXknbGwgYmUgY2xlYXJlZCBmcm9tIHRoZSBib3VuZGluZyBib3guXG4gICAgaWYgKGNvbmZpZy5tYXhIZWlnaHQpIHtcbiAgICAgIGlmIChoYXNFeGFjdFBvc2l0aW9uKSB7XG4gICAgICAgIHN0eWxlcy5tYXhIZWlnaHQgPSBjb2VyY2VDc3NQaXhlbFZhbHVlKGNvbmZpZy5tYXhIZWlnaHQpO1xuICAgICAgfSBlbHNlIGlmIChoYXNGbGV4aWJsZURpbWVuc2lvbnMpIHtcbiAgICAgICAgc3R5bGVzLm1heEhlaWdodCA9ICcnO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChjb25maWcubWF4V2lkdGgpIHtcbiAgICAgIGlmIChoYXNFeGFjdFBvc2l0aW9uKSB7XG4gICAgICAgIHN0eWxlcy5tYXhXaWR0aCA9IGNvZXJjZUNzc1BpeGVsVmFsdWUoY29uZmlnLm1heFdpZHRoKTtcbiAgICAgIH0gZWxzZSBpZiAoaGFzRmxleGlibGVEaW1lbnNpb25zKSB7XG4gICAgICAgIHN0eWxlcy5tYXhXaWR0aCA9ICcnO1xuICAgICAgfVxuICAgIH1cblxuICAgIGV4dGVuZFN0eWxlcyh0aGlzLl9wYW5lLnN0eWxlLCBzdHlsZXMpO1xuICB9XG5cbiAgLyoqIEdldHMgdGhlIGV4YWN0IHRvcC9ib3R0b20gZm9yIHRoZSBvdmVybGF5IHdoZW4gbm90IHVzaW5nIGZsZXhpYmxlIHNpemluZyBvciB3aGVuIHB1c2hpbmcuICovXG4gIHByaXZhdGUgX2dldEV4YWN0T3ZlcmxheVkoXG4gICAgcG9zaXRpb246IENvbm5lY3RlZFBvc2l0aW9uLFxuICAgIG9yaWdpblBvaW50OiBQb2ludCxcbiAgICBzY3JvbGxQb3NpdGlvbjogVmlld3BvcnRTY3JvbGxQb3NpdGlvbixcbiAgKSB7XG4gICAgLy8gUmVzZXQgYW55IGV4aXN0aW5nIHN0eWxlcy4gVGhpcyBpcyBuZWNlc3NhcnkgaW4gY2FzZSB0aGVcbiAgICAvLyBwcmVmZXJyZWQgcG9zaXRpb24gaGFzIGNoYW5nZWQgc2luY2UgdGhlIGxhc3QgYGFwcGx5YC5cbiAgICBsZXQgc3R5bGVzID0ge3RvcDogJycsIGJvdHRvbTogJyd9IGFzIENTU1N0eWxlRGVjbGFyYXRpb247XG4gICAgbGV0IG92ZXJsYXlQb2ludCA9IHRoaXMuX2dldE92ZXJsYXlQb2ludChvcmlnaW5Qb2ludCwgdGhpcy5fb3ZlcmxheVJlY3QsIHBvc2l0aW9uKTtcblxuICAgIGlmICh0aGlzLl9pc1B1c2hlZCkge1xuICAgICAgb3ZlcmxheVBvaW50ID0gdGhpcy5fcHVzaE92ZXJsYXlPblNjcmVlbihvdmVybGF5UG9pbnQsIHRoaXMuX292ZXJsYXlSZWN0LCBzY3JvbGxQb3NpdGlvbik7XG4gICAgfVxuXG4gICAgLy8gV2Ugd2FudCB0byBzZXQgZWl0aGVyIGB0b3BgIG9yIGBib3R0b21gIGJhc2VkIG9uIHdoZXRoZXIgdGhlIG92ZXJsYXkgd2FudHMgdG8gYXBwZWFyXG4gICAgLy8gYWJvdmUgb3IgYmVsb3cgdGhlIG9yaWdpbiBhbmQgdGhlIGRpcmVjdGlvbiBpbiB3aGljaCB0aGUgZWxlbWVudCB3aWxsIGV4cGFuZC5cbiAgICBpZiAocG9zaXRpb24ub3ZlcmxheVkgPT09ICdib3R0b20nKSB7XG4gICAgICAvLyBXaGVuIHVzaW5nIGBib3R0b21gLCB3ZSBhZGp1c3QgdGhlIHkgcG9zaXRpb24gc3VjaCB0aGF0IGl0IGlzIHRoZSBkaXN0YW5jZVxuICAgICAgLy8gZnJvbSB0aGUgYm90dG9tIG9mIHRoZSB2aWV3cG9ydCByYXRoZXIgdGhhbiB0aGUgdG9wLlxuICAgICAgY29uc3QgZG9jdW1lbnRIZWlnaHQgPSB0aGlzLl9kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQhLmNsaWVudEhlaWdodDtcbiAgICAgIHN0eWxlcy5ib3R0b20gPSBgJHtkb2N1bWVudEhlaWdodCAtIChvdmVybGF5UG9pbnQueSArIHRoaXMuX292ZXJsYXlSZWN0LmhlaWdodCl9cHhgO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdHlsZXMudG9wID0gY29lcmNlQ3NzUGl4ZWxWYWx1ZShvdmVybGF5UG9pbnQueSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHN0eWxlcztcbiAgfVxuXG4gIC8qKiBHZXRzIHRoZSBleGFjdCBsZWZ0L3JpZ2h0IGZvciB0aGUgb3ZlcmxheSB3aGVuIG5vdCB1c2luZyBmbGV4aWJsZSBzaXppbmcgb3Igd2hlbiBwdXNoaW5nLiAqL1xuICBwcml2YXRlIF9nZXRFeGFjdE92ZXJsYXlYKFxuICAgIHBvc2l0aW9uOiBDb25uZWN0ZWRQb3NpdGlvbixcbiAgICBvcmlnaW5Qb2ludDogUG9pbnQsXG4gICAgc2Nyb2xsUG9zaXRpb246IFZpZXdwb3J0U2Nyb2xsUG9zaXRpb24sXG4gICkge1xuICAgIC8vIFJlc2V0IGFueSBleGlzdGluZyBzdHlsZXMuIFRoaXMgaXMgbmVjZXNzYXJ5IGluIGNhc2UgdGhlIHByZWZlcnJlZCBwb3NpdGlvbiBoYXNcbiAgICAvLyBjaGFuZ2VkIHNpbmNlIHRoZSBsYXN0IGBhcHBseWAuXG4gICAgbGV0IHN0eWxlcyA9IHtsZWZ0OiAnJywgcmlnaHQ6ICcnfSBhcyBDU1NTdHlsZURlY2xhcmF0aW9uO1xuICAgIGxldCBvdmVybGF5UG9pbnQgPSB0aGlzLl9nZXRPdmVybGF5UG9pbnQob3JpZ2luUG9pbnQsIHRoaXMuX292ZXJsYXlSZWN0LCBwb3NpdGlvbik7XG5cbiAgICBpZiAodGhpcy5faXNQdXNoZWQpIHtcbiAgICAgIG92ZXJsYXlQb2ludCA9IHRoaXMuX3B1c2hPdmVybGF5T25TY3JlZW4ob3ZlcmxheVBvaW50LCB0aGlzLl9vdmVybGF5UmVjdCwgc2Nyb2xsUG9zaXRpb24pO1xuICAgIH1cblxuICAgIC8vIFdlIHdhbnQgdG8gc2V0IGVpdGhlciBgbGVmdGAgb3IgYHJpZ2h0YCBiYXNlZCBvbiB3aGV0aGVyIHRoZSBvdmVybGF5IHdhbnRzIHRvIGFwcGVhciBcImJlZm9yZVwiXG4gICAgLy8gb3IgXCJhZnRlclwiIHRoZSBvcmlnaW4sIHdoaWNoIGRldGVybWluZXMgdGhlIGRpcmVjdGlvbiBpbiB3aGljaCB0aGUgZWxlbWVudCB3aWxsIGV4cGFuZC5cbiAgICAvLyBGb3IgdGhlIGhvcml6b250YWwgYXhpcywgdGhlIG1lYW5pbmcgb2YgXCJiZWZvcmVcIiBhbmQgXCJhZnRlclwiIGNoYW5nZSBiYXNlZCBvbiB3aGV0aGVyIHRoZVxuICAgIC8vIHBhZ2UgaXMgaW4gUlRMIG9yIExUUi5cbiAgICBsZXQgaG9yaXpvbnRhbFN0eWxlUHJvcGVydHk6ICdsZWZ0JyB8ICdyaWdodCc7XG5cbiAgICBpZiAodGhpcy5faXNSdGwoKSkge1xuICAgICAgaG9yaXpvbnRhbFN0eWxlUHJvcGVydHkgPSBwb3NpdGlvbi5vdmVybGF5WCA9PT0gJ2VuZCcgPyAnbGVmdCcgOiAncmlnaHQnO1xuICAgIH0gZWxzZSB7XG4gICAgICBob3Jpem9udGFsU3R5bGVQcm9wZXJ0eSA9IHBvc2l0aW9uLm92ZXJsYXlYID09PSAnZW5kJyA/ICdyaWdodCcgOiAnbGVmdCc7XG4gICAgfVxuXG4gICAgLy8gV2hlbiB3ZSdyZSBzZXR0aW5nIGByaWdodGAsIHdlIGFkanVzdCB0aGUgeCBwb3NpdGlvbiBzdWNoIHRoYXQgaXQgaXMgdGhlIGRpc3RhbmNlXG4gICAgLy8gZnJvbSB0aGUgcmlnaHQgZWRnZSBvZiB0aGUgdmlld3BvcnQgcmF0aGVyIHRoYW4gdGhlIGxlZnQgZWRnZS5cbiAgICBpZiAoaG9yaXpvbnRhbFN0eWxlUHJvcGVydHkgPT09ICdyaWdodCcpIHtcbiAgICAgIGNvbnN0IGRvY3VtZW50V2lkdGggPSB0aGlzLl9kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQhLmNsaWVudFdpZHRoO1xuICAgICAgc3R5bGVzLnJpZ2h0ID0gYCR7ZG9jdW1lbnRXaWR0aCAtIChvdmVybGF5UG9pbnQueCArIHRoaXMuX292ZXJsYXlSZWN0LndpZHRoKX1weGA7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0eWxlcy5sZWZ0ID0gY29lcmNlQ3NzUGl4ZWxWYWx1ZShvdmVybGF5UG9pbnQueCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHN0eWxlcztcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSB2aWV3IHByb3BlcnRpZXMgb2YgdGhlIHRyaWdnZXIgYW5kIG92ZXJsYXksIGluY2x1ZGluZyB3aGV0aGVyIHRoZXkgYXJlIGNsaXBwZWRcbiAgICogb3IgY29tcGxldGVseSBvdXRzaWRlIHRoZSB2aWV3IG9mIGFueSBvZiB0aGUgc3RyYXRlZ3kncyBzY3JvbGxhYmxlcy5cbiAgICovXG4gIHByaXZhdGUgX2dldFNjcm9sbFZpc2liaWxpdHkoKTogU2Nyb2xsaW5nVmlzaWJpbGl0eSB7XG4gICAgLy8gTm90ZTogbmVlZHMgZnJlc2ggcmVjdHMgc2luY2UgdGhlIHBvc2l0aW9uIGNvdWxkJ3ZlIGNoYW5nZWQuXG4gICAgY29uc3Qgb3JpZ2luQm91bmRzID0gdGhpcy5fZ2V0T3JpZ2luUmVjdCgpO1xuICAgIGNvbnN0IG92ZXJsYXlCb3VuZHMgPSB0aGlzLl9wYW5lLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG4gICAgLy8gVE9ETyhqZWxib3Vybik6IGluc3RlYWQgb2YgbmVlZGluZyBhbGwgb2YgdGhlIGNsaWVudCByZWN0cyBmb3IgdGhlc2Ugc2Nyb2xsaW5nIGNvbnRhaW5lcnNcbiAgICAvLyBldmVyeSB0aW1lLCB3ZSBzaG91bGQgYmUgYWJsZSB0byB1c2UgdGhlIHNjcm9sbFRvcCBvZiB0aGUgY29udGFpbmVycyBpZiB0aGUgc2l6ZSBvZiB0aG9zZVxuICAgIC8vIGNvbnRhaW5lcnMgaGFzbid0IGNoYW5nZWQuXG4gICAgY29uc3Qgc2Nyb2xsQ29udGFpbmVyQm91bmRzID0gdGhpcy5fc2Nyb2xsYWJsZXMubWFwKHNjcm9sbGFibGUgPT4ge1xuICAgICAgcmV0dXJuIHNjcm9sbGFibGUuZ2V0RWxlbWVudFJlZigpLm5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgaXNPcmlnaW5DbGlwcGVkOiBpc0VsZW1lbnRDbGlwcGVkQnlTY3JvbGxpbmcob3JpZ2luQm91bmRzLCBzY3JvbGxDb250YWluZXJCb3VuZHMpLFxuICAgICAgaXNPcmlnaW5PdXRzaWRlVmlldzogaXNFbGVtZW50U2Nyb2xsZWRPdXRzaWRlVmlldyhvcmlnaW5Cb3VuZHMsIHNjcm9sbENvbnRhaW5lckJvdW5kcyksXG4gICAgICBpc092ZXJsYXlDbGlwcGVkOiBpc0VsZW1lbnRDbGlwcGVkQnlTY3JvbGxpbmcob3ZlcmxheUJvdW5kcywgc2Nyb2xsQ29udGFpbmVyQm91bmRzKSxcbiAgICAgIGlzT3ZlcmxheU91dHNpZGVWaWV3OiBpc0VsZW1lbnRTY3JvbGxlZE91dHNpZGVWaWV3KG92ZXJsYXlCb3VuZHMsIHNjcm9sbENvbnRhaW5lckJvdW5kcyksXG4gICAgfTtcbiAgfVxuXG4gIC8qKiBTdWJ0cmFjdHMgdGhlIGFtb3VudCB0aGF0IGFuIGVsZW1lbnQgaXMgb3ZlcmZsb3dpbmcgb24gYW4gYXhpcyBmcm9tIGl0cyBsZW5ndGguICovXG4gIHByaXZhdGUgX3N1YnRyYWN0T3ZlcmZsb3dzKGxlbmd0aDogbnVtYmVyLCAuLi5vdmVyZmxvd3M6IG51bWJlcltdKTogbnVtYmVyIHtcbiAgICByZXR1cm4gb3ZlcmZsb3dzLnJlZHVjZSgoY3VycmVudFZhbHVlOiBudW1iZXIsIGN1cnJlbnRPdmVyZmxvdzogbnVtYmVyKSA9PiB7XG4gICAgICByZXR1cm4gY3VycmVudFZhbHVlIC0gTWF0aC5tYXgoY3VycmVudE92ZXJmbG93LCAwKTtcbiAgICB9LCBsZW5ndGgpO1xuICB9XG5cbiAgLyoqIE5hcnJvd3MgdGhlIGdpdmVuIHZpZXdwb3J0IHJlY3QgYnkgdGhlIGN1cnJlbnQgX3ZpZXdwb3J0TWFyZ2luLiAqL1xuICBwcml2YXRlIF9nZXROYXJyb3dlZFZpZXdwb3J0UmVjdCgpOiBEaW1lbnNpb25zIHtcbiAgICAvLyBXZSByZWNhbGN1bGF0ZSB0aGUgdmlld3BvcnQgcmVjdCBoZXJlIG91cnNlbHZlcywgcmF0aGVyIHRoYW4gdXNpbmcgdGhlIFZpZXdwb3J0UnVsZXIsXG4gICAgLy8gYmVjYXVzZSB3ZSB3YW50IHRvIHVzZSB0aGUgYGNsaWVudFdpZHRoYCBhbmQgYGNsaWVudEhlaWdodGAgYXMgdGhlIGJhc2UuIFRoZSBkaWZmZXJlbmNlXG4gICAgLy8gYmVpbmcgdGhhdCB0aGUgY2xpZW50IHByb3BlcnRpZXMgZG9uJ3QgaW5jbHVkZSB0aGUgc2Nyb2xsYmFyLCBhcyBvcHBvc2VkIHRvIGBpbm5lcldpZHRoYFxuICAgIC8vIGFuZCBgaW5uZXJIZWlnaHRgIHRoYXQgZG8uIFRoaXMgaXMgbmVjZXNzYXJ5LCBiZWNhdXNlIHRoZSBvdmVybGF5IGNvbnRhaW5lciB1c2VzXG4gICAgLy8gMTAwJSBgd2lkdGhgIGFuZCBgaGVpZ2h0YCB3aGljaCBkb24ndCBpbmNsdWRlIHRoZSBzY3JvbGxiYXIgZWl0aGVyLlxuICAgIGNvbnN0IHdpZHRoID0gdGhpcy5fZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50IS5jbGllbnRXaWR0aDtcbiAgICBjb25zdCBoZWlnaHQgPSB0aGlzLl9kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQhLmNsaWVudEhlaWdodDtcbiAgICBjb25zdCBzY3JvbGxQb3NpdGlvbiA9IHRoaXMuX3ZpZXdwb3J0UnVsZXIuZ2V0Vmlld3BvcnRTY3JvbGxQb3NpdGlvbigpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHRvcDogc2Nyb2xsUG9zaXRpb24udG9wICsgdGhpcy5fdmlld3BvcnRNYXJnaW4sXG4gICAgICBsZWZ0OiBzY3JvbGxQb3NpdGlvbi5sZWZ0ICsgdGhpcy5fdmlld3BvcnRNYXJnaW4sXG4gICAgICByaWdodDogc2Nyb2xsUG9zaXRpb24ubGVmdCArIHdpZHRoIC0gdGhpcy5fdmlld3BvcnRNYXJnaW4sXG4gICAgICBib3R0b206IHNjcm9sbFBvc2l0aW9uLnRvcCArIGhlaWdodCAtIHRoaXMuX3ZpZXdwb3J0TWFyZ2luLFxuICAgICAgd2lkdGg6IHdpZHRoIC0gMiAqIHRoaXMuX3ZpZXdwb3J0TWFyZ2luLFxuICAgICAgaGVpZ2h0OiBoZWlnaHQgLSAyICogdGhpcy5fdmlld3BvcnRNYXJnaW4sXG4gICAgfTtcbiAgfVxuXG4gIC8qKiBXaGV0aGVyIHRoZSB3ZSdyZSBkZWFsaW5nIHdpdGggYW4gUlRMIGNvbnRleHQgKi9cbiAgcHJpdmF0ZSBfaXNSdGwoKSB7XG4gICAgcmV0dXJuIHRoaXMuX292ZXJsYXlSZWYuZ2V0RGlyZWN0aW9uKCkgPT09ICdydGwnO1xuICB9XG5cbiAgLyoqIERldGVybWluZXMgd2hldGhlciB0aGUgb3ZlcmxheSB1c2VzIGV4YWN0IG9yIGZsZXhpYmxlIHBvc2l0aW9uaW5nLiAqL1xuICBwcml2YXRlIF9oYXNFeGFjdFBvc2l0aW9uKCkge1xuICAgIHJldHVybiAhdGhpcy5faGFzRmxleGlibGVEaW1lbnNpb25zIHx8IHRoaXMuX2lzUHVzaGVkO1xuICB9XG5cbiAgLyoqIFJldHJpZXZlcyB0aGUgb2Zmc2V0IG9mIGEgcG9zaXRpb24gYWxvbmcgdGhlIHggb3IgeSBheGlzLiAqL1xuICBwcml2YXRlIF9nZXRPZmZzZXQocG9zaXRpb246IENvbm5lY3RlZFBvc2l0aW9uLCBheGlzOiAneCcgfCAneScpIHtcbiAgICBpZiAoYXhpcyA9PT0gJ3gnKSB7XG4gICAgICAvLyBXZSBkb24ndCBkbyBzb21ldGhpbmcgbGlrZSBgcG9zaXRpb25bJ29mZnNldCcgKyBheGlzXWAgaW5cbiAgICAgIC8vIG9yZGVyIHRvIGF2b2lkIGJyZWFraW5nIG1pbmlmaWVycyB0aGF0IHJlbmFtZSBwcm9wZXJ0aWVzLlxuICAgICAgcmV0dXJuIHBvc2l0aW9uLm9mZnNldFggPT0gbnVsbCA/IHRoaXMuX29mZnNldFggOiBwb3NpdGlvbi5vZmZzZXRYO1xuICAgIH1cblxuICAgIHJldHVybiBwb3NpdGlvbi5vZmZzZXRZID09IG51bGwgPyB0aGlzLl9vZmZzZXRZIDogcG9zaXRpb24ub2Zmc2V0WTtcbiAgfVxuXG4gIC8qKiBWYWxpZGF0ZXMgdGhhdCB0aGUgY3VycmVudCBwb3NpdGlvbiBtYXRjaCB0aGUgZXhwZWN0ZWQgdmFsdWVzLiAqL1xuICBwcml2YXRlIF92YWxpZGF0ZVBvc2l0aW9ucygpOiB2b2lkIHtcbiAgICBpZiAodHlwZW9mIG5nRGV2TW9kZSA9PT0gJ3VuZGVmaW5lZCcgfHwgbmdEZXZNb2RlKSB7XG4gICAgICBpZiAoIXRoaXMuX3ByZWZlcnJlZFBvc2l0aW9ucy5sZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgRXJyb3IoJ0ZsZXhpYmxlQ29ubmVjdGVkUG9zaXRpb25TdHJhdGVneTogQXQgbGVhc3Qgb25lIHBvc2l0aW9uIGlzIHJlcXVpcmVkLicpO1xuICAgICAgfVxuXG4gICAgICAvLyBUT0RPKGNyaXNiZXRvKTogcmVtb3ZlIHRoZXNlIG9uY2UgQW5ndWxhcidzIHRlbXBsYXRlIHR5cGVcbiAgICAgIC8vIGNoZWNraW5nIGlzIGFkdmFuY2VkIGVub3VnaCB0byBjYXRjaCB0aGVzZSBjYXNlcy5cbiAgICAgIHRoaXMuX3ByZWZlcnJlZFBvc2l0aW9ucy5mb3JFYWNoKHBhaXIgPT4ge1xuICAgICAgICB2YWxpZGF0ZUhvcml6b250YWxQb3NpdGlvbignb3JpZ2luWCcsIHBhaXIub3JpZ2luWCk7XG4gICAgICAgIHZhbGlkYXRlVmVydGljYWxQb3NpdGlvbignb3JpZ2luWScsIHBhaXIub3JpZ2luWSk7XG4gICAgICAgIHZhbGlkYXRlSG9yaXpvbnRhbFBvc2l0aW9uKCdvdmVybGF5WCcsIHBhaXIub3ZlcmxheVgpO1xuICAgICAgICB2YWxpZGF0ZVZlcnRpY2FsUG9zaXRpb24oJ292ZXJsYXlZJywgcGFpci5vdmVybGF5WSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKiogQWRkcyBhIHNpbmdsZSBDU1MgY2xhc3Mgb3IgYW4gYXJyYXkgb2YgY2xhc3NlcyBvbiB0aGUgb3ZlcmxheSBwYW5lbC4gKi9cbiAgcHJpdmF0ZSBfYWRkUGFuZWxDbGFzc2VzKGNzc0NsYXNzZXM6IHN0cmluZyB8IHN0cmluZ1tdKSB7XG4gICAgaWYgKHRoaXMuX3BhbmUpIHtcbiAgICAgIGNvZXJjZUFycmF5KGNzc0NsYXNzZXMpLmZvckVhY2goY3NzQ2xhc3MgPT4ge1xuICAgICAgICBpZiAoY3NzQ2xhc3MgIT09ICcnICYmIHRoaXMuX2FwcGxpZWRQYW5lbENsYXNzZXMuaW5kZXhPZihjc3NDbGFzcykgPT09IC0xKSB7XG4gICAgICAgICAgdGhpcy5fYXBwbGllZFBhbmVsQ2xhc3Nlcy5wdXNoKGNzc0NsYXNzKTtcbiAgICAgICAgICB0aGlzLl9wYW5lLmNsYXNzTGlzdC5hZGQoY3NzQ2xhc3MpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKiogQ2xlYXJzIHRoZSBjbGFzc2VzIHRoYXQgdGhlIHBvc2l0aW9uIHN0cmF0ZWd5IGhhcyBhcHBsaWVkIGZyb20gdGhlIG92ZXJsYXkgcGFuZWwuICovXG4gIHByaXZhdGUgX2NsZWFyUGFuZWxDbGFzc2VzKCkge1xuICAgIGlmICh0aGlzLl9wYW5lKSB7XG4gICAgICB0aGlzLl9hcHBsaWVkUGFuZWxDbGFzc2VzLmZvckVhY2goY3NzQ2xhc3MgPT4ge1xuICAgICAgICB0aGlzLl9wYW5lLmNsYXNzTGlzdC5yZW1vdmUoY3NzQ2xhc3MpO1xuICAgICAgfSk7XG4gICAgICB0aGlzLl9hcHBsaWVkUGFuZWxDbGFzc2VzID0gW107XG4gICAgfVxuICB9XG5cbiAgLyoqIFJldHVybnMgdGhlIENsaWVudFJlY3Qgb2YgdGhlIGN1cnJlbnQgb3JpZ2luLiAqL1xuICBwcml2YXRlIF9nZXRPcmlnaW5SZWN0KCk6IERpbWVuc2lvbnMge1xuICAgIGNvbnN0IG9yaWdpbiA9IHRoaXMuX29yaWdpbjtcblxuICAgIGlmIChvcmlnaW4gaW5zdGFuY2VvZiBFbGVtZW50UmVmKSB7XG4gICAgICByZXR1cm4gb3JpZ2luLm5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIEVsZW1lbnQgc28gU1ZHIGVsZW1lbnRzIGFyZSBhbHNvIHN1cHBvcnRlZC5cbiAgICBpZiAob3JpZ2luIGluc3RhbmNlb2YgRWxlbWVudCkge1xuICAgICAgcmV0dXJuIG9yaWdpbi5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICB9XG5cbiAgICBjb25zdCB3aWR0aCA9IG9yaWdpbi53aWR0aCB8fCAwO1xuICAgIGNvbnN0IGhlaWdodCA9IG9yaWdpbi5oZWlnaHQgfHwgMDtcblxuICAgIC8vIElmIHRoZSBvcmlnaW4gaXMgYSBwb2ludCwgcmV0dXJuIGEgY2xpZW50IHJlY3QgYXMgaWYgaXQgd2FzIGEgMHgwIGVsZW1lbnQgYXQgdGhlIHBvaW50LlxuICAgIHJldHVybiB7XG4gICAgICB0b3A6IG9yaWdpbi55LFxuICAgICAgYm90dG9tOiBvcmlnaW4ueSArIGhlaWdodCxcbiAgICAgIGxlZnQ6IG9yaWdpbi54LFxuICAgICAgcmlnaHQ6IG9yaWdpbi54ICsgd2lkdGgsXG4gICAgICBoZWlnaHQsXG4gICAgICB3aWR0aCxcbiAgICB9O1xuICB9XG59XG5cbi8qKiBBIHNpbXBsZSAoeCwgeSkgY29vcmRpbmF0ZS4gKi9cbmludGVyZmFjZSBQb2ludCB7XG4gIHg6IG51bWJlcjtcbiAgeTogbnVtYmVyO1xufVxuXG4vKiogUmVjb3JkIG9mIG1lYXN1cmVtZW50cyBmb3IgaG93IGFuIG92ZXJsYXkgKGF0IGEgZ2l2ZW4gcG9zaXRpb24pIGZpdHMgaW50byB0aGUgdmlld3BvcnQuICovXG5pbnRlcmZhY2UgT3ZlcmxheUZpdCB7XG4gIC8qKiBXaGV0aGVyIHRoZSBvdmVybGF5IGZpdHMgY29tcGxldGVseSBpbiB0aGUgdmlld3BvcnQuICovXG4gIGlzQ29tcGxldGVseVdpdGhpblZpZXdwb3J0OiBib29sZWFuO1xuXG4gIC8qKiBXaGV0aGVyIHRoZSBvdmVybGF5IGZpdHMgaW4gdGhlIHZpZXdwb3J0IG9uIHRoZSB5LWF4aXMuICovXG4gIGZpdHNJblZpZXdwb3J0VmVydGljYWxseTogYm9vbGVhbjtcblxuICAvKiogV2hldGhlciB0aGUgb3ZlcmxheSBmaXRzIGluIHRoZSB2aWV3cG9ydCBvbiB0aGUgeC1heGlzLiAqL1xuICBmaXRzSW5WaWV3cG9ydEhvcml6b250YWxseTogYm9vbGVhbjtcblxuICAvKiogVGhlIHRvdGFsIHZpc2libGUgYXJlYSAoaW4gcHheMikgb2YgdGhlIG92ZXJsYXkgaW5zaWRlIHRoZSB2aWV3cG9ydC4gKi9cbiAgdmlzaWJsZUFyZWE6IG51bWJlcjtcbn1cblxuLyoqIFJlY29yZCBvZiB0aGUgbWVhc3VyZW1lbnRzIGRldGVybWluaW5nIHdoZXRoZXIgYW4gb3ZlcmxheSB3aWxsIGZpdCBpbiBhIHNwZWNpZmljIHBvc2l0aW9uLiAqL1xuaW50ZXJmYWNlIEZhbGxiYWNrUG9zaXRpb24ge1xuICBwb3NpdGlvbjogQ29ubmVjdGVkUG9zaXRpb247XG4gIG9yaWdpblBvaW50OiBQb2ludDtcbiAgb3ZlcmxheVBvaW50OiBQb2ludDtcbiAgb3ZlcmxheUZpdDogT3ZlcmxheUZpdDtcbiAgb3ZlcmxheVJlY3Q6IERpbWVuc2lvbnM7XG59XG5cbi8qKiBQb3NpdGlvbiBhbmQgc2l6ZSBvZiB0aGUgb3ZlcmxheSBzaXppbmcgd3JhcHBlciBmb3IgYSBzcGVjaWZpYyBwb3NpdGlvbi4gKi9cbmludGVyZmFjZSBCb3VuZGluZ0JveFJlY3Qge1xuICB0b3A6IG51bWJlcjtcbiAgbGVmdDogbnVtYmVyO1xuICBib3R0b206IG51bWJlcjtcbiAgcmlnaHQ6IG51bWJlcjtcbiAgaGVpZ2h0OiBudW1iZXI7XG4gIHdpZHRoOiBudW1iZXI7XG59XG5cbi8qKiBSZWNvcmQgb2YgbWVhc3VyZXMgZGV0ZXJtaW5pbmcgaG93IHdlbGwgYSBnaXZlbiBwb3NpdGlvbiB3aWxsIGZpdCB3aXRoIGZsZXhpYmxlIGRpbWVuc2lvbnMuICovXG5pbnRlcmZhY2UgRmxleGlibGVGaXQge1xuICBwb3NpdGlvbjogQ29ubmVjdGVkUG9zaXRpb247XG4gIG9yaWdpbjogUG9pbnQ7XG4gIG92ZXJsYXlSZWN0OiBEaW1lbnNpb25zO1xuICBib3VuZGluZ0JveFJlY3Q6IEJvdW5kaW5nQm94UmVjdDtcbn1cblxuLyoqIEEgY29ubmVjdGVkIHBvc2l0aW9uIGFzIHNwZWNpZmllZCBieSB0aGUgdXNlci4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ29ubmVjdGVkUG9zaXRpb24ge1xuICBvcmlnaW5YOiAnc3RhcnQnIHwgJ2NlbnRlcicgfCAnZW5kJztcbiAgb3JpZ2luWTogJ3RvcCcgfCAnY2VudGVyJyB8ICdib3R0b20nO1xuXG4gIG92ZXJsYXlYOiAnc3RhcnQnIHwgJ2NlbnRlcicgfCAnZW5kJztcbiAgb3ZlcmxheVk6ICd0b3AnIHwgJ2NlbnRlcicgfCAnYm90dG9tJztcblxuICB3ZWlnaHQ/OiBudW1iZXI7XG4gIG9mZnNldFg/OiBudW1iZXI7XG4gIG9mZnNldFk/OiBudW1iZXI7XG4gIHBhbmVsQ2xhc3M/OiBzdHJpbmcgfCBzdHJpbmdbXTtcbn1cblxuLyoqIFNoYWxsb3ctZXh0ZW5kcyBhIHN0eWxlc2hlZXQgb2JqZWN0IHdpdGggYW5vdGhlciBzdHlsZXNoZWV0IG9iamVjdC4gKi9cbmZ1bmN0aW9uIGV4dGVuZFN0eWxlcyhcbiAgZGVzdGluYXRpb246IENTU1N0eWxlRGVjbGFyYXRpb24sXG4gIHNvdXJjZTogQ1NTU3R5bGVEZWNsYXJhdGlvbixcbik6IENTU1N0eWxlRGVjbGFyYXRpb24ge1xuICBmb3IgKGxldCBrZXkgaW4gc291cmNlKSB7XG4gICAgaWYgKHNvdXJjZS5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICBkZXN0aW5hdGlvbltrZXldID0gc291cmNlW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGRlc3RpbmF0aW9uO1xufVxuXG4vKipcbiAqIEV4dHJhY3RzIHRoZSBwaXhlbCB2YWx1ZSBhcyBhIG51bWJlciBmcm9tIGEgdmFsdWUsIGlmIGl0J3MgYSBudW1iZXJcbiAqIG9yIGEgQ1NTIHBpeGVsIHN0cmluZyAoZS5nLiBgMTMzN3B4YCkuIE90aGVyd2lzZSByZXR1cm5zIG51bGwuXG4gKi9cbmZ1bmN0aW9uIGdldFBpeGVsVmFsdWUoaW5wdXQ6IG51bWJlciB8IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQpOiBudW1iZXIgfCBudWxsIHtcbiAgaWYgKHR5cGVvZiBpbnB1dCAhPT0gJ251bWJlcicgJiYgaW5wdXQgIT0gbnVsbCkge1xuICAgIGNvbnN0IFt2YWx1ZSwgdW5pdHNdID0gaW5wdXQuc3BsaXQoY3NzVW5pdFBhdHRlcm4pO1xuICAgIHJldHVybiAhdW5pdHMgfHwgdW5pdHMgPT09ICdweCcgPyBwYXJzZUZsb2F0KHZhbHVlKSA6IG51bGw7XG4gIH1cblxuICByZXR1cm4gaW5wdXQgfHwgbnVsbDtcbn1cblxuLyoqXG4gKiBHZXRzIGEgdmVyc2lvbiBvZiBhbiBlbGVtZW50J3MgYm91bmRpbmcgYENsaWVudFJlY3RgIHdoZXJlIGFsbCB0aGUgdmFsdWVzIGFyZSByb3VuZGVkIGRvd24gdG9cbiAqIHRoZSBuZWFyZXN0IHBpeGVsLiBUaGlzIGFsbG93cyB1cyB0byBhY2NvdW50IGZvciB0aGUgY2FzZXMgd2hlcmUgdGhlcmUgbWF5IGJlIHN1Yi1waXhlbFxuICogZGV2aWF0aW9ucyBpbiB0aGUgYENsaWVudFJlY3RgIHJldHVybmVkIGJ5IHRoZSBicm93c2VyIChlLmcuIHdoZW4gem9vbWVkIGluIHdpdGggYSBwZXJjZW50YWdlXG4gKiBzaXplLCBzZWUgIzIxMzUwKS5cbiAqL1xuZnVuY3Rpb24gZ2V0Um91bmRlZEJvdW5kaW5nQ2xpZW50UmVjdChjbGllbnRSZWN0OiBEaW1lbnNpb25zKTogRGltZW5zaW9ucyB7XG4gIHJldHVybiB7XG4gICAgdG9wOiBNYXRoLmZsb29yKGNsaWVudFJlY3QudG9wKSxcbiAgICByaWdodDogTWF0aC5mbG9vcihjbGllbnRSZWN0LnJpZ2h0KSxcbiAgICBib3R0b206IE1hdGguZmxvb3IoY2xpZW50UmVjdC5ib3R0b20pLFxuICAgIGxlZnQ6IE1hdGguZmxvb3IoY2xpZW50UmVjdC5sZWZ0KSxcbiAgICB3aWR0aDogTWF0aC5mbG9vcihjbGllbnRSZWN0LndpZHRoKSxcbiAgICBoZWlnaHQ6IE1hdGguZmxvb3IoY2xpZW50UmVjdC5oZWlnaHQpLFxuICB9O1xufVxuXG5leHBvcnQgY29uc3QgU1RBTkRBUkRfRFJPUERPV05fQkVMT1dfUE9TSVRJT05TOiBDb25uZWN0ZWRQb3NpdGlvbltdID0gW1xuICB7b3JpZ2luWDogJ3N0YXJ0Jywgb3JpZ2luWTogJ2JvdHRvbScsIG92ZXJsYXlYOiAnc3RhcnQnLCBvdmVybGF5WTogJ3RvcCd9LFxuICB7b3JpZ2luWDogJ3N0YXJ0Jywgb3JpZ2luWTogJ3RvcCcsIG92ZXJsYXlYOiAnc3RhcnQnLCBvdmVybGF5WTogJ2JvdHRvbSd9LFxuICB7b3JpZ2luWDogJ2VuZCcsIG9yaWdpblk6ICdib3R0b20nLCBvdmVybGF5WDogJ2VuZCcsIG92ZXJsYXlZOiAndG9wJ30sXG4gIHtvcmlnaW5YOiAnZW5kJywgb3JpZ2luWTogJ3RvcCcsIG92ZXJsYXlYOiAnZW5kJywgb3ZlcmxheVk6ICdib3R0b20nfSxcbl07XG5cbmV4cG9ydCBjb25zdCBTVEFOREFSRF9EUk9QRE9XTl9BREpBQ0VOVF9QT1NJVElPTlM6IENvbm5lY3RlZFBvc2l0aW9uW10gPSBbXG4gIHtvcmlnaW5YOiAnZW5kJywgb3JpZ2luWTogJ3RvcCcsIG92ZXJsYXlYOiAnc3RhcnQnLCBvdmVybGF5WTogJ3RvcCd9LFxuICB7b3JpZ2luWDogJ2VuZCcsIG9yaWdpblk6ICdib3R0b20nLCBvdmVybGF5WDogJ3N0YXJ0Jywgb3ZlcmxheVk6ICdib3R0b20nfSxcbiAge29yaWdpblg6ICdzdGFydCcsIG9yaWdpblk6ICd0b3AnLCBvdmVybGF5WDogJ2VuZCcsIG92ZXJsYXlZOiAndG9wJ30sXG4gIHtvcmlnaW5YOiAnc3RhcnQnLCBvcmlnaW5ZOiAnYm90dG9tJywgb3ZlcmxheVg6ICdlbmQnLCBvdmVybGF5WTogJ2JvdHRvbSd9LFxuXTtcbiJdfQ==
|