From 767525a777a331ea1bf93700828d1df09625e565 Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Mon, 26 Aug 2019 14:05:48 +0300 Subject: [PATCH 01/47] feat: implement create control script --- .../create-new-component.js | 65 +++++++++++++++++++ packages/main/package.json | 1 + 2 files changed, 66 insertions(+) create mode 100644 packages/main/lib/create-new-component/create-new-component.js diff --git a/packages/main/lib/create-new-component/create-new-component.js b/packages/main/lib/create-new-component/create-new-component.js new file mode 100644 index 000000000000..718a175ee4ea --- /dev/null +++ b/packages/main/lib/create-new-component/create-new-component.js @@ -0,0 +1,65 @@ +const jsFileContentTemplate = sComponentName => { + return `import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js"; +import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js"; +import ${sComponentName}Template from "./generated/templates/${sComponentName}Template.lit.js"; + +// Styles +import ${sComponentName}Css from "./generated/themes/${sComponentName}.css.js"; + + +const metadata = { + tag: "ui5-${sComponentName.toLowerCase()}", + properties: { + // + }, + slots: { + // + }, + events: { + // + }, +}; + +class ${sComponentName} extends UI5Element { + static get metadata() { + return metadata; + } + + static get render() { + return litRender; + } + + static get styles() { + return ${sComponentName}Css; + } + + static get template() { + return ${sComponentName}Template; + } + + static async define(...params) { + super.define(...params); + } +} + +${sComponentName}.define(); + +export default ${sComponentName}; +`; +}; + +const fs = require("fs"); + + +const aArgs = process.argv.slice(2); +const sComponentName = aArgs[0]; +const oPaths = { + "js": `./src/${sComponentName}.js`, + "css": `./src/themes/${sComponentName}.css`, + "hbs": `./src/${sComponentName}.hbs`, +}; +const sJsFileContentTemplate = jsFileContentTemplate(sComponentName); + +fs.writeFileSync(oPaths.js, sJsFileContentTemplate, { flag: "wx+" }); +fs.writeFileSync(oPaths.css, "", { flag: "wx+" }); +fs.writeFileSync(oPaths.hbs, "
Hello World
", { flag: "wx+" }); diff --git a/packages/main/package.json b/packages/main/package.json index 3204efbce21e..8cef87f6029d 100644 --- a/packages/main/package.json +++ b/packages/main/package.json @@ -66,6 +66,7 @@ "copy:qunit": "cpx \"test/**/qunit/*.*\" dist/test-resources", "copy:webcomponents-polyfill": "cpx \"../../node_modules/@webcomponents/webcomponentsjs/**/*.*\" dist/webcomponentsjs/", "dev": "npm-run-all --sequential build:i18n watch:all", + "generate-new-component" : "node ./lib/create-new-component/create-new-component.js", "start": "npm-run-all --parallel serve:static dev", "lint": "eslint .", "test:wdio": "npm-run-all --parallel --race serve:static test:wdio-run", From 2f2ba11662b9cb24b28faf3374ac2e39eb901156 Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Mon, 26 Aug 2019 16:21:44 +0300 Subject: [PATCH 02/47] fix: create control script pr notes fix --- .../{create-new-component.js => index.js} | 10 +++++++--- packages/main/package.json | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) rename packages/main/lib/create-new-component/{create-new-component.js => index.js} (97%) diff --git a/packages/main/lib/create-new-component/create-new-component.js b/packages/main/lib/create-new-component/index.js similarity index 97% rename from packages/main/lib/create-new-component/create-new-component.js rename to packages/main/lib/create-new-component/index.js index 718a175ee4ea..7c641d464cf0 100644 --- a/packages/main/lib/create-new-component/create-new-component.js +++ b/packages/main/lib/create-new-component/index.js @@ -48,11 +48,13 @@ export default ${sComponentName}; `; }; -const fs = require("fs"); - - const aArgs = process.argv.slice(2); const sComponentName = aArgs[0]; + +if (!sComponentName){ + return; +} + const oPaths = { "js": `./src/${sComponentName}.js`, "css": `./src/themes/${sComponentName}.css`, @@ -60,6 +62,8 @@ const oPaths = { }; const sJsFileContentTemplate = jsFileContentTemplate(sComponentName); +const fs = require("fs"); + fs.writeFileSync(oPaths.js, sJsFileContentTemplate, { flag: "wx+" }); fs.writeFileSync(oPaths.css, "", { flag: "wx+" }); fs.writeFileSync(oPaths.hbs, "
Hello World
", { flag: "wx+" }); diff --git a/packages/main/package.json b/packages/main/package.json index 8cef87f6029d..099808bf7248 100644 --- a/packages/main/package.json +++ b/packages/main/package.json @@ -66,7 +66,7 @@ "copy:qunit": "cpx \"test/**/qunit/*.*\" dist/test-resources", "copy:webcomponents-polyfill": "cpx \"../../node_modules/@webcomponents/webcomponentsjs/**/*.*\" dist/webcomponentsjs/", "dev": "npm-run-all --sequential build:i18n watch:all", - "generate-new-component" : "node ./lib/create-new-component/create-new-component.js", + "generate-new-component" : "node ./lib/create-new-component/index.js", "start": "npm-run-all --parallel serve:static dev", "lint": "eslint .", "test:wdio": "npm-run-all --parallel --race serve:static test:wdio-run", From f722bb6af126862f92a7334efe8204fc59dc70c2 Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Wed, 28 Aug 2019 09:59:33 +0300 Subject: [PATCH 03/47] add console error on empty string for a name of component --- packages/main/lib/create-new-component/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/main/lib/create-new-component/index.js b/packages/main/lib/create-new-component/index.js index 7c641d464cf0..73e1c5d036e4 100644 --- a/packages/main/lib/create-new-component/index.js +++ b/packages/main/lib/create-new-component/index.js @@ -52,6 +52,7 @@ const aArgs = process.argv.slice(2); const sComponentName = aArgs[0]; if (!sComponentName){ + console.error("Please enter component name.") return; } From 1357c13de27baf04686ffea392ccbea4a9025713 Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Wed, 28 Aug 2019 13:04:55 +0300 Subject: [PATCH 04/47] solve conflict --- packages/main/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/main/package.json b/packages/main/package.json index 099808bf7248..44a703fac6f8 100644 --- a/packages/main/package.json +++ b/packages/main/package.json @@ -50,7 +50,7 @@ "build:templates": "mkdirp dist/generated/templates && node ./lib/hbs2ui5/index.js -d src/ -o dist/generated/templates", "build:i18n": "npm-run-all --sequential build:i18n-defaults build:i18n-JSON", "build:i18n-defaults": "mkdirp dist/generated/i18n && node ./lib/i18n/defaults.js src/i18n dist/generated/i18n", - "build:i18n-JSON": "mkdirp dist/generated/i18n && node ./lib/i18n/toJSON.js src/i18n dist/generated/i18n", + "build:i18n-JSON": "mkdirp dist/assets/i18n && node ./lib/i18n/toJSON.js src/i18n dist/assets/i18n", "build:samples": "npm run copy:test --scripts-prepend-node-path && npm run build:api --scripts-prepend-node-path && npm run build:docs --scripts-prepend-node-path && node lib/playground/index.js", "build:pages": "npm run copy:pages", "build:qunit": "npm run copy:qunit", @@ -155,4 +155,4 @@ "dir-glob": "2.0.0", "wdio-chromedriver-service/chromedriver": "^76.0.0" } -} +} \ No newline at end of file From bd9bf4881c2834427face9a49216b206f8d30f7a Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Wed, 28 Aug 2019 13:16:15 +0300 Subject: [PATCH 05/47] removed hungarian notation --- .../main/lib/create-new-component/index.js | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/main/lib/create-new-component/index.js b/packages/main/lib/create-new-component/index.js index 73e1c5d036e4..7cb978302bea 100644 --- a/packages/main/lib/create-new-component/index.js +++ b/packages/main/lib/create-new-component/index.js @@ -1,14 +1,14 @@ -const jsFileContentTemplate = sComponentName => { +const jsFileContentTemplate = componentName => { return `import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js"; import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js"; -import ${sComponentName}Template from "./generated/templates/${sComponentName}Template.lit.js"; +import ${componentName}Template from "./generated/templates/${componentName}Template.lit.js"; // Styles -import ${sComponentName}Css from "./generated/themes/${sComponentName}.css.js"; +import ${componentName}Css from "./generated/themes/${componentName}.css.js"; const metadata = { - tag: "ui5-${sComponentName.toLowerCase()}", + tag: "ui5-${componentName.toLowerCase()}", properties: { // }, @@ -20,7 +20,7 @@ const metadata = { }, }; -class ${sComponentName} extends UI5Element { +class ${componentName} extends UI5Element { static get metadata() { return metadata; } @@ -30,11 +30,11 @@ class ${sComponentName} extends UI5Element { } static get styles() { - return ${sComponentName}Css; + return ${componentName}Css; } static get template() { - return ${sComponentName}Template; + return ${componentName}Template; } static async define(...params) { @@ -42,26 +42,26 @@ class ${sComponentName} extends UI5Element { } } -${sComponentName}.define(); +${componentName}.define(); -export default ${sComponentName}; +export default ${componentName}; `; }; -const aArgs = process.argv.slice(2); -const sComponentName = aArgs[0]; +const consoleArguments = process.argv.slice(2); +const componentName = consoleArguments[0]; -if (!sComponentName){ +if (!componentName){ console.error("Please enter component name.") return; } const oPaths = { - "js": `./src/${sComponentName}.js`, - "css": `./src/themes/${sComponentName}.css`, - "hbs": `./src/${sComponentName}.hbs`, + "js": `./src/${componentName}.js`, + "css": `./src/themes/${componentName}.css`, + "hbs": `./src/${componentName}.hbs`, }; -const sJsFileContentTemplate = jsFileContentTemplate(sComponentName); +const sJsFileContentTemplate = jsFileContentTemplate(componentName); const fs = require("fs"); From 4b82ba52111460b19c2be7d34665fcf65aae4af5 Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Wed, 28 Aug 2019 13:23:31 +0300 Subject: [PATCH 06/47] removed old component creation snippet file --- .../create-new-component.js | 65 ------------------- .../main/lib/create-new-component/index.js | 8 +-- 2 files changed, 4 insertions(+), 69 deletions(-) delete mode 100644 packages/main/lib/create-new-component/create-new-component.js diff --git a/packages/main/lib/create-new-component/create-new-component.js b/packages/main/lib/create-new-component/create-new-component.js deleted file mode 100644 index 718a175ee4ea..000000000000 --- a/packages/main/lib/create-new-component/create-new-component.js +++ /dev/null @@ -1,65 +0,0 @@ -const jsFileContentTemplate = sComponentName => { - return `import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js"; -import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js"; -import ${sComponentName}Template from "./generated/templates/${sComponentName}Template.lit.js"; - -// Styles -import ${sComponentName}Css from "./generated/themes/${sComponentName}.css.js"; - - -const metadata = { - tag: "ui5-${sComponentName.toLowerCase()}", - properties: { - // - }, - slots: { - // - }, - events: { - // - }, -}; - -class ${sComponentName} extends UI5Element { - static get metadata() { - return metadata; - } - - static get render() { - return litRender; - } - - static get styles() { - return ${sComponentName}Css; - } - - static get template() { - return ${sComponentName}Template; - } - - static async define(...params) { - super.define(...params); - } -} - -${sComponentName}.define(); - -export default ${sComponentName}; -`; -}; - -const fs = require("fs"); - - -const aArgs = process.argv.slice(2); -const sComponentName = aArgs[0]; -const oPaths = { - "js": `./src/${sComponentName}.js`, - "css": `./src/themes/${sComponentName}.css`, - "hbs": `./src/${sComponentName}.hbs`, -}; -const sJsFileContentTemplate = jsFileContentTemplate(sComponentName); - -fs.writeFileSync(oPaths.js, sJsFileContentTemplate, { flag: "wx+" }); -fs.writeFileSync(oPaths.css, "", { flag: "wx+" }); -fs.writeFileSync(oPaths.hbs, "
Hello World
", { flag: "wx+" }); diff --git a/packages/main/lib/create-new-component/index.js b/packages/main/lib/create-new-component/index.js index 7cb978302bea..4711b4ac01b7 100644 --- a/packages/main/lib/create-new-component/index.js +++ b/packages/main/lib/create-new-component/index.js @@ -56,7 +56,7 @@ if (!componentName){ return; } -const oPaths = { +const filePaths = { "js": `./src/${componentName}.js`, "css": `./src/themes/${componentName}.css`, "hbs": `./src/${componentName}.hbs`, @@ -65,6 +65,6 @@ const sJsFileContentTemplate = jsFileContentTemplate(componentName); const fs = require("fs"); -fs.writeFileSync(oPaths.js, sJsFileContentTemplate, { flag: "wx+" }); -fs.writeFileSync(oPaths.css, "", { flag: "wx+" }); -fs.writeFileSync(oPaths.hbs, "
Hello World
", { flag: "wx+" }); +fs.writeFileSync(filePaths.js, sJsFileContentTemplate, { flag: "wx+" }); +fs.writeFileSync(filePaths.css, "", { flag: "wx+" }); +fs.writeFileSync(filePaths.hbs, "
Hello World
", { flag: "wx+" }); From f77bfb624d1acd1625df1226aef7efce8c0b629d Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Fri, 30 Aug 2019 08:59:15 +0300 Subject: [PATCH 07/47] feat(ui5-tabcontainer): acc update --- packages/main/src/TabContainer.hbs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/main/src/TabContainer.hbs b/packages/main/src/TabContainer.hbs index 498e0ad70bd0..65409a69954a 100644 --- a/packages/main/src/TabContainer.hbs +++ b/packages/main/src/TabContainer.hbs @@ -3,7 +3,7 @@ dir="{{rtl}}" >
- +
@@ -45,7 +45,7 @@
- + {{#if showOverflow}} @@ -54,6 +54,7 @@ class="{{classes.overflowButton}}" icon="sap-icon://slim-arrow-down" type="Transparent" + title="Overflow Menu" > {{/if}}
@@ -62,7 +63,7 @@
{{#each renderItems}} {{#unless this.isSeparator}} -
+
{{/unless}} From a9235f717a933722a6f7da290a9ded874be42f59 Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Fri, 30 Aug 2019 09:05:41 +0300 Subject: [PATCH 08/47] merge conflict tags solve --- packages/main/package.json | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/main/package.json b/packages/main/package.json index 67e4a99b2850..0208e201dfb2 100644 --- a/packages/main/package.json +++ b/packages/main/package.json @@ -65,13 +65,7 @@ "copy:pages": "cpx \"test/**/pages/*.*\" dist/test-resources", "copy:qunit": "cpx \"test/**/qunit/*.*\" dist/test-resources", "copy:webcomponents-polyfill": "cpx \"../../node_modules/@webcomponents/webcomponentsjs/**/*.*\" dist/webcomponentsjs/", -<<<<<<< HEAD - "dev": "npm-run-all --sequential build:i18n watch:all", "generate-new-component" : "node ./lib/create-new-component/index.js", - "start": "npm-run-all --parallel serve:static dev", -======= - "generate-new-component" : "node ./lib/create-new-component/index.js", ->>>>>>> upstream/master "lint": "eslint .", "start": "npm-run-all --parallel serve:static start:prepare", "start:prepare": "npm-run-all --sequential build:i18n watch:all", From fdd2118a4ecdd676290ab3d65f771a0ebbf5574d Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Fri, 30 Aug 2019 11:04:48 +0300 Subject: [PATCH 09/47] feat(ui5-tabcontainer): update ACC of header and content --- packages/main/src/TabContainer.hbs | 6 +++--- packages/main/src/TabContainer.js | 17 +++++++++++++++++ packages/main/src/i18n/messagebundle.properties | 9 +++++++++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/packages/main/src/TabContainer.hbs b/packages/main/src/TabContainer.hbs index 65409a69954a..826f2c581d88 100644 --- a/packages/main/src/TabContainer.hbs +++ b/packages/main/src/TabContainer.hbs @@ -3,7 +3,7 @@ dir="{{rtl}}" >
- +
@@ -45,7 +45,7 @@
- + {{#if showOverflow}} @@ -54,7 +54,7 @@ class="{{classes.overflowButton}}" icon="sap-icon://slim-arrow-down" type="Transparent" - title="Overflow Menu" + title="{{overflowMenuTitle}}" > {{/if}}
diff --git a/packages/main/src/TabContainer.js b/packages/main/src/TabContainer.js index f5bb73bb51c3..5354c2bc21da 100644 --- a/packages/main/src/TabContainer.js +++ b/packages/main/src/TabContainer.js @@ -5,6 +5,8 @@ import ScrollEnablement from "@ui5/webcomponents-base/dist/delegate/ScrollEnable import ItemNavigation from "@ui5/webcomponents-base/dist/delegate/ItemNavigation.js"; import { isSpace, isEnter } from "@ui5/webcomponents-base/dist/events/PseudoEvents.js"; import { getRTL } from "@ui5/webcomponents-base/dist/config/RTL.js"; +import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js"; +import { TABCONTAINER_PREVIOUS_ACC_NAME, TABCONTAINER_NEXT_ICON_ACC_NAME, TABCONTAINER_OVERFLOW_MENU_TITLE } from "./generated/i18n/i18n-defaults.js"; import TabContainerTemplate from "./generated/templates/TabContainerTemplate.lit.js"; import Button from "./Button.js"; import CustomListItem from "./CustomListItem.js"; @@ -176,6 +178,8 @@ class TabContainer extends UI5Element { // Init ItemNavigation this._initItemNavigation(); + + this.i18nBundle = getI18nBundle("@ui5/webcomponents"); } onBeforeRendering() { @@ -391,6 +395,18 @@ class TabContainer extends UI5Element { return this.items.some(item => item.icon) && this.items.some(item => item.text); } + get previousIconACCName() { + return this.i18nBundle.getText(TABCONTAINER_PREVIOUS_ACC_NAME); + } + + get nextIconACCName() { + return this.i18nBundle.getText(TABCONTAINER_NEXT_ICON_ACC_NAME); + } + + get overflowMenuTitle() { + return this.i18nBundle.getText(TABCONTAINER_OVERFLOW_MENU_TITLE); + } + get rtl() { return getRTL() ? "rtl" : undefined; } @@ -402,6 +418,7 @@ class TabContainer extends UI5Element { Icon.define(), List.define(), Popover.define(), + fetchI18nBundle("@ui5/webcomponents"), ]); super.define(...params); diff --git a/packages/main/src/i18n/messagebundle.properties b/packages/main/src/i18n/messagebundle.properties index 8e1ff1f1294c..52af05c1c07c 100644 --- a/packages/main/src/i18n/messagebundle.properties +++ b/packages/main/src/i18n/messagebundle.properties @@ -229,6 +229,15 @@ SWITCH_ON=On #XACT: ARIA announcement for the switch off SWITCH_OFF=Off +#XACT: ACC next icon name in tab container +TABCONTAINER_NEXT_ICON_ACC_NAME=Next + +#XACT: ACC previous icon name in tab container +TABCONTAINER_PREVIOUS_ACC_NAME=Previous + +#XACT: ACC overflow menu title in tab container +TABCONTAINER_OVERFLOW_MENU_TITLE=Overflow Menu + #XTXT: Text for characters left TEXTAREA_CHARACTERS_LEFT={0} characters remaining From af2422cf2eeb7aa2a25ef5851c20758d51d3449a Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Fri, 30 Aug 2019 11:04:48 +0300 Subject: [PATCH 10/47] feat(ui5-tabcontainer): update ACC of header and content --- packages/main/src/TabContainer.hbs | 6 +++--- packages/main/src/TabContainer.js | 17 +++++++++++++++++ packages/main/src/i18n/messagebundle.properties | 9 +++++++++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/packages/main/src/TabContainer.hbs b/packages/main/src/TabContainer.hbs index 65409a69954a..aa1e158b60a6 100644 --- a/packages/main/src/TabContainer.hbs +++ b/packages/main/src/TabContainer.hbs @@ -3,7 +3,7 @@ dir="{{rtl}}" >
- +
@@ -45,7 +45,7 @@
- + {{#if showOverflow}} @@ -54,7 +54,7 @@ class="{{classes.overflowButton}}" icon="sap-icon://slim-arrow-down" type="Transparent" - title="Overflow Menu" + title="{{overflowMenuTitle}}" > {{/if}}
diff --git a/packages/main/src/TabContainer.js b/packages/main/src/TabContainer.js index f5bb73bb51c3..5354c2bc21da 100644 --- a/packages/main/src/TabContainer.js +++ b/packages/main/src/TabContainer.js @@ -5,6 +5,8 @@ import ScrollEnablement from "@ui5/webcomponents-base/dist/delegate/ScrollEnable import ItemNavigation from "@ui5/webcomponents-base/dist/delegate/ItemNavigation.js"; import { isSpace, isEnter } from "@ui5/webcomponents-base/dist/events/PseudoEvents.js"; import { getRTL } from "@ui5/webcomponents-base/dist/config/RTL.js"; +import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js"; +import { TABCONTAINER_PREVIOUS_ACC_NAME, TABCONTAINER_NEXT_ICON_ACC_NAME, TABCONTAINER_OVERFLOW_MENU_TITLE } from "./generated/i18n/i18n-defaults.js"; import TabContainerTemplate from "./generated/templates/TabContainerTemplate.lit.js"; import Button from "./Button.js"; import CustomListItem from "./CustomListItem.js"; @@ -176,6 +178,8 @@ class TabContainer extends UI5Element { // Init ItemNavigation this._initItemNavigation(); + + this.i18nBundle = getI18nBundle("@ui5/webcomponents"); } onBeforeRendering() { @@ -391,6 +395,18 @@ class TabContainer extends UI5Element { return this.items.some(item => item.icon) && this.items.some(item => item.text); } + get previousIconACCName() { + return this.i18nBundle.getText(TABCONTAINER_PREVIOUS_ACC_NAME); + } + + get nextIconACCName() { + return this.i18nBundle.getText(TABCONTAINER_NEXT_ICON_ACC_NAME); + } + + get overflowMenuTitle() { + return this.i18nBundle.getText(TABCONTAINER_OVERFLOW_MENU_TITLE); + } + get rtl() { return getRTL() ? "rtl" : undefined; } @@ -402,6 +418,7 @@ class TabContainer extends UI5Element { Icon.define(), List.define(), Popover.define(), + fetchI18nBundle("@ui5/webcomponents"), ]); super.define(...params); diff --git a/packages/main/src/i18n/messagebundle.properties b/packages/main/src/i18n/messagebundle.properties index 8e1ff1f1294c..52af05c1c07c 100644 --- a/packages/main/src/i18n/messagebundle.properties +++ b/packages/main/src/i18n/messagebundle.properties @@ -229,6 +229,15 @@ SWITCH_ON=On #XACT: ARIA announcement for the switch off SWITCH_OFF=Off +#XACT: ACC next icon name in tab container +TABCONTAINER_NEXT_ICON_ACC_NAME=Next + +#XACT: ACC previous icon name in tab container +TABCONTAINER_PREVIOUS_ACC_NAME=Previous + +#XACT: ACC overflow menu title in tab container +TABCONTAINER_OVERFLOW_MENU_TITLE=Overflow Menu + #XTXT: Text for characters left TEXTAREA_CHARACTERS_LEFT={0} characters remaining From 067dbaa0c0184a8642fcf2cba7d6b808b2aaa99b Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Tue, 3 Sep 2019 11:35:56 +0300 Subject: [PATCH 11/47] feat:(ui5-datepicker): update ACC of the component and input included --- packages/main/src/DatePicker.hbs | 7 +++- packages/main/src/DatePicker.js | 24 +++++++++++++ packages/main/src/Input.hbs | 3 ++ packages/main/src/Input.js | 34 +++++++++++++++++++ .../main/src/i18n/messagebundle.properties | 6 ++++ packages/main/src/themes/DatePicker.css | 2 ++ 6 files changed, 75 insertions(+), 1 deletion(-) diff --git a/packages/main/src/DatePicker.hbs b/packages/main/src/DatePicker.hbs index 56657d2b8627..273e1adecfe2 100644 --- a/packages/main/src/DatePicker.hbs +++ b/packages/main/src/DatePicker.hbs @@ -11,9 +11,12 @@ ?disabled="{{disabled}}" ?readonly="{{readonly}}" value-state="{{valueState}}" + aria-autocomplete="none" + aria-haspopup @ui5-change="{{_handleInputChange}}" @ui5-input="{{_handleInputLiveChange}}" data-sap-focus-ref + ._accInfo ="{{accInfo}}" > {{#unless readonly}} {{/unless}} @@ -46,6 +51,6 @@ @ui5-selectedDatesChange="{{_calendar.onSelectedDatesChange}}" > - + {{dateAriaDescriber}}
diff --git a/packages/main/src/DatePicker.js b/packages/main/src/DatePicker.js index 8e14d0c70dd3..f3350f97612b 100644 --- a/packages/main/src/DatePicker.js +++ b/packages/main/src/DatePicker.js @@ -13,6 +13,8 @@ import CalendarDate from "@ui5/webcomponents-base/dist/dates/CalendarDate.js"; import ValueState from "@ui5/webcomponents-base/dist/types/ValueState.js"; import { isShow } from "@ui5/webcomponents-base/dist/events/PseudoEvents.js"; import "./icons/appointment-2.js"; +import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js"; +import { DATEPICKER_OPEN_ICON_TITLE, DATEPICKER_DATE_TYPE } from "./generated/i18n/i18n-defaults.js"; import Icon from "./Icon.js"; import Popover from "./Popover.js"; import Calendar from "./Calendar.js"; @@ -285,6 +287,8 @@ class DatePicker extends UI5Element { onSelectedDatesChange: this._handleCalendarSelectedDatesChange.bind(this), selectedDates: [], }; + + this.i18nBundle = getI18nBundle("@ui5/webcomponents"); } onBeforeRendering() { @@ -397,6 +401,25 @@ class DatePicker extends UI5Element { return this._oDateFormat; } + get accInfo() { + return { + "ariaDescribedBy": `${this._id}-date`, + "ariaHasPopup": "true", + "ariaAutoComplete": "none", + "roleAttribute": "combobox", + "ariaOwns": `${this._id}-popover`, + "ariaExpanded": this.isOpen(), + }; + } + + get openIconTitle() { + return this.i18nBundle.getText(DATEPICKER_OPEN_ICON_TITLE); + } + + get dateAriaDescriber() { + return this.i18nBundle.getText(DATEPICKER_DATE_TYPE); + } + _getPopover() { return this.shadowRoot.querySelector("ui5-popover"); } @@ -544,6 +567,7 @@ class DatePicker extends UI5Element { Popover.define(), Calendar.define(), Input.define(), + fetchI18nBundle("@ui5/webcomponents"), ]); super.define(...params); diff --git a/packages/main/src/Input.hbs b/packages/main/src/Input.hbs index e362d20dee33..15808fe495ec 100644 --- a/packages/main/src/Input.hbs +++ b/packages/main/src/Input.hbs @@ -16,10 +16,13 @@ ?required="{{required}}" .value="{{value}}" placeholder="{{inputPlaceholder}}" + role="{{roleAttribute}}" + aria-owns="{{ariaOwns}}" aria-invalid="{{ariaInvalid}}" aria-haspopup="{{ariaHasPopup}}" aria-describedby="{{ariaDescribedBy}}" aria-autocomplete="{{ariaAutoComplete}}" + aria-expanded="{{ariaExpanded}}" @input="{{_handleInput}}" @change="{{_handleChange}}" data-sap-no-tab-ref diff --git a/packages/main/src/Input.js b/packages/main/src/Input.js index bb53179d0b0b..3a0795f556e8 100644 --- a/packages/main/src/Input.js +++ b/packages/main/src/Input.js @@ -214,6 +214,10 @@ const metadata = { _popover: { type: Object, }, + + _accInfo: { + type: Object, + }, }, events: /** @lends sap.ui.webcomponents.main.Input.prototype */ { /** @@ -575,17 +579,47 @@ class Input extends UI5Element { } get ariaDescribedBy() { + if (this._accInfo && this._accInfo.ariaDescribedBy) { + return `${this.suggestionsTextId} ${this.valueStateTextId} ${this._accInfo.ariaDescribedBy}`.trim(); + } return `${this.suggestionsTextId} ${this.valueStateTextId}`.trim(); } get ariaHasPopup() { + if (this._accInfo && this._accInfo.ariaHasPopup) { + return this._accInfo.ariaHasPopup; + } return this.showSuggestions ? "true" : undefined; } get ariaAutoComplete() { + if (this._accInfo && this._accInfo.ariaAutoComplete) { + return this._accInfo.ariaAutoComplete; + } return this.showSuggestions ? "list" : undefined; } + get roleAttribute() { + if (this._accInfo && this._accInfo.roleAttribute) { + return this._accInfo.roleAttribute; + } + return ""; + } + + get ariaOwns() { + if (this._accInfo && this._accInfo.ariaOwns) { + return this._accInfo.ariaOwns; + } + return ""; + } + + get ariaExpanded() { + if (this._accInfo && this._accInfo.ariaExpanded !== undefined) { + return this._accInfo.ariaExpanded; + } + return ""; + } + get hasValueState() { return this.valueState !== ValueState.None; } diff --git a/packages/main/src/i18n/messagebundle.properties b/packages/main/src/i18n/messagebundle.properties index 85ef7abbc110..eee8d0f170fc 100644 --- a/packages/main/src/i18n/messagebundle.properties +++ b/packages/main/src/i18n/messagebundle.properties @@ -25,6 +25,12 @@ BUTTON_ARIA_TYPE_REJECT=Negative Action #XACT: ARIA announcement for the emphasized button BUTTON_ARIA_TYPE_EMPHASIZED=Emphasized +#XACT: Aria information for the Date Picker +DATEPICKER_DATE_TYPE=Date + +#XACT: DatePicker 'Open Picker' icon title +DATEPICKER_OPEN_ICON_TITLE=Open Picker + #XTXT ICON_ACTION_SETTINGS=Settings diff --git a/packages/main/src/themes/DatePicker.css b/packages/main/src/themes/DatePicker.css index a99da7fde36f..2d47a667550f 100644 --- a/packages/main/src/themes/DatePicker.css +++ b/packages/main/src/themes/DatePicker.css @@ -1,3 +1,5 @@ +@import "./InvisibleTextStyles.css"; + :host(:not([hidden])) { display: inline-block; } From 874d752e5116fafdb7008d41d8c78c7ed0488019 Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Tue, 3 Sep 2019 14:12:37 +0300 Subject: [PATCH 12/47] Updating with comments from PR --- packages/main/src/DatePicker.hbs | 2 +- packages/main/src/DatePicker.js | 8 ++++---- packages/main/src/Input.hbs | 2 +- packages/main/src/Input.js | 17 ++++------------- packages/main/src/i18n/messagebundle.properties | 4 ++-- 5 files changed, 12 insertions(+), 21 deletions(-) diff --git a/packages/main/src/DatePicker.hbs b/packages/main/src/DatePicker.hbs index 273e1adecfe2..f60b5773ce29 100644 --- a/packages/main/src/DatePicker.hbs +++ b/packages/main/src/DatePicker.hbs @@ -51,6 +51,6 @@ @ui5-selectedDatesChange="{{_calendar.onSelectedDatesChange}}" > - {{dateAriaDescriber}} + {{dateAriaDescription}}
diff --git a/packages/main/src/DatePicker.js b/packages/main/src/DatePicker.js index f3350f97612b..8e56c5ef6374 100644 --- a/packages/main/src/DatePicker.js +++ b/packages/main/src/DatePicker.js @@ -14,7 +14,7 @@ import ValueState from "@ui5/webcomponents-base/dist/types/ValueState.js"; import { isShow } from "@ui5/webcomponents-base/dist/events/PseudoEvents.js"; import "./icons/appointment-2.js"; import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js"; -import { DATEPICKER_OPEN_ICON_TITLE, DATEPICKER_DATE_TYPE } from "./generated/i18n/i18n-defaults.js"; +import { DATEPICKER_OPEN_ICON_TITLE, DATEPICKER_DATE_ACC_TEXT } from "./generated/i18n/i18n-defaults.js"; import Icon from "./Icon.js"; import Popover from "./Popover.js"; import Calendar from "./Calendar.js"; @@ -406,7 +406,7 @@ class DatePicker extends UI5Element { "ariaDescribedBy": `${this._id}-date`, "ariaHasPopup": "true", "ariaAutoComplete": "none", - "roleAttribute": "combobox", + "role": "combobox", "ariaOwns": `${this._id}-popover`, "ariaExpanded": this.isOpen(), }; @@ -416,8 +416,8 @@ class DatePicker extends UI5Element { return this.i18nBundle.getText(DATEPICKER_OPEN_ICON_TITLE); } - get dateAriaDescriber() { - return this.i18nBundle.getText(DATEPICKER_DATE_TYPE); + get dateAriaDescription() { + return this.i18nBundle.getText(DATEPICKER_DATE_ACC_TEXT); } _getPopover() { diff --git a/packages/main/src/Input.hbs b/packages/main/src/Input.hbs index 15808fe495ec..c3cb6ff71b32 100644 --- a/packages/main/src/Input.hbs +++ b/packages/main/src/Input.hbs @@ -16,7 +16,7 @@ ?required="{{required}}" .value="{{value}}" placeholder="{{inputPlaceholder}}" - role="{{roleAttribute}}" + role="{{role}}" aria-owns="{{ariaOwns}}" aria-invalid="{{ariaInvalid}}" aria-haspopup="{{ariaHasPopup}}" diff --git a/packages/main/src/Input.js b/packages/main/src/Input.js index 03c50d935e2b..99ecdfa87aee 100644 --- a/packages/main/src/Input.js +++ b/packages/main/src/Input.js @@ -605,25 +605,16 @@ class Input extends UI5Element { return this.showSuggestions ? "list" : undefined; } - get roleAttribute() { - if (this._accInfo && this._accInfo.roleAttribute) { - return this._accInfo.roleAttribute; - } - return ""; + get role() { + return this._accInfo && this._accInfo.role; } get ariaOwns() { - if (this._accInfo && this._accInfo.ariaOwns) { - return this._accInfo.ariaOwns; - } - return ""; + return this._accInfo && this._accInfo.ariaOwns; } get ariaExpanded() { - if (this._accInfo && this._accInfo.ariaExpanded !== undefined) { - return this._accInfo.ariaExpanded; - } - return ""; + return this._accInfo && this._accInfo.ariaExpanded; } get hasValueState() { diff --git a/packages/main/src/i18n/messagebundle.properties b/packages/main/src/i18n/messagebundle.properties index eee8d0f170fc..29f343b711b6 100644 --- a/packages/main/src/i18n/messagebundle.properties +++ b/packages/main/src/i18n/messagebundle.properties @@ -25,8 +25,8 @@ BUTTON_ARIA_TYPE_REJECT=Negative Action #XACT: ARIA announcement for the emphasized button BUTTON_ARIA_TYPE_EMPHASIZED=Emphasized -#XACT: Aria information for the Date Picker -DATEPICKER_DATE_TYPE=Date +#XACT: Date +DATEPICKER_DATE_ACC_TEXT=Date #XACT: DatePicker 'Open Picker' icon title DATEPICKER_OPEN_ICON_TITLE=Open Picker From 6d1dc16b3a71d1dba50182732cdb6952e6569dc9 Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Wed, 4 Sep 2019 13:30:51 +0300 Subject: [PATCH 13/47] Update with notes from PR --- packages/main/src/Input.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/main/src/Input.js b/packages/main/src/Input.js index 99ecdfa87aee..d50c3003c473 100644 --- a/packages/main/src/Input.js +++ b/packages/main/src/Input.js @@ -592,14 +592,14 @@ class Input extends UI5Element { } get ariaHasPopup() { - if (this._accInfo && this._accInfo.ariaHasPopup) { + if (this._accInfo) { return this._accInfo.ariaHasPopup; } return this.showSuggestions ? "true" : undefined; } get ariaAutoComplete() { - if (this._accInfo && this._accInfo.ariaAutoComplete) { + if (this._accInfo) { return this._accInfo.ariaAutoComplete; } return this.showSuggestions ? "list" : undefined; From 5ed53a2d531e7f2295f57d0607d00797825d5890 Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Thu, 5 Sep 2019 13:37:30 +0300 Subject: [PATCH 14/47] Improve of get methods for acc in input --- packages/main/src/DatePicker.hbs | 2 +- packages/main/src/Input.hbs | 14 ++++---- packages/main/src/Input.js | 57 +++++++++++--------------------- 3 files changed, 28 insertions(+), 45 deletions(-) diff --git a/packages/main/src/DatePicker.hbs b/packages/main/src/DatePicker.hbs index f60b5773ce29..0cd9c9e00131 100644 --- a/packages/main/src/DatePicker.hbs +++ b/packages/main/src/DatePicker.hbs @@ -16,7 +16,7 @@ @ui5-change="{{_handleInputChange}}" @ui5-input="{{_handleInputLiveChange}}" data-sap-focus-ref - ._accInfo ="{{accInfo}}" + ._inputAccInfo ="{{accInfo}}" > {{#unless readonly}} { return this.showSuggestions ? "true" : undefined; }, + "ariaAutoComplete": this._inputAccInfo ? this._inputAccInfo.ariaAutoComplete : () => { return this.showSuggestions ? "list" : undefined; }, + "role": this._inputAccInfo && this._inputAccInfo.role, + "ariaOwns": this._inputAccInfo && this._inputAccInfo.ariaOwns, + "ariaExpanded": this._inputAccInfo && this._inputAccInfo.ariaExpanded, + }, + }; } get hasValueState() { From 70b510447e159c412e0bb2e5b3d0530a08c8d46a Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Thu, 5 Sep 2019 16:20:33 +0300 Subject: [PATCH 15/47] update with comments from pr --- packages/main/src/Input.hbs | 14 +++++++------- packages/main/src/Input.js | 10 ++++++---- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/main/src/Input.hbs b/packages/main/src/Input.hbs index 5a36c59e3949..be700e7ada3c 100644 --- a/packages/main/src/Input.hbs +++ b/packages/main/src/Input.hbs @@ -16,13 +16,13 @@ ?required="{{required}}" .value="{{value}}" placeholder="{{inputPlaceholder}}" - role="{{accInfo.inputAccInfo.role}}" - aria-owns="{{accInfo.inputAccInfo.ariaOwns}}" - aria-invalid="{{accInfo.inputAccInfo.ariaInvalid}}" - aria-haspopup="{{accInfo.inputAccInfo.ariaHasPopup}}" - aria-describedby="{{accInfo.inputAccInfo.ariaDescribedBy}}" - aria-autocomplete="{{accInfo.inputAccInfo.ariaAutoComplete}}" - aria-expanded="{{accInfo.inputAccInfo.ariaExpanded}}" + role="{{accInfo.input.role}}" + aria-owns="{{accInfo.input.ariaOwns}}" + aria-invalid="{{accInfo.input.ariaInvalid}}" + aria-haspopup="{{accInfo.input.ariaHasPopup}}" + aria-describedby="{{accInfo.input.ariaDescribedBy}}" + aria-autocomplete="{{accInfo.input.ariaAutoComplete}}" + aria-expanded="{{accInfo.input.ariaExpanded}}" @input="{{_handleInput}}" @change="{{_handleChange}}" data-sap-no-tab-ref diff --git a/packages/main/src/Input.js b/packages/main/src/Input.js index d88b5dc514ae..a0ab586fc456 100644 --- a/packages/main/src/Input.js +++ b/packages/main/src/Input.js @@ -585,14 +585,16 @@ class Input extends UI5Element { } get accInfo() { + const ariaHasPopupDefault = this.showSuggestions ? "true" : undefined; + const ariaAutoCompleteDefault = this.showSuggestions ? "list" : undefined; return { - "wrapperAccInfo": { + "wrapper": { }, - "inputAccInfo": { + "input": { "ariaDescribedBy": this._inputAccInfo ? `${this.suggestionsTextId} ${this.valueStateTextId} ${this._inputAccInfo.ariaDescribedBy}`.trim() : `${this.suggestionsTextId} ${this.valueStateTextId}`.trim(), "ariaInvalid": this.valueState === ValueState.Error ? "true" : undefined, - "ariaHasPopup": this._inputAccInfo ? this._inputAccInfo.ariaHasPopup : () => { return this.showSuggestions ? "true" : undefined; }, - "ariaAutoComplete": this._inputAccInfo ? this._inputAccInfo.ariaAutoComplete : () => { return this.showSuggestions ? "list" : undefined; }, + "ariaHasPopup": this._inputAccInfo ? this._inputAccInfo.ariaHasPopup : ariaHasPopupDefault, + "ariaAutoComplete": this._inputAccInfo ? this._inputAccInfo.ariaAutoComplete : ariaAutoCompleteDefault, "role": this._inputAccInfo && this._inputAccInfo.role, "ariaOwns": this._inputAccInfo && this._inputAccInfo.ariaOwns, "ariaExpanded": this._inputAccInfo && this._inputAccInfo.ariaExpanded, From d6598dae6aafa5b42337d8223c9d4d2919869228 Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Tue, 10 Sep 2019 11:27:35 +0300 Subject: [PATCH 16/47] changing the place of input parent information --- packages/main/src/DatePicker.hbs | 3 --- packages/main/src/DatePicker.js | 4 ++++ packages/main/src/Input.hbs | 4 ++++ packages/main/src/Input.js | 1 + 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/main/src/DatePicker.hbs b/packages/main/src/DatePicker.hbs index 0cd9c9e00131..a1f1dc8eddac 100644 --- a/packages/main/src/DatePicker.hbs +++ b/packages/main/src/DatePicker.hbs @@ -11,8 +11,6 @@ ?disabled="{{disabled}}" ?readonly="{{readonly}}" value-state="{{valueState}}" - aria-autocomplete="none" - aria-haspopup @ui5-change="{{_handleInputChange}}" @ui5-input="{{_handleInputLiveChange}}" data-sap-focus-ref @@ -51,6 +49,5 @@ @ui5-selectedDatesChange="{{_calendar.onSelectedDatesChange}}" > - {{dateAriaDescription}} diff --git a/packages/main/src/DatePicker.js b/packages/main/src/DatePicker.js index 8e56c5ef6374..24a6cfa0535d 100644 --- a/packages/main/src/DatePicker.js +++ b/packages/main/src/DatePicker.js @@ -409,6 +409,10 @@ class DatePicker extends UI5Element { "role": "combobox", "ariaOwns": `${this._id}-popover`, "ariaExpanded": this.isOpen(), + "parentInfo": { + "id": this._id, + "ariaDescription": this.dateAriaDescription, + }, }; } diff --git a/packages/main/src/Input.hbs b/packages/main/src/Input.hbs index be700e7ada3c..78029bfb7b74 100644 --- a/packages/main/src/Input.hbs +++ b/packages/main/src/Input.hbs @@ -38,6 +38,10 @@ {{suggestionsText}} {{/if}} + {{#if accInfo.input.parentInfo}} + {{accInfo.input.parentInfo.ariaDescription}} + {{/if}} + {{#if hasValueState}} {{valueStateText}} {{/if}} diff --git a/packages/main/src/Input.js b/packages/main/src/Input.js index a0ab586fc456..95e5106923b1 100644 --- a/packages/main/src/Input.js +++ b/packages/main/src/Input.js @@ -598,6 +598,7 @@ class Input extends UI5Element { "role": this._inputAccInfo && this._inputAccInfo.role, "ariaOwns": this._inputAccInfo && this._inputAccInfo.ariaOwns, "ariaExpanded": this._inputAccInfo && this._inputAccInfo.ariaExpanded, + "parentInfo": this._inputAccInfo && this._inputAccInfo.parentInfo, }, }; } From 0c842f7ea25a77be8907cc763f13067029d44763 Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Tue, 10 Sep 2019 14:29:00 +0300 Subject: [PATCH 17/47] update escaping information repeating --- packages/main/src/DatePicker.js | 5 +---- packages/main/src/Input.hbs | 4 ++-- packages/main/src/Input.js | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/main/src/DatePicker.js b/packages/main/src/DatePicker.js index 24a6cfa0535d..7a95672407b9 100644 --- a/packages/main/src/DatePicker.js +++ b/packages/main/src/DatePicker.js @@ -409,10 +409,7 @@ class DatePicker extends UI5Element { "role": "combobox", "ariaOwns": `${this._id}-popover`, "ariaExpanded": this.isOpen(), - "parentInfo": { - "id": this._id, - "ariaDescription": this.dateAriaDescription, - }, + "ariaDescription": this.dateAriaDescription, }; } diff --git a/packages/main/src/Input.hbs b/packages/main/src/Input.hbs index 78029bfb7b74..eaf02bd056e0 100644 --- a/packages/main/src/Input.hbs +++ b/packages/main/src/Input.hbs @@ -38,8 +38,8 @@ {{suggestionsText}} {{/if}} - {{#if accInfo.input.parentInfo}} - {{accInfo.input.parentInfo.ariaDescription}} + {{#if accInfo.input.ariaDescribedBy}} + {{accInfo.input.ariaDescription}} {{/if}} {{#if hasValueState}} diff --git a/packages/main/src/Input.js b/packages/main/src/Input.js index 95e5106923b1..dfa4bab1efa1 100644 --- a/packages/main/src/Input.js +++ b/packages/main/src/Input.js @@ -598,7 +598,7 @@ class Input extends UI5Element { "role": this._inputAccInfo && this._inputAccInfo.role, "ariaOwns": this._inputAccInfo && this._inputAccInfo.ariaOwns, "ariaExpanded": this._inputAccInfo && this._inputAccInfo.ariaExpanded, - "parentInfo": this._inputAccInfo && this._inputAccInfo.parentInfo, + "ariaDescription": this._inputAccInfo && this._inputAccInfo.ariaDescription, }, }; } From cf56bf0c0166a5c5ace358c8aa81e5a1ad2324b3 Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Mon, 28 Oct 2019 11:25:26 +0200 Subject: [PATCH 18/47] merge commit --- packages/main/src/Input.js | 16 ---------------- packages/main/src/themes/DatePicker.css | 3 --- 2 files changed, 19 deletions(-) diff --git a/packages/main/src/Input.js b/packages/main/src/Input.js index 9f978e2cab60..edcb1ef80661 100644 --- a/packages/main/src/Input.js +++ b/packages/main/src/Input.js @@ -590,21 +590,12 @@ class Input extends UI5Element { get suggestionsTextId() { return this.showSuggestions ? `${this._id}-suggestionsText` : ""; -<<<<<<< HEAD - } - - get valueStateTextId() { - return this.hasValueState ? `${this._id}-descr` : ""; - } - -======= } get valueStateTextId() { return this.hasValueState ? `${this._id}-valueStateDesc` : ""; } ->>>>>>> upstream/master get accInfo() { const ariaHasPopupDefault = this.showSuggestions ? "true" : undefined; const ariaAutoCompleteDefault = this.showSuggestions ? "list" : undefined; @@ -612,17 +603,10 @@ class Input extends UI5Element { "wrapper": { }, "input": { -<<<<<<< HEAD - "ariaDescribedBy": this._inputAccInfo ? `${this.suggestionsTextId} ${this.valueStateTextId} ${this._inputAccInfo.ariaDescribedBy}`.trim() : `${this.suggestionsTextId} ${this.valueStateTextId}`.trim(), - "ariaInvalid": this.valueState === ValueState.Error ? "true" : undefined, - "ariaHasPopup": this._inputAccInfo ? this._inputAccInfo.ariaHasPopup : ariaHasPopupDefault, - "ariaAutoComplete": this._inputAccInfo ? this._inputAccInfo.ariaAutoComplete : ariaAutoCompleteDefault, -======= "ariaDescribedBy": this._inputAccInfo.ariaDescribedBy ? `${this.suggestionsTextId} ${this.valueStateTextId} ${this._inputAccInfo.ariaDescribedBy}`.trim() : `${this.suggestionsTextId} ${this.valueStateTextId}`.trim(), "ariaInvalid": this.valueState === ValueState.Error ? "true" : undefined, "ariaHasPopup": this._inputAccInfo.ariaHasPopup ? this._inputAccInfo.ariaHasPopup : ariaHasPopupDefault, "ariaAutoComplete": this._inputAccInfo.ariaAutoComplete ? this._inputAccInfo.ariaAutoComplete : ariaAutoCompleteDefault, ->>>>>>> upstream/master "role": this._inputAccInfo && this._inputAccInfo.role, "ariaOwns": this._inputAccInfo && this._inputAccInfo.ariaOwns, "ariaExpanded": this._inputAccInfo && this._inputAccInfo.ariaExpanded, diff --git a/packages/main/src/themes/DatePicker.css b/packages/main/src/themes/DatePicker.css index 1cc7c600aafd..fe6e0fc97485 100644 --- a/packages/main/src/themes/DatePicker.css +++ b/packages/main/src/themes/DatePicker.css @@ -1,8 +1,5 @@ @import "./InvisibleTextStyles.css"; -<<<<<<< HEAD -======= @import "./InputIcon.css"; ->>>>>>> upstream/master :host(:not([hidden])) { display: inline-block; From 4e329fa188b3d513638803a05bfe1d19d19b1a1f Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Mon, 28 Oct 2019 14:57:25 +0200 Subject: [PATCH 19/47] fix(ui5-daypicker): Separating datepicker click handling to mousedown/up handlers(#872) --- packages/main/src/DayPicker.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/main/src/DayPicker.js b/packages/main/src/DayPicker.js index 66d71d8d7fb8..ff8a7abbe6d8 100644 --- a/packages/main/src/DayPicker.js +++ b/packages/main/src/DayPicker.js @@ -244,7 +244,7 @@ class DayPicker extends UI5Element { this._dayNames[0].classes += " ui5-dp-firstday"; } - onclick(event) { + onmousedown(event) { const target = getShadowDOMTarget(event); const dayPressed = this._isDayPressed(target); @@ -264,7 +264,13 @@ class DayPicker extends UI5Element { } } - this._modifySelectionAndNotifySubscribers(targetDate, event.ctrlKey); + this.targetDate = targetDate; + } + } + + onmouseup(event) { + if (this.targetDate) { + this._modifySelectionAndNotifySubscribers(this.targetDate, event.ctrlKey); } } From 49a4436f7699510157285a4bae92bd47f2b7e3dd Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Mon, 28 Oct 2019 16:49:35 +0200 Subject: [PATCH 20/47] On press between date cells the pop up no longer closes --- packages/main/src/DayPicker.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/main/src/DayPicker.js b/packages/main/src/DayPicker.js index ff8a7abbe6d8..08a50e81d7b9 100644 --- a/packages/main/src/DayPicker.js +++ b/packages/main/src/DayPicker.js @@ -271,6 +271,7 @@ class DayPicker extends UI5Element { onmouseup(event) { if (this.targetDate) { this._modifySelectionAndNotifySubscribers(this.targetDate, event.ctrlKey); + this.targetDate = null; } } From a35e96b7a4ed0c075824039c064d3f9cda5284ac Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Fri, 6 Dec 2019 13:59:28 +0200 Subject: [PATCH 21/47] feat(ui5-datepicker): implementing min and max date limits --- packages/main/src/Calendar.hbs | 6 ++ packages/main/src/Calendar.js | 40 +++++++++++ packages/main/src/DatePicker.hbs | 2 + packages/main/src/DatePicker.js | 89 +++++++++++++++++++++++- packages/main/src/DayPicker.js | 46 ++++++++++++ packages/main/src/MonthPicker.js | 40 +++++++++++ packages/main/src/YearPicker.js | 39 +++++++++++ packages/main/src/themes/DayPicker.css | 6 ++ packages/main/src/themes/MonthPicker.css | 6 ++ packages/main/src/themes/YearPicker.css | 6 ++ packages/main/test/pages/DatePicker.html | 11 ++- 11 files changed, 288 insertions(+), 3 deletions(-) diff --git a/packages/main/src/Calendar.hbs b/packages/main/src/Calendar.hbs index 779ac8dc8e00..e20f21be6601 100644 --- a/packages/main/src/Calendar.hbs +++ b/packages/main/src/Calendar.hbs @@ -19,6 +19,8 @@ .selectedDates="{{_oMonth.selectedDates}}" ._hidden="{{_oMonth._hidden}}" .primaryCalendarType="{{_oMonth.primaryCalendarType}}" + .minDate="{{_oMonth.minDate}}" + .maxDate="{{_oMonth.maxDate}}" timestamp="{{_oMonth.timestamp}}" @ui5-selectionChange="{{_oMonth.onSelectedDatesChange}}" @ui5-navigate="{{_oMonth.onNavigate}}" @@ -29,6 +31,8 @@ class="{{classes.monthPicker}}" ._hidden="{{_monthPicker._hidden}}" .primaryCalendarType="{{_oMonth.primaryCalendarType}}" + .minDate="{{_oMonth.minDate}}" + .maxDate="{{_oMonth.maxDate}}" timestamp="{{_monthPicker.timestamp}}" @ui5-selectedMonthChange="{{_monthPicker.onSelectedMonthChange}}" > @@ -38,6 +42,8 @@ class="{{classes.yearPicker}}" ._hidden="{{_yearPicker._hidden}}" .primaryCalendarType="{{_oMonth.primaryCalendarType}}" + .minDate="{{_oMonth.minDate}}" + .maxDate="{{_oMonth.maxDate}}" timestamp="{{_yearPicker.timestamp}}" ._selectedYear="{{_yearPicker._selectedYear}}" @ui5-selectedYearChange="{{_yearPicker.onSelectedYearChange}}" diff --git a/packages/main/src/Calendar.js b/packages/main/src/Calendar.js index 1faad0fdc480..d36a66a6080e 100644 --- a/packages/main/src/Calendar.js +++ b/packages/main/src/Calendar.js @@ -61,26 +61,56 @@ const metadata = { multiple: true, }, + /** + * Determines the мinimum date available for selection. + * + * @type {Object} + * @defaultvalue undefined + * @public + */ + minDate: { + type: Object, + defaultValue: undefined + }, + + /** + * Determines the maximum date available for selection. + * + * @type {Object} + * @defaultvalue undefined + * @public + */ + maxDate: { + type: Object, + defaultValue: undefined + }, + _header: { type: Object, }, + _oMonth: { type: Object, }, + _monthPicker: { type: Object, }, + _yearPicker: { type: Object, }, + _calendarWidth: { type: String, noAttribute: true, }, + _calendarHeight: { type: String, noAttribute: true, }, + formatPattern: { type: String, }, @@ -158,6 +188,8 @@ class Calendar extends UI5Element { this._oMonth.timestamp = this._timestamp; this._oMonth.selectedDates = [...this._selectedDates]; this._oMonth.primaryCalendarType = this._primaryCalendarType; + this._oMonth.minDate = this.minDate; + this._oMonth.maxDate = this.maxDate; this._header.monthText = this._oLocaleData.getMonths("wide", this._primaryCalendarType)[this._month]; this._header.yearText = oYearFormat.format(this._localDate); @@ -208,6 +240,14 @@ class Calendar extends UI5Element { return this.selectedDates || []; } + get _maxDate() { + return this.maxDate && new Date(this.maxDate); + } + + get _minDate() { + return this.minDate && new Date(this.minDate); + } + _handleSelectedDatesChange(event) { this.selectedDates = [...event.detail.dates]; diff --git a/packages/main/src/DatePicker.hbs b/packages/main/src/DatePicker.hbs index 12217d436f06..4c6b9fdb503b 100644 --- a/packages/main/src/DatePicker.hbs +++ b/packages/main/src/DatePicker.hbs @@ -49,6 +49,8 @@ format-pattern="{{_calendar.formatPattern}}" timestamp="{{_calendar.timestamp}}" .selectedDates="{{_calendar.selectedDates}}" + .minDate="{{_calendar.minDate}}" + .maxDate="{{_calendar.maxDate}}" @ui5-selectedDatesChange="{{_calendar.onSelectedDatesChange}}" > diff --git a/packages/main/src/DatePicker.js b/packages/main/src/DatePicker.js index 0ec17bcdfc76..adf3d9933f09 100644 --- a/packages/main/src/DatePicker.js +++ b/packages/main/src/DatePicker.js @@ -73,6 +73,30 @@ const metadata = { type: String, }, + /** + * Determines the мinimum date available for selection. + * + * @type {Object} + * @defaultvalue undefined + * @public + */ + minDate: { + type: Object, + defaultValue: undefined + }, + + /** + * Determines the maximum date available for selection. + * + * @type {Object} + * @defaultvalue undefined + * @public + */ + maxDate: { + type: Object, + defaultValue: undefined + }, + /** * Determines the calendar type. * The input value is formated according to the calendar type and the picker shows @@ -288,9 +312,21 @@ class DatePicker extends UI5Element { this._calendar = { onSelectedDatesChange: this._handleCalendarSelectedDatesChange.bind(this), - selectedDates: [], + selectedDates: [] }; + if (this.isValid(this.getAttribute("minDate"))) { + this.minDate = new Date(this.getAttribute("minDate")); + } else if (this.getAttribute("minDate")) { + console.warn(`In order for the "minDate" property to have effect, you should enter valid date format`); + } + + if (this.isValid(this.getAttribute("maxDate"))) { + this.maxDate = new Date(this.getAttribute("maxDate")); + } else if (this.getAttribute("maxDate")) { + console.warn(`In order for the "maxDate" property to have effect, you should enter valid date format`); + } + this.i18nBundle = getI18nBundle("@ui5/webcomponents"); } @@ -310,6 +346,14 @@ class DatePicker extends UI5Element { } else if (this.name) { console.warn(`In order for the "name" property to have effect, you should also: import "@ui5/webcomponents/dist/features/InputElementsFormSupport.js";`); // eslint-disable-line } + + if (this.minDate) { + this._calendar.minDate = this.minDate; + } + + if (this.maxDate) { + this._calendar.maxDate = this.maxDate; + } } _onkeydown(event) { @@ -326,9 +370,13 @@ class DatePicker extends UI5Element { _handleInputChange() { let nextValue = this._getInput().getInputValue(); const isValid = this.isValid(nextValue); + const isInValidRange = this.isInValidRange(nextValue); - if (isValid) { + if (isValid && isInValidRange) { nextValue = this.normalizeValue(nextValue); + this.valueState = ValueState.None; + } else { + this.valueState = ValueState.Error; } @@ -355,6 +403,35 @@ class DatePicker extends UI5Element { return !!(value && this.getFormat().parse(value)); } + /** + * Checks if a date is in range between minimum and maximum date + * @param {object} value + * @public + */ + isInValidRange(value = "") { + let pickedDate = new Date(value), + minDate = this.minDate, + maxDate = this.maxDate; + + if(minDate && maxDate){ + if(minDate <= pickedDate && maxDate >= pickedDate){ + return true; + } + } else if (minDate && !maxDate) { + if (minDate <= pickedDate) { + return true; + } + } else if (maxDate && !minDate) { + if (maxDate >= pickedDate) { + return true; + } + } else if (!maxDate && !minDate) { + return true; + } + + return false; + } + // because the parser understands more than one format // but we need values in one format normalizeValue(sValue) { @@ -424,6 +501,14 @@ class DatePicker extends UI5Element { }; } + get _maxDate() { + return this.maxDate && new Date(this.maxDate); + } + + get _minDate() { + return this.minDate && new Date(this.minDate); + } + get openIconTitle() { return this.i18nBundle.getText(DATEPICKER_OPEN_ICON_TITLE); } diff --git a/packages/main/src/DayPicker.js b/packages/main/src/DayPicker.js index 08a50e81d7b9..4ae3709c02bc 100644 --- a/packages/main/src/DayPicker.js +++ b/packages/main/src/DayPicker.js @@ -52,6 +52,30 @@ const metadata = { multiple: true, }, + /** + * Determines the мinimum date available for selection. + * + * @type {Object} + * @defaultvalue undefined + * @public + */ + minDate: { + type: Object, + defaultValue: undefined + }, + + /** + * Determines the maximum date available for selection. + * + * @type {Object} + * @defaultvalue undefined + * @public + */ + maxDate: { + type: Object, + defaultValue: undefined + }, + _weeks: { type: Object, multiple: true, @@ -204,6 +228,10 @@ class DayPicker extends UI5Element { day.classes += " ui5-dp-item--weeekend"; } + if ((this.minDate || this.maxDate) && this._isOutOfSelectableRange(oCalDate)){ + day.classes += " ui5-dp-item--disabled" + } + if (day.classes.indexOf("ui5-dp-wday6") !== -1 || _aVisibleDays.length - 1 === i) { this._weeks.push(week); @@ -388,6 +416,24 @@ class DayPicker extends UI5Element { return (target.className.indexOf("ui5-dp-item") > -1) || (targetParent && target.parentNode.classList.contains("ui5-dp-item")); } + _isOutOfSelectableRange (date){ + let currentDate = date._oUDate.oDate, + maxDate = this.maxDate, + minDate = this.minDate; + + if (maxDate){ + maxDate.setHours(0); + } + + if (minDate){ + minDate.setHours(0); + } + + currentDate.setHours(0); + + return currentDate > maxDate || currentDate < minDate; + } + _getVisibleDays(oStartDate, bIncludeBCDates) { let oCalDate, iDaysOldMonth, diff --git a/packages/main/src/MonthPicker.js b/packages/main/src/MonthPicker.js index a167fb3a0242..86bc9e370fbd 100644 --- a/packages/main/src/MonthPicker.js +++ b/packages/main/src/MonthPicker.js @@ -28,6 +28,7 @@ const metadata = { timestamp: { type: Integer, }, + /** * Sets a calendar type used for display. * If not set, the calendar type of the global configuration is used. @@ -37,14 +38,41 @@ const metadata = { primaryCalendarType: { type: CalendarType, }, + + /** + * Determines the мinimum date available for selection. + * + * @type {Object} + * @defaultvalue undefined + * @public + */ + minDate: { + type: Object, + defaultValue: undefined + }, + + /** + * Determines the maximum date available for selection. + * + * @type {Object} + * @defaultvalue undefined + * @public + */ + maxDate: { + type: Object, + defaultValue: undefined + }, + _quarters: { type: Object, multiple: true, }, + _hidden: { type: Boolean, noAttribute: true, }, + }, events: /** @lends sap.ui.webcomponents.main.MonthPicker.prototype */ { /** @@ -122,6 +150,10 @@ class MonthPicker extends UI5Element { month.classes += " ui5-mp-item--selected"; } + if ((this.minDate || this.maxDate) && this._isOutOfSelectableRange(i)){ + month.classes += " ui5-mp-item--disabled"; + } + const quarterIndex = parseInt(i / 3); if (quarters[quarterIndex]) { @@ -184,6 +216,14 @@ class MonthPicker extends UI5Element { } } + _isOutOfSelectableRange (monthIndex){ + let currentDateYear = this._localDate.getFullYear(), + minDateCheck = this.minDate && (currentDateYear <= this.minDate.getFullYear() && monthIndex < this.minDate.getMonth()), + maxDateCheck = this.maxDate && (currentDateYear >= this.maxDate.getFullYear() && monthIndex > this.maxDate.getMonth()); + + return maxDateCheck || minDateCheck; + } + getTimestampFromDOM(domNode) { const oMonthDomRef = domNode.getAttribute("data-sap-timestamp"); return parseInt(oMonthDomRef); diff --git a/packages/main/src/YearPicker.js b/packages/main/src/YearPicker.js index 25f3aaf7ecc7..169cdeefa937 100644 --- a/packages/main/src/YearPicker.js +++ b/packages/main/src/YearPicker.js @@ -30,6 +30,7 @@ const metadata = { timestamp: { type: Integer, }, + /** * Sets a calendar type used for display. * If not set, the calendar type of the global configuration is used. @@ -39,14 +40,41 @@ const metadata = { primaryCalendarType: { type: CalendarType, }, + + /** + * Determines the мinimum date available for selection. + * + * @type {Object} + * @defaultvalue undefined + * @public + */ + minDate: { + type: Object, + defaultValue: undefined + }, + + /** + * Determines the maximum date available for selection. + * + * @type {Object} + * @defaultvalue undefined + * @public + */ + maxDate: { + type: Object, + defaultValue: undefined + }, + _selectedYear: { type: Integer, noAttribute: true, }, + _yearIntervals: { type: Object, multiple: true, }, + _hidden: { type: Boolean, noAttribute: true, @@ -151,6 +179,10 @@ class YearPicker extends UI5Element { year.classes += " ui5-yp-item--selected"; } + if ((this.minDate || this.maxDate) && this._isOutOfSelectableRange(oCalDate.getYear())) { + year.classes += " ui5-yp-item--disabled"; + } + if (intervals[intervalIndex]) { intervals[intervalIndex].push(year); } @@ -256,6 +288,13 @@ class YearPicker extends UI5Element { this.timestamp = oCalDate.valueOf() / 1000; } + _isOutOfSelectableRange (year){ + const minDateCheck = this.minDate && year < this.minDate.getFullYear(), + maxDateCheck = this.maxDate && year > this.maxDate.getFullYear(); + + return minDateCheck || maxDateCheck; + } + get styles() { return { main: { diff --git a/packages/main/src/themes/DayPicker.css b/packages/main/src/themes/DayPicker.css index 30b53ac97749..5f0e99d77a8b 100644 --- a/packages/main/src/themes/DayPicker.css +++ b/packages/main/src/themes/DayPicker.css @@ -84,6 +84,12 @@ background: var(--_ui5_daypicker_item_weekend_background_color); } +.ui5-dp-item.ui5-dp-item--disabled { + background: darkgray; + pointer-events: none; + color: var(--sapUiBaseText); +} + .ui5-dp-item.ui5-dp-item--weeekend:hover { background: var(--_ui5_daypicker_item_weekend_hover_background_color); } diff --git a/packages/main/src/themes/MonthPicker.css b/packages/main/src/themes/MonthPicker.css index d77a65ee65e1..98d62bd5cb21 100644 --- a/packages/main/src/themes/MonthPicker.css +++ b/packages/main/src/themes/MonthPicker.css @@ -47,6 +47,12 @@ color: var(--sapUiContentContrastTextColor); } +.ui5-mp-item.ui5-mp-item--disabled { + background: darkgray; + pointer-events: none; + color: var(--sapUiBaseText); +} + .ui5-mp-item.ui5-mp-item--selected:focus { background-color: var(--_ui5_monthpicker_item_selected_focus); } diff --git a/packages/main/src/themes/YearPicker.css b/packages/main/src/themes/YearPicker.css index 6bfacb015b2a..7b2b3de83536 100644 --- a/packages/main/src/themes/YearPicker.css +++ b/packages/main/src/themes/YearPicker.css @@ -62,6 +62,12 @@ color: var(--sapUiContentContrastTextColor); } +.ui5-yp-item.ui5-yp-item--disabled { + background: darkgray; + pointer-events: none; + color: var(--sapUiBaseText); +} + .ui5-yp-item.ui5-yp-item--selected:focus { background-color: var(--_ui5_yearpicker_item_selected_focus); } diff --git a/packages/main/test/pages/DatePicker.html b/packages/main/test/pages/DatePicker.html index e0baca353bb6..79530e70b80c 100644 --- a/packages/main/test/pages/DatePicker.html +++ b/packages/main/test/pages/DatePicker.html @@ -80,7 +80,16 @@

japanese calendar type

explicitly set empty placeholder

- + + +

Date picker with min and max date 1/1/2000 - 1/1/2100

+ + +

Date picker with only min date 1/1/2000

+ + +

Date picker with only max date date 1/1/2100

+ - + \ No newline at end of file diff --git a/packages/main/test/pages/DayPicker.html b/packages/main/test/pages/DayPicker.html index 4f6c19a9d948..a8891207ff40 100644 --- a/packages/main/test/pages/DayPicker.html +++ b/packages/main/test/pages/DayPicker.html @@ -29,6 +29,7 @@ - + + diff --git a/packages/main/test/pages/Select.html b/packages/main/test/pages/Select.html index 58568cc0b286..3c659b662dc8 100644 --- a/packages/main/test/pages/Select.html +++ b/packages/main/test/pages/Select.html @@ -158,4 +158,4 @@

Change event counter holder

}); - + \ No newline at end of file diff --git a/packages/main/test/specs/ComboBox.spec.js b/packages/main/test/specs/ComboBox.spec.js index ceb1cc82366e..b220ee942d84 100644 --- a/packages/main/test/specs/ComboBox.spec.js +++ b/packages/main/test/specs/ComboBox.spec.js @@ -7,13 +7,14 @@ describe("General interaction", () => { const combo = $("#combo"); const arrow = combo.shadow$("[input-icon]"); - const popover = combo.shadow$(".ui5-combobox-popover"); + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#combo"); + const popover = browser.$(`.${staticAreaItemClassName}`).shadow$("ui5-popover"); - assert.ok(!popover.isDisplayedInViewport(), "Popover should not be displayed") + assert.ok(!popover.getProperty("opened"), "Popover should not be displayed") arrow.click(); - assert.ok(popover.isDisplayedInViewport(), "Popover should be displayed") + assert.ok(popover.getProperty("opened"), "Popover should be displayed") }); it ("Should open the popover when typing a value", () => { @@ -22,13 +23,14 @@ describe("General interaction", () => { const combo = $("#combo"); const lazy = $("#lazy"); const input = combo.shadow$("#ui5-combobox-input"); - const popover = combo.shadow$(".ui5-combobox-popover"); - const listItems = combo.shadow$(".ui5-combobox-popover").$("ui5-list").$$("ui5-li"); + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#combo"); + const popover = browser.$(`.${staticAreaItemClassName}`).shadow$("ui5-popover"); + const listItems = popover.$("ui5-list").$$("ui5-li"); input.click(); input.keys("b"); - assert.ok(popover.isDisplayedInViewport(), "Popover should be displayed"); + assert.ok(popover.getProperty("opened"), "Popover should be displayed"); assert.strictEqual(input.getProperty("value"), "Bahrain", "Value should be Bahrain"); @@ -51,18 +53,20 @@ describe("General interaction", () => { const combo = $("#combo2"); const arrow = combo.shadow$("[input-icon]"); const input = combo.shadow$("#ui5-combobox-input"); - let listItems = combo.shadow$(".ui5-combobox-popover").$("ui5-list").$$("ui5-li"); + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#combo2"); + const popover = browser.$(`.${staticAreaItemClassName}`).shadow$("ui5-popover"); + let listItems = popover.$("ui5-list").$$("ui5-li"); arrow.click(); assert.strictEqual(listItems.length, 11, "Items should be 11"); input.keys("a"); - listItems = combo.shadow$(".ui5-combobox-popover").$("ui5-list").$$("ui5-li"); + listItems = popover.$("ui5-list").$$("ui5-li"); assert.strictEqual(listItems.length, 5, "Items should be 5"); input.keys("u"); - listItems = combo.shadow$(".ui5-combobox-popover").$("ui5-list").$$("ui5-li"); + listItems = popover.$("ui5-list").$$("ui5-li"); assert.strictEqual(listItems.length, 2, "Items should be 2"); }); @@ -106,7 +110,9 @@ describe("General interaction", () => { arrow.click(); // click on first item - combo.shadow$(".ui5-combobox-popover").$("ui5-list").$$("ui5-li")[0].click(); + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#change-cb"); + const popover = browser.$(`.${staticAreaItemClassName}`).shadow$("ui5-popover"); + popover.$("ui5-list").$$("ui5-li")[0].click(); assert.strictEqual(placeholder.getText(), "Argentina", "Text should be empty"); assert.strictEqual(counter.getText(), "1", "Call count should be 1"); @@ -116,22 +122,24 @@ describe("General interaction", () => { const combo = $("#contains-cb"); const input = combo.shadow$("#ui5-combobox-input"); const arrow = combo.shadow$("[input-icon]"); - let listItems = combo.shadow$(".ui5-combobox-popover").$("ui5-list").$$("ui5-li"); + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#contains-cb"); + const popover = browser.$(`.${staticAreaItemClassName}`).shadow$("ui5-popover"); + let listItems = popover.$("ui5-list").$$("ui5-li"); arrow.click(); assert.strictEqual(listItems.length, 4, "Items should be 4"); input.keys("n"); - listItems = combo.shadow$(".ui5-combobox-popover").$("ui5-list").$$("ui5-li"); + listItems = popover.$("ui5-list").$$("ui5-li"); assert.strictEqual(listItems.length, 3, "Items should be 3"); input.keys("a"); - listItems = combo.shadow$(".ui5-combobox-popover").$("ui5-list").$$("ui5-li"); + listItems = popover.$("ui5-list").$$("ui5-li"); assert.strictEqual(listItems.length, 2, "Items should be 2"); input.keys("d"); - listItems = combo.shadow$(".ui5-combobox-popover").$("ui5-list").$$("ui5-li"); + listItems = popover.$("ui5-list").$$("ui5-li"); assert.strictEqual(listItems.length, 1, "Items should be 1"); assert.strictEqual(listItems[0].getText(), "Canada"); }); @@ -140,19 +148,21 @@ describe("General interaction", () => { const combo = $("#startswith-cb"); const input = combo.shadow$("#ui5-combobox-input"); const arrow = combo.shadow$("[input-icon]"); - let listItems = combo.shadow$(".ui5-combobox-popover").$("ui5-list").$$("ui5-li"); + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#startswith-cb"); + const popover = browser.$(`.${staticAreaItemClassName}`).shadow$("ui5-popover"); + let listItems = popover.$("ui5-list").$$("ui5-li"); arrow.click(); assert.strictEqual(listItems.length, 4, "Items should be 4"); input.keys("a"); - listItems = combo.shadow$(".ui5-combobox-popover").$("ui5-list").$$("ui5-li"); + listItems = popover.$("ui5-list").$$("ui5-li"); assert.strictEqual(listItems.length, 1, "Items should be 1"); assert.strictEqual(listItems[0].getText(), "Argentina"); input.keys("a"); - listItems = combo.shadow$(".ui5-combobox-popover").$("ui5-list").$$("ui5-li"); + listItems = popover.$("ui5-list").$$("ui5-li"); assert.strictEqual(listItems.length, 0, "Items should be 0"); }); }); \ No newline at end of file diff --git a/packages/main/test/specs/DatePicker-fg.spec.js b/packages/main/test/specs/DatePicker-fg.spec.js index 8586572adec5..082f6b51e197 100644 --- a/packages/main/test/specs/DatePicker-fg.spec.js +++ b/packages/main/test/specs/DatePicker-fg.spec.js @@ -5,28 +5,29 @@ describe('Date Picker Field Glass modifications', () => { it('direct usage for comparison', () => { browser.url('http://localhost:8080/test-resources/pages/DatePicker_fg.html'); - let popoverContent = browser.$("#ui5-datepicker--startDate").shadow$("ui5-popover") - assert.ok(!popoverContent.isDisplayedInViewport(), "popover is initially hidden"); + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#ui5-datepicker--startDate"); + let popoverContent = browser.$(`.${staticAreaItemClassName}`).shadow$("ui5-popover") + assert.ok(!popoverContent.getProperty("opened"), "popover is initially hidden"); const innerInput = browser.$("#ui5-datepicker--startDate").shadow$("ui5-input").shadow$("input"); innerInput.click(); - assert.ok(popoverContent.isDisplayedInViewport(), "popover is visible"); + assert.ok(popoverContent.getProperty("opened"), "popover is visible"); innerInput.keys("Tab"); const dpEnd = browser.$("#ui5-datepicker--endDate"); - assert.ok(!popoverContent.isDisplayedInViewport(), "popover is hidden"); + assert.ok(!popoverContent.getProperty("opened"), "popover is hidden"); assert.ok(dpEnd.isFocused(), "focus is on end date"); }); it('Input click and tab out', () => { DatePickerFGPage.open(); - assert.ok(!DatePickerFGPage.startPopoverContent.isDisplayedInViewport(), "popover is initially hidden"); + assert.ok(!DatePickerFGPage.startPopoverContent.getProperty("opened"), "popover is initially hidden"); DatePickerFGPage.startInnerInput.click(); - assert.ok(DatePickerFGPage.startPopoverContent.isDisplayedInViewport(), "popover is visible after click"); + assert.ok(DatePickerFGPage.startPopoverContent.getProperty("opened"), "popover is visible after click"); DatePickerFGPage.startInnerInput.keys("Tab"); - assert.ok(!DatePickerFGPage.startPopoverContent.isDisplayedInViewport(), "popover is hidden after tab out"); + assert.ok(!DatePickerFGPage.startPopoverContent.getProperty("opened"), "popover is hidden after tab out"); assert.ok(DatePickerFGPage.dpEnd.isFocused(), "focus is on end date"); }); }); diff --git a/packages/main/test/specs/DayPicker.spec.js b/packages/main/test/specs/DayPicker.spec.js index 86de14cd232a..63346ea35823 100644 --- a/packages/main/test/specs/DayPicker.spec.js +++ b/packages/main/test/specs/DayPicker.spec.js @@ -4,29 +4,43 @@ const assert = require("chai").assert; describe("Day Picker Tests", () => { browser.url("http://localhost:8080/test-resources/pages/DayPicker.html"); - beforeEach(() => { - browser.execute(() => { - document.getElementById("daypicker").openPicker(); - }); - }); - it("Day Picker Renders", () => { daypicker.id = "daypicker"; const DayPicker = daypicker.dayPickerRoot; - + assert.ok(DayPicker, "Day Picker is rendered"); }); - + it("Select day with Space", () => { - browser.keys("Space"); // The initial focus is on th current date + const today = browser.$(`#${daypicker._sut}`).shadow$(".ui5-dp-item--now"); + + today.click(); + today.keys("ArrowRight"); + browser.keys("Space"); + + const selectedDate = browser.execute( () => { + const timestamp = parseInt(document.activeElement.shadowRoot.activeElement.getAttribute("data-sap-timestamp")); - assert.isOk(daypicker.currentDate, new Date().getDate(), "Dates are equal"); + return new Date(timestamp * 1000).getDate(); + }); + + assert.strictEqual(selectedDate, new Date(Date.now() + 24 * 3600 * 1000).getDate(), "Dates are equal"); }); it("Select day with Enter", () => { - browser.keys("ArrowRight"); + daypicker.id = "daypicker1"; + const today = browser.$(`#${daypicker._sut}`).shadow$(".ui5-dp-item--now"); + + today.click(); + today.keys("ArrowRight"); browser.keys("Enter"); - assert.strictEqual(daypicker.currentDate, new Date(Date.now() + 24 * 3600 * 1000).getDate(), "Dates are equal"); // Tomorrow should be selected + const selectedDate = browser.execute( () => { + const timestamp = parseInt(document.activeElement.shadowRoot.activeElement.getAttribute("data-sap-timestamp")); + + return new Date(timestamp * 1000).getDate(); + }); + + assert.strictEqual(selectedDate, new Date(Date.now() + 24 * 3600 * 1000).getDate(), "Dates are equal"); }); }); diff --git a/packages/main/test/specs/Input.spec.js b/packages/main/test/specs/Input.spec.js index 281bc0ef3b73..29bb6e84ef71 100644 --- a/packages/main/test/specs/Input.spec.js +++ b/packages/main/test/specs/Input.spec.js @@ -57,11 +57,13 @@ describe("Input general interaction", () => { it("Should open suggestions popover when focused", () => { const input = $("#myInput2"); + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#myInput2") + const popover = browser.$(`.${staticAreaItemClassName}`).shadow$("ui5-popover"); // focus the input field which will display the suggestions input.click(); - assert.ok(input.shadow$("ui5-popover").isDisplayedInViewport(), "The popover is visible"); + assert.ok(popover.isDisplayedInViewport(), "The popover is visible"); }); it("fires change", () => { @@ -132,7 +134,8 @@ describe("Input general interaction", () => { let item; const suggestionsInput = $("#myInput").shadow$("input"); const inputResult = $("#inputResult").shadow$("input"); - const popover = $("#myInput").shadow$("ui5-popover"); + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#myInput") + const popover = browser.$(`.${staticAreaItemClassName}`).shadow$("ui5-popover"); suggestionsInput.click(); suggestionsInput.keys("p"); diff --git a/packages/main/test/specs/MultiComboBox.spec.js b/packages/main/test/specs/MultiComboBox.spec.js index 209552adadd3..4e59be8b196c 100644 --- a/packages/main/test/specs/MultiComboBox.spec.js +++ b/packages/main/test/specs/MultiComboBox.spec.js @@ -6,7 +6,8 @@ describe("MultiComboBox general interaction", () => { describe("toggling", () => { it("opens/closes", () => { const icon = browser.$("#multi1").shadow$("[input-icon]"); - const popover = browser.$("#multi1").shadow$(".ui5-multi-combobox-all-items-popover"); + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#multi1") + const popover = browser.$(`.${staticAreaItemClassName}`).shadow$(".ui5-multi-combobox-all-items-popover"); icon.click(); assert.ok(popover.getProperty("opened"), "Popover should be displayed in the viewport"); @@ -42,9 +43,10 @@ describe("MultiComboBox general interaction", () => { it("Opens all items popover, selects and deselects the first item", () => { const icon = browser.$("#mcb").shadow$("[input-icon]"); - const popover = browser.$("#mcb").shadow$(".ui5-multi-combobox-all-items-popover"); - const firstItem = browser.$("#first-item"); - const firstItemCheckbox = browser.$("#mcb").shadow$(".ui5-multi-combobox-all-items-list > ui5-li").shadow$("ui5-checkbox"); + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#mcb") + const popover = browser.$(`.${staticAreaItemClassName}`).shadow$(".ui5-multi-combobox-all-items-popover"); + const firstItem = popover.$("ui5-list > ui5-li"); + const firstItemCheckbox = firstItem.shadow$("ui5-checkbox"); const eventInput = $("#events-input"); const paramsInput = $("#events-parameters"); const callCountInput = $("#events-call-count"); @@ -74,16 +76,15 @@ describe("MultiComboBox general interaction", () => { it("Opens all items popover when start typing and filters items", () => { const input = browser.$("#mcb").shadow$("#ui5-multi-combobox-input"); - const popover = browser.$("#mcb").shadow$(".ui5-multi-combobox-all-items-popover"); + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#mcb") + const popover = browser.$(`.${staticAreaItemClassName}`).shadow$(".ui5-multi-combobox-all-items-popover"); input.click(); input.keys("c"); - const list = browser.$("#mcb").shadow$(".ui5-multi-combobox-all-items-list"); + const list = popover.$(".ui5-multi-combobox-all-items-list"); assert.ok(popover.getProperty("opened"), "Popover should be displayed in the viewport"); - - assert.strictEqual(list.getProperty("items").length, 3, "3 items should be shown"); input.keys("o"); @@ -96,7 +97,7 @@ describe("MultiComboBox general interaction", () => { input.keys("Backspace"); - assert.strictEqual(list.getProperty("items").length, 3, "1 items should be shown"); + assert.strictEqual(list.getProperty("items").length, 3, "3 items should be shown"); }); it("tests built in validation by typing a non existing option", () => { @@ -121,8 +122,9 @@ describe("MultiComboBox general interaction", () => { it("When item is clicked, the popover should be closed and the value in the input should be removed", () => { const input = browser.$("#another-mcb").shadow$("#ui5-multi-combobox-input"); - const popover = browser.$("#another-mcb").shadow$(".ui5-multi-combobox-all-items-popover"); - const firstItem = browser.$("#another-mcb").shadow$(".ui5-multi-combobox-all-items-list > ui5-li"); + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#another-mcb") + const popover = browser.$(`.${staticAreaItemClassName}`).shadow$(".ui5-multi-combobox-all-items-popover"); + const firstItem = popover.$(".ui5-multi-combobox-all-items-list > ui5-li"); input.click(); input.keys("c"); @@ -138,8 +140,9 @@ describe("MultiComboBox general interaction", () => { it("When item's checkbox is clicked, the popover should not be closed and the value in the input should be kept", () => { const input = browser.$("#another-mcb").shadow$("#ui5-multi-combobox-input"); - const popover = browser.$("#another-mcb").shadow$(".ui5-multi-combobox-all-items-popover"); - const firstItemCheckbox = browser.$("#another-mcb").shadow$(".ui5-multi-combobox-all-items-list > ui5-li").shadow$("ui5-checkbox"); + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#another-mcb") + const popover = browser.$(`.${staticAreaItemClassName}`).shadow$(".ui5-multi-combobox-all-items-popover"); + const firstItemCheckbox = popover.$(".ui5-multi-combobox-all-items-list > ui5-li").shadow$("ui5-checkbox"); input.click(); input.keys("c"); diff --git a/packages/main/test/specs/Popover.spec.js b/packages/main/test/specs/Popover.spec.js index a75c72d614ad..0fef5172b3f8 100644 --- a/packages/main/test/specs/Popover.spec.js +++ b/packages/main/test/specs/Popover.spec.js @@ -59,7 +59,8 @@ describe("Popover general interaction", () => { it("tests if overflown content can be reached by scrolling", () => { const manyItemsSelect = $("#many-items"); - const items = manyItemsSelect.shadow$$("ui5-li"); + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#many-items") + const items = browser.$(`.${staticAreaItemClassName}`).shadow$$("ui5-li"); manyItemsSelect.click(); diff --git a/packages/main/test/specs/Select.spec.js b/packages/main/test/specs/Select.spec.js index 17caa53e5944..01238404499a 100644 --- a/packages/main/test/specs/Select.spec.js +++ b/packages/main/test/specs/Select.spec.js @@ -10,8 +10,8 @@ describe("Select general interaction", () => { const EXPECTED_SELECTION_TEXT = "Cozy"; select.click(); - - const firstItem = browser.$("#mySelect").shadow$$("ui5-li")[0]; + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#mySelect") + const firstItem = browser.$(`.${staticAreaItemClassName}`).shadow$$("ui5-li")[0]; firstItem.click(); @@ -25,7 +25,8 @@ describe("Select general interaction", () => { select.click(); - const firstItem = browser.$("#mySelect").shadow$("ui5-li:first-child"); + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#mySelect") + const firstItem = browser.$(`.${staticAreaItemClassName}`).shadow$("ui5-li:first-child"); firstItem.click(); assert.strictEqual(inputResult.getProperty("value"), "1", "Event not fired when already selected item is selected"); @@ -87,7 +88,6 @@ describe("Select general interaction", () => { // Close the select not to cover other components that tests would try to click select.keys("Escape"); - }); it("tests selection does not cycle with ArrowUp", () => { @@ -108,55 +108,59 @@ describe("Select general interaction", () => { it("opens upon space", () => { const btn = $("#myBtn2"); - const popover = browser.$("#mySelect").shadow$("ui5-popover"); + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#mySelect"); + const popover = browser.$(`.${staticAreaItemClassName}`).shadow$("ui5-popover"); btn.click(); btn.keys("Tab"); browser.keys("Space"); - assert.ok(popover.isDisplayedInViewport(), "Select is opened."); + assert.ok(popover.getProperty("opened"), "Select is opened."); }); it("toggles upon F4", () => { const btn = $("#myBtn2"); - const popover = browser.$("#mySelect").shadow$("ui5-popover"); + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#mySelect") + const popover = browser.$(`.${staticAreaItemClassName}`).shadow$("ui5-popover"); btn.click(); btn.keys("Tab"); browser.keys("F4"); - assert.ok(popover.isDisplayedInViewport(), "Select is opened."); + assert.ok(popover.getProperty("opened"), "Select is opened."); browser.keys("F4"); - assert.ok(!popover.isDisplayedInViewport(), "Select is closed."); + assert.ok(!popover.getProperty("opened"), "Select is closed."); }); it("toggles upon ALT + UP", () => { const btn = $("#myBtn2"); - const popover = browser.$("#mySelect").shadow$("ui5-popover"); + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#mySelect") + const popover = browser.$(`.${staticAreaItemClassName}`).shadow$("ui5-popover"); btn.click(); btn.keys("Tab"); browser.keys(["Alt", "ArrowUp", "NULL"]); - assert.ok(popover.isDisplayedInViewport(), "Select is opened."); + assert.ok(popover.getProperty("opened"), "Select is opened."); browser.keys(["Alt", "ArrowUp", "NULL"]); - assert.ok(!popover.isDisplayedInViewport(), "Select is closed."); + assert.ok(!popover.getProperty("opened"), "Select is closed."); }); it("toggles upon ALT + DOWN", () => { const btn = $("#myBtn2"); - const popover = browser.$("#mySelect").shadow$("ui5-popover"); + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#mySelect") + const popover = browser.$(`.${staticAreaItemClassName}`).shadow$("ui5-popover"); btn.click(); btn.keys("Tab"); browser.keys(["Alt", "ArrowDown", "NULL"]); - assert.ok(popover.isDisplayedInViewport(), "Select is opened."); + assert.ok(popover.getProperty("opened"), "Select is opened."); browser.keys(["Alt", "ArrowDown", "NULL"]); - assert.ok(!popover.isDisplayedInViewport(), "Select is closed."); + assert.ok(!popover.getProperty("opened"), "Select is closed."); }); it("adds unselected only items to select", () => { @@ -166,7 +170,8 @@ describe("Select general interaction", () => { addItemsBtn.click(); const firstOption = browser.$("#mySelect ui5-option:first-child"); - const firstListItem = browser.$("#mySelect").shadow$("ui5-li:first-child"); + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#mySelect"); + const firstListItem = browser.$(`.${staticAreaItemClassName}`).shadow$("ui5-li:first-child"); assert.ok(firstOption.getProperty("selected"), "First option should be selected"); assert.ok(firstListItem.getProperty("selected"), "First list item should be selected"); @@ -216,7 +221,8 @@ describe("Select general interaction", () => { select.keys("Escape"); select.click(); - const firstItem = browser.$("#mySelect").shadow$("ui5-li:first-child"); + const staticAreaItemClassName = browser.getStaticAreaItemClassName("#mySelect"); + const firstItem = browser.$(`.${staticAreaItemClassName}`).shadow$("ui5-li:first-child"); firstItem.click(); diff --git a/packages/tools/components-package/wdio.js b/packages/tools/components-package/wdio.js index 5c1289b87f45..c5f595e55c11 100644 --- a/packages/tools/components-package/wdio.js +++ b/packages/tools/components-package/wdio.js @@ -228,6 +228,12 @@ exports.config = { return elem.classList.contains(className); }, this, className); }, true); + + browser.addCommand("getStaticAreaItemClassName", function(selector) { + return browser.execute((selector) => { + return document.querySelector(selector).getStaticAreaItemDomRef().host.classList[0]; + }, selector); + }, false); }, /** * Runs before a WebdriverIO command gets executed. From 3b2204ad3fd15e591181760e4722f65fa56bc257 Mon Sep 17 00:00:00 2001 From: Tsanislav Gatev Date: Fri, 6 Dec 2019 13:59:28 +0200 Subject: [PATCH 32/47] feat(ui5-datepicker): implementing min and max date limits --- packages/main/test/pages/DatePicker.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/main/test/pages/DatePicker.html b/packages/main/test/pages/DatePicker.html index 6f7aa809d459..f6ea718c6646 100644 --- a/packages/main/test/pages/DatePicker.html +++ b/packages/main/test/pages/DatePicker.html @@ -81,14 +81,14 @@

japanese calendar type

explicitly set empty placeholder

-

Date picker with min and max date 9/1/2019 - 11/1/2019

- +

Date picker with min and max date 1/1/2000 - 1/1/2100

+

Date picker with only min date 1/1/2000

- +

Date picker with only max date date 1/1/2100

- +