@qooxdoo/framework 7.0.0-beta → 7.0.0-beta.4

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.
Files changed (224) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/Manifest.json +11 -8
  3. package/bin/deploy/qx +0 -0
  4. package/lib/compiler/compile-info.json +86 -96
  5. package/lib/compiler/index.js +35547 -47284
  6. package/{source/class/qx/tool/compiler/targets → lib/resource/qx/tool/cli/templates}/TypeScriptWriter-base_declaration.txt +0 -0
  7. package/lib/resource/qx/tool/cli/templates/loader/loader-browser.tmpl.js +8 -2
  8. package/lib/resource/qx/tool/cli/templates/loader/loader-node.tmpl.js +24 -11
  9. package/lib/resource/qx/tool/cli/templates/loader/loader-rhino.tmpl.js +9 -2
  10. package/lib/resource/qx/tool/cli/templates/skeleton/mobile/source/theme/custom/css/custom.css +1 -1
  11. package/lib/resource/qx/tool/cli/templates/skeleton/mobile/source/theme/custom/css/custom.css.map +1 -44
  12. package/lib/resource/qx/tool/cli/templates/template_vars.js +1 -1
  13. package/lib/resource/qx/tool/loadsass.js +13 -0
  14. package/lib/resource/qx/tool/schema/Manifest-1-0-0.json +1 -2
  15. package/lib/resource/qx/tool/schema/Manifest-2-0-0.json +1 -2
  16. package/lib/resource/qx/tool/schema/compile-1-0-0.json +19 -9
  17. package/lib/resource/qx/tool/website/sass/qooxdoo.css +1 -1
  18. package/lib/resource/qx/tool/website/sass/qooxdoo.css.map +1 -9
  19. package/package.json +14 -14
  20. package/source/class/qx/Annotation.js +2 -2
  21. package/source/class/qx/Class.js +20 -4
  22. package/source/class/qx/Interface.js +6 -0
  23. package/source/class/qx/Promise.js +32 -2
  24. package/source/class/qx/bom/Element.js +1 -0
  25. package/source/class/qx/bom/Font.js +17 -2
  26. package/source/class/qx/bom/Iframe.js +10 -5
  27. package/source/class/qx/bom/Label.js +2 -1
  28. package/source/class/qx/bom/Template.js +2 -0
  29. package/source/class/qx/bom/client/Browser.js +11 -2
  30. package/source/class/qx/bom/client/OperatingSystem.js +16 -0
  31. package/source/class/qx/bom/element/Decoration.js +8 -5
  32. package/source/class/qx/bom/element/Dimension.js +46 -0
  33. package/source/class/qx/bom/webfonts/WebFont.js +10 -0
  34. package/source/class/qx/core/BaseInit.js +9 -3
  35. package/source/class/qx/core/Environment.js +1 -0
  36. package/source/class/qx/core/Property.js +2 -2
  37. package/source/class/qx/data/SingleValueBinding.js +6 -3
  38. package/source/class/qx/data/controller/CheckedList.js +18 -9
  39. package/source/class/qx/data/controller/List.js +8 -0
  40. package/source/class/qx/dev/unit/Sinon.js +1 -1
  41. package/source/class/qx/event/Utils.js +1 -1
  42. package/source/class/qx/event/handler/DragDrop.js +1 -1
  43. package/source/class/qx/event/handler/Gesture.js +3 -1
  44. package/source/class/qx/event/handler/Mouse.js +61 -22
  45. package/source/class/qx/event/handler/Video.js +111 -0
  46. package/source/class/qx/html/Element.js +47 -32
  47. package/source/class/qx/html/Image.js +2 -2
  48. package/source/class/qx/html/Node.js +34 -4
  49. package/source/class/qx/lang/Json.js +1 -0
  50. package/source/class/qx/lang/String.js +53 -1
  51. package/source/class/qx/test/Annotation.js +2 -1
  52. package/source/class/qx/test/Promise.js +5 -3
  53. package/source/class/qx/test/bom/Font.js +10 -1
  54. package/source/class/qx/test/core/Property.js +5 -3
  55. package/source/class/qx/test/html/Element.js +3 -3
  56. package/source/class/qx/test/lang/String.js +28 -0
  57. package/source/class/qx/test/type/BaseString.js +7 -0
  58. package/source/class/qx/test/ui/embed/Iframe.js +1 -0
  59. package/source/class/qx/test/ui/form/ComboBox.js +0 -42
  60. package/source/class/qx/test/ui/virtual/performance/AbstractLayerTest.js +6 -2
  61. package/source/class/qx/theme/manager/Decoration.js +0 -0
  62. package/source/class/qx/theme/manager/Font.js +11 -0
  63. package/source/class/qx/theme/tangible/Appearance.js +10 -0
  64. package/source/class/qx/theme/tangible/ColorDark.js +0 -0
  65. package/source/class/qx/theme/tangible/Decoration.js +6 -0
  66. package/source/class/qx/tool/cli/Cli.js +5 -3
  67. package/source/class/qx/tool/cli/Watch.js +52 -0
  68. package/source/class/qx/tool/cli/api/AbstractApi.js +1 -1
  69. package/source/class/qx/tool/cli/api/CompilerApi.js +16 -6
  70. package/source/class/qx/tool/cli/api/LibraryApi.js +1 -1
  71. package/source/class/qx/tool/cli/commands/Command.js +7 -0
  72. package/source/class/qx/tool/cli/commands/Compile.js +28 -9
  73. package/source/class/qx/tool/cli/commands/Lint.js +30 -11
  74. package/source/class/qx/tool/cli/commands/Package.js +1 -2
  75. package/source/class/qx/tool/cli/commands/Run.js +2 -25
  76. package/source/class/qx/tool/cli/commands/Serve.js +9 -0
  77. package/source/class/qx/tool/cli/commands/package/Publish.js +19 -10
  78. package/source/class/qx/tool/compiler/Analyser.js +22 -23
  79. package/source/class/qx/tool/compiler/ClassFile.js +3 -2
  80. package/source/class/qx/tool/compiler/Console.js +17 -1
  81. package/source/class/qx/tool/compiler/Preprocess.js +1 -1
  82. package/source/class/qx/tool/compiler/app/Application.js +4 -2
  83. package/source/class/qx/tool/compiler/app/Cldr.js +1 -1
  84. package/source/class/qx/tool/compiler/app/Library.js +82 -88
  85. package/source/class/qx/tool/compiler/app/Part.js +1 -1
  86. package/source/class/qx/tool/compiler/app/Translation.js +1 -1
  87. package/source/class/qx/tool/compiler/app/WebFont.js +5 -4
  88. package/source/class/qx/tool/compiler/jsdoc/ChildControlParser.js +1 -1
  89. package/source/class/qx/tool/compiler/jsdoc/CommandParser.js +1 -1
  90. package/source/class/qx/tool/compiler/jsdoc/ParamParser.js +1 -1
  91. package/source/class/qx/tool/compiler/jsdoc/Parser.js +1 -1
  92. package/source/class/qx/tool/compiler/jsdoc/ReturnParser.js +1 -1
  93. package/source/class/qx/tool/compiler/jsdoc/ThrowsParser.js +1 -1
  94. package/source/class/qx/tool/compiler/makers/AbstractAppMaker.js +1 -1
  95. package/source/class/qx/tool/compiler/makers/AppMaker.js +14 -14
  96. package/source/class/qx/tool/compiler/makers/Maker.js +1 -1
  97. package/source/class/qx/tool/compiler/resources/AbstractMatcher.js +1 -1
  98. package/source/class/qx/tool/compiler/resources/Asset.js +2 -2
  99. package/source/class/qx/tool/compiler/resources/ImageLoader.js +3 -2
  100. package/source/class/qx/tool/compiler/resources/Manager.js +5 -5
  101. package/source/class/qx/tool/compiler/resources/MetaLoader.js +1 -1
  102. package/source/class/qx/tool/compiler/resources/ResourceConverter.js +1 -1
  103. package/source/class/qx/tool/compiler/resources/ResourceLoader.js +1 -1
  104. package/source/class/qx/tool/compiler/resources/ScssConverter.js +9 -3
  105. package/source/class/qx/tool/compiler/resources/ScssFile.js +13 -12
  106. package/source/class/qx/tool/compiler/resources/ScssIncludeConverter.js +1 -1
  107. package/source/class/qx/tool/compiler/targets/BuildTarget.js +1 -1
  108. package/source/class/qx/tool/compiler/targets/SourceCodeCopier.js +1 -1
  109. package/source/class/qx/tool/compiler/targets/SourceTarget.js +1 -1
  110. package/source/class/qx/tool/compiler/targets/Target.js +70 -32
  111. package/source/class/qx/tool/compiler/targets/TypeScriptWriter.js +3 -4
  112. package/source/class/qx/tool/compiler/targets/meta/AbstractJavascriptMeta.js +22 -0
  113. package/source/class/qx/tool/compiler/targets/meta/ApplicationMeta.js +30 -0
  114. package/source/class/qx/tool/compiler/targets/meta/BootJs.js +22 -0
  115. package/source/class/qx/tool/compiler/targets/meta/Javascript.js +22 -0
  116. package/source/class/qx/tool/compiler/targets/meta/Package.js +37 -2
  117. package/source/class/qx/tool/compiler/targets/meta/PackageJavascript.js +22 -0
  118. package/source/class/qx/tool/compiler/targets/meta/Part.js +22 -0
  119. package/source/class/qx/tool/compiler/targets/meta/PolyfillJs.js +29 -7
  120. package/source/class/qx/tool/compiler/targets/meta/Uglify.js +23 -1
  121. package/source/class/qx/tool/config/Abstract.js +3 -3
  122. package/source/class/qx/tool/config/Utils.js +10 -1
  123. package/source/class/qx/tool/utils/IndexedArray.js +1 -1
  124. package/source/class/qx/tool/utils/Json.js +2 -2
  125. package/source/class/qx/tool/utils/LogManager.js +1 -1
  126. package/source/class/qx/tool/utils/Logger.js +1 -1
  127. package/source/class/qx/tool/utils/Promisify.js +1 -1
  128. package/source/class/qx/tool/utils/Utils.js +118 -1
  129. package/source/class/qx/tool/utils/Values.js +1 -1
  130. package/source/class/qx/tool/utils/Website.js +23 -18
  131. package/source/class/qx/tool/utils/files/FindFiles.js +1 -1
  132. package/source/class/qx/tool/utils/files/Utils.js +1 -1
  133. package/source/class/qx/tool/utils/json/Parser.js +1 -1
  134. package/source/class/qx/tool/utils/json/Stringify.js +1 -1
  135. package/source/class/qx/tool/utils/json/Tokenizer.js +1 -1
  136. package/source/class/qx/tool/utils/json/Writer.js +1 -1
  137. package/source/class/qx/type/BaseString.js +2 -1
  138. package/source/class/qx/ui/basic/Image.js +15 -7
  139. package/source/class/qx/ui/basic/Label.js +3 -1
  140. package/source/class/qx/ui/container/SlideBar.js +3 -0
  141. package/source/class/qx/ui/control/DateChooser.js +20 -1
  142. package/source/class/qx/ui/core/scroll/NativeScrollBar.js +3 -0
  143. package/source/class/qx/ui/core/scroll/ScrollBar.js +3 -0
  144. package/source/class/qx/ui/form/AbstractSelectBox.js +38 -6
  145. package/source/class/qx/ui/form/Button.js +3 -0
  146. package/source/class/qx/ui/form/CheckBox.js +25 -1
  147. package/source/class/qx/ui/form/CheckedList.js +2 -1
  148. package/source/class/qx/ui/form/ComboBox.js +36 -27
  149. package/source/class/qx/ui/form/List.js +3 -0
  150. package/source/class/qx/ui/form/MenuButton.js +24 -2
  151. package/source/class/qx/ui/form/RadioButton.js +7 -0
  152. package/source/class/qx/ui/form/RadioButtonGroup.js +3 -0
  153. package/source/class/qx/ui/form/RadioGroup.js +19 -0
  154. package/source/class/qx/ui/form/SelectBox.js +23 -1
  155. package/source/class/qx/ui/form/Slider.js +15 -0
  156. package/source/class/qx/ui/form/SplitButton.js +3 -0
  157. package/source/class/qx/ui/form/ToggleButton.js +8 -0
  158. package/source/class/qx/ui/menu/AbstractButton.js +24 -0
  159. package/source/class/qx/ui/menu/Button.js +3 -0
  160. package/source/class/qx/ui/menu/CheckBox.js +8 -0
  161. package/source/class/qx/ui/menu/Manager.js +2 -0
  162. package/source/class/qx/ui/menu/Menu.js +63 -1
  163. package/source/class/qx/ui/menu/RadioButton.js +10 -1
  164. package/source/class/qx/ui/menubar/Button.js +0 -27
  165. package/source/class/qx/ui/menubar/MenuBar.js +12 -0
  166. package/source/class/qx/ui/splitpane/Blocker.js +3 -0
  167. package/source/class/qx/ui/splitpane/HLayout.js +2 -2
  168. package/source/class/qx/ui/splitpane/Pane.js +4 -1
  169. package/source/class/qx/ui/splitpane/VLayout.js +2 -2
  170. package/source/class/qx/ui/table/Table.js +24 -2
  171. package/source/class/qx/ui/table/cellrenderer/Abstract.js +3 -1
  172. package/source/class/qx/ui/table/cellrenderer/AbstractImage.js +7 -3
  173. package/source/class/qx/ui/table/headerrenderer/HeaderCell.js +3 -0
  174. package/source/class/qx/ui/table/pane/Header.js +3 -0
  175. package/source/class/qx/ui/table/pane/Scroller.js +3 -7
  176. package/source/class/qx/ui/table/rowrenderer/Default.js +1 -1
  177. package/source/class/qx/ui/tabview/Page.js +26 -0
  178. package/source/class/qx/ui/tabview/TabView.js +3 -0
  179. package/source/class/qx/ui/toolbar/Button.js +2 -27
  180. package/source/class/qx/ui/toolbar/CheckBox.js +0 -27
  181. package/source/class/qx/ui/toolbar/RadioButton.js +21 -0
  182. package/source/class/qx/ui/toolbar/SplitButton.js +0 -28
  183. package/source/class/qx/ui/toolbar/ToolBar.js +3 -0
  184. package/source/class/qx/util/ColorUtil.js +2 -1
  185. package/source/class/qx/util/ResourceManager.js +16 -7
  186. package/source/class/qx/util/format/DateFormat.js +9 -0
  187. package/source/class/qxWeb.js +8 -4
  188. package/source/resource/qx/decoration/Indigo/font/JosefinSlab-SemiBold.ttf +0 -0
  189. package/source/resource/qx/decoration/Indigo/font/SIL Open Font License 1.1.txt +0 -0
  190. package/source/resource/qx/iconfont/MaterialIcons/fetch-fonts.sh +0 -0
  191. package/source/resource/qx/mobile/scss/common/_gradients.scss +3 -1
  192. package/source/resource/qx/mobile/scss/theme/indigo/_styles.scss +1 -1
  193. package/source/resource/qx/mobile/scss/ui/_carousel.scss +2 -2
  194. package/source/resource/qx/mobile/scss/ui/_checkbox.scss +3 -3
  195. package/source/resource/qx/mobile/scss/ui/_collapsible.scss +2 -2
  196. package/source/resource/qx/mobile/scss/ui/_picker.scss +4 -4
  197. package/source/resource/qx/mobile/scss/ui/_radiobutton.scss +4 -4
  198. package/source/resource/qx/mobile/scss/ui/_slider.scss +7 -7
  199. package/source/resource/qx/scss/_gradients.scss +3 -1
  200. package/source/resource/qx/scss/_mixins.scss +4 -2
  201. package/source/resource/qx/tool/bin/build-devtools +0 -0
  202. package/source/resource/qx/tool/bin/build-website +0 -0
  203. package/source/resource/qx/tool/bin/download-assets +0 -0
  204. package/source/resource/qx/tool/cli/templates/TypeScriptWriter-base_declaration.txt +13 -0
  205. package/source/resource/qx/tool/cli/templates/loader/loader-browser.tmpl.js +8 -2
  206. package/source/resource/qx/tool/cli/templates/loader/loader-node.tmpl.js +24 -11
  207. package/source/resource/qx/tool/cli/templates/loader/loader-rhino.tmpl.js +9 -2
  208. package/source/resource/qx/tool/cli/templates/skeleton/mobile/source/theme/custom/scss/_styles.scss +1 -1
  209. package/source/resource/qx/tool/cli/templates/template_vars.js +1 -1
  210. package/source/resource/qx/tool/loadsass.js +13 -0
  211. package/source/resource/qx/tool/schema/Manifest-1-0-0.json +1 -2
  212. package/source/resource/qx/tool/schema/Manifest-2-0-0.json +1 -2
  213. package/source/resource/qx/tool/schema/compile-1-0-0.json +19 -9
  214. package/source/resource/qx/website/scss/ui/_carousel.scss +2 -2
  215. package/lib/resource/qx/tool/website/.gitignore +0 -2
  216. package/source/class/qx/io/request/auth/.gitignore +0 -0
  217. package/source/class/qx/test/bom/client/.gitignore +0 -0
  218. package/source/class/qx/test/ui/control/.gitignore +0 -0
  219. package/source/class/qx/tool/compiler/Version.js +0 -20
  220. package/source/resource/qx/decoration/Modern/treevirtual/.gitignore +0 -0
  221. package/source/resource/qx/mobile/css/.gitignore +0 -3
  222. package/source/resource/qx/tool/website/.gitignore +0 -2
  223. package/source/resource/qx/website/.gitignore +0 -1
  224. package/source/resource/qx/website/scss/.gitignore +0 -1
@@ -3,7 +3,7 @@
3
3
  * qooxdoo-compiler - node.js based replacement for the Qooxdoo python
4
4
  * toolchain
5
5
  *
6
- * https://github.com/qooxdoo/qooxdoo-compiler
6
+ * https://github.com/qooxdoo/qooxdoo
7
7
  *
8
8
  * Copyright:
9
9
  * 2011-2017 Zenesis Limited, http://www.zenesis.com
@@ -3,7 +3,7 @@
3
3
  * qooxdoo-compiler - node.js based replacement for the Qooxdoo python
4
4
  * toolchain
5
5
  *
6
- * https://github.com/qooxdoo/qooxdoo-compiler
6
+ * https://github.com/qooxdoo/qooxdoo
7
7
  *
8
8
  * Copyright:
9
9
  * 2011-2017 Zenesis Limited, http://www.zenesis.com
@@ -3,7 +3,7 @@
3
3
  * qooxdoo-compiler - node.js based replacement for the Qooxdoo python
4
4
  * toolchain
5
5
  *
6
- * https://github.com/qooxdoo/qooxdoo-compiler
6
+ * https://github.com/qooxdoo/qooxdoo
7
7
  *
8
8
  * Copyright:
9
9
  * 2011-2019 Zenesis Limited, http://www.zenesis.com
@@ -3,7 +3,7 @@
3
3
  * qooxdoo-compiler - node.js based replacement for the Qooxdoo python
4
4
  * toolchain
5
5
  *
6
- * https://github.com/qooxdoo/qooxdoo-compiler
6
+ * https://github.com/qooxdoo/qooxdoo
7
7
  *
8
8
  * Copyright:
9
9
  * 2011-2019 Zenesis Limited, http://www.zenesis.com
@@ -3,7 +3,7 @@
3
3
  * qooxdoo-compiler - node.js based replacement for the Qooxdoo python
4
4
  * toolchain
5
5
  *
6
- * https://github.com/qooxdoo/qooxdoo-compiler
6
+ * https://github.com/qooxdoo/qooxdoo
7
7
  *
8
8
  * Copyright:
9
9
  * 2011-2019 Zenesis Limited, http://www.zenesis.com
@@ -3,7 +3,7 @@
3
3
  * qooxdoo-compiler - node.js based replacement for the Qooxdoo python
4
4
  * toolchain
5
5
  *
6
- * https://github.com/qooxdoo/qooxdoo-compiler
6
+ * https://github.com/qooxdoo/qooxdoo
7
7
  *
8
8
  * Copyright:
9
9
  * 2011-2019 Zenesis Limited, http://www.zenesis.com
@@ -387,7 +387,8 @@ qx.Class.define("qx.type.BaseString",
387
387
  'toUpperCase',
388
388
  'toLocaleLowerCase',
389
389
  'toLocaleUpperCase',
390
- 'trim'
390
+ 'trim',
391
+ 'codePointAt'
391
392
  ];
392
393
 
393
394
  // feature/bug detection:
@@ -796,10 +796,7 @@ qx.Class.define("qx.ui.basic.Image",
796
796
  height = this.getHeight() || hint.height;
797
797
  }
798
798
  else {
799
- var font = qx.theme.manager.Font.getInstance().resolve(source.match(/@([^/]+)/)[1]);
800
- if (qx.core.Environment.get("qx.debug")) {
801
- this.assertObject(font, "Virtual image source contains unkown font descriptor");
802
- }
799
+ var font = this.__getFont(source);
803
800
  var size = parseInt(source.split("/")[2] || font.getSize(), 10);
804
801
  width = ResourceManager.getImageWidth(source) || size;
805
802
  height = ResourceManager.getImageHeight(source) || size;
@@ -830,7 +827,8 @@ qx.Class.define("qx.ui.basic.Image",
830
827
  } else {
831
828
  var source = this.getSource();
832
829
  var sparts = source.split("/");
833
- var size = parseInt(sparts[2] || qx.theme.manager.Font.getInstance().resolve(source.match(/@([^/]+)/)[1]).getSize());
830
+ var font = this.__getFont(source);
831
+ var size = parseInt(sparts[2] || font.getSize());
834
832
  el.setStyle("fontSize", size + "px");
835
833
  }
836
834
  },
@@ -930,6 +928,14 @@ qx.Class.define("qx.ui.basic.Image",
930
928
  }
931
929
  },
932
930
 
931
+ __getFont(source) {
932
+ var font = qx.theme.manager.Font.getInstance().resolve(source.match(/@([^/]+)/)[1]);
933
+ if (typeof font == "string") {
934
+ throw new Error(`Cannot find font in virtual image source: '${source}'`);
935
+ }
936
+ return font;
937
+ },
938
+
933
939
  /**
934
940
  * Combines the decorator's image styles with our own image to make sure
935
941
  * gradient and backgroundImage decorators work on Images.
@@ -942,7 +948,7 @@ qx.Class.define("qx.ui.basic.Image",
942
948
 
943
949
  if (isFont) {
944
950
  var ResourceManager = qx.util.ResourceManager.getInstance();
945
- var font = qx.theme.manager.Font.getInstance().resolve(source.match(/@([^/]+)/)[1]);
951
+ var font = this.__getFont(source);
946
952
  var fontStyles = qx.lang.Object.clone(font.getStyles());
947
953
  delete fontStyles.color;
948
954
  el.setStyles(fontStyles);
@@ -977,7 +983,8 @@ qx.Class.define("qx.ui.basic.Image",
977
983
  var combinedStyles = {
978
984
  "backgroundImage": attr.style.backgroundImage,
979
985
  "backgroundPosition": (attr.style.backgroundPosition || "0 0"),
980
- "backgroundRepeat": (attr.style.backgroundRepeat || "no-repeat")
986
+ "backgroundRepeat": (attr.style.backgroundRepeat || "no-repeat"),
987
+ "position": "absolute"
981
988
  };
982
989
 
983
990
  if (hasBackground) {
@@ -1006,6 +1013,7 @@ qx.Class.define("qx.ui.basic.Image",
1006
1013
  }
1007
1014
  if (el.setSource){
1008
1015
  el.setSource(source);
1016
+ el.setStyle("position", "absolute");
1009
1017
  }
1010
1018
  },
1011
1019
 
@@ -363,7 +363,9 @@ qx.Class.define("qx.ui.basic.Label",
363
363
  {
364
364
  this.__font = qx.theme.manager.Font.getInstance().resolve(value);
365
365
  if (this.__font instanceof qx.bom.webfonts.WebFont) {
366
- this.__webfontListenerId = this.__font.addListener("changeStatus", this._onWebFontStatusChange, this);
366
+ if (!this.__font.isValid()) {
367
+ this.__webfontListenerId = this.__font.addListener("changeStatus", this._onWebFontStatusChange, this);
368
+ }
367
369
  }
368
370
  styles = this.__font.getStyles();
369
371
  }
@@ -272,6 +272,9 @@ qx.Class.define("qx.ui.container.SlideBar",
272
272
  // property apply
273
273
  _applyOrientation : function(value, old)
274
274
  {
275
+ // ARIA attrs
276
+ this.getContentElement().setAttribute("aria-orientation", value);
277
+
275
278
  var oldLayouts = [this.getLayout(), this._getLayout()];
276
279
  var buttonForward = this.getChildControl("button-forward");
277
280
  var buttonBackward = this.getChildControl("button-backward");
@@ -190,7 +190,26 @@ qx.Class.define("qx.ui.control.DateChooser",
190
190
  event : "changeShownYear"
191
191
  },
192
192
 
193
- /** The date value of the widget. */
193
+ /**
194
+ * The date value of the widget.
195
+ *
196
+ * CAUTION: Date is a reference type. If you call `setValue` with
197
+ * a Date object, and then change that Date object's value, e.g.,
198
+ * with `date.setYear()`, and then call `setValue` with that same
199
+ * Date object, ** the widget will not update **. Instead, you
200
+ * should instantiate a new Date object with the old (modified)
201
+ * date object as its initiatializer, and pass that to `setValue`,
202
+ * e.g.,
203
+ *
204
+ * ```
205
+ * date = new Date();
206
+ * dateChooser.setValue(date);
207
+ * // ...some time later...
208
+ * date = date.setDate(date.getDate() + 1);
209
+ * // dateChooser.setValue(date); // This will NOT update the widget
210
+ * dateChooser.setValue(new Date(date)); // This WILL update the widget
211
+ * ```
212
+ */
194
213
  value :
195
214
  {
196
215
  check : "Date",
@@ -234,6 +234,9 @@ qx.Class.define("qx.ui.core.scroll.NativeScrollBar",
234
234
  // property apply
235
235
  _applyOrientation : function(value, old)
236
236
  {
237
+ // ARIA attrs
238
+ this.getContentElement().setAttribute("aria-orientation", value);
239
+
237
240
  var isHorizontal = this.__isHorizontal = value === "horizontal";
238
241
 
239
242
  this.set({
@@ -301,6 +301,9 @@ qx.Class.define("qx.ui.core.scroll.ScrollBar",
301
301
  // property apply
302
302
  _applyOrientation : function(value, old)
303
303
  {
304
+ // ARIA attrs
305
+ this.getContentElement().setAttribute("aria-orientation", value);
306
+
304
307
  // Dispose old layout
305
308
  var oldLayout = this._getLayout();
306
309
  if (oldLayout) {
@@ -55,6 +55,12 @@ qx.Class.define("qx.ui.form.AbstractSelectBox",
55
55
  this._setLayout(layout);
56
56
  layout.setAlignY("middle");
57
57
 
58
+ // ARIA attrs
59
+ const contentEl = this.getContentElement();
60
+ contentEl.setAttribute("role", "button");
61
+ contentEl.setAttribute("aria-haspopup", "listbox");
62
+ contentEl.setAttribute("aria-expanded", false);
63
+
58
64
  // Register listeners
59
65
  this.addListener("keypress", this._onKeyPress);
60
66
  this.addListener("blur", this._onBlur, this);
@@ -130,7 +136,7 @@ qx.Class.define("qx.ui.form.AbstractSelectBox",
130
136
 
131
137
  switch(id)
132
138
  {
133
- case "list":
139
+ case "list": {
134
140
  control = new qx.ui.form.List().set({
135
141
  focusable: false,
136
142
  keepFocus: true,
@@ -140,12 +146,18 @@ qx.Class.define("qx.ui.form.AbstractSelectBox",
140
146
  selectionMode: "one",
141
147
  quickSelection: true
142
148
  });
149
+ const listId = "list-" + control.toHashCode();
150
+ const childrenContainerEl = control.getChildrenContainer().getContentElement();
151
+ childrenContainerEl.setAttribute("id", listId);
152
+ childrenContainerEl.setAttribute("role", "listbox");
153
+ this.getContentElement().setAttribute("aria-owns", listId);
143
154
 
155
+ control.addListener("addItem", this._onListAddItem, this);
144
156
  control.addListener("changeSelection", this._onListChangeSelection, this);
145
157
  control.addListener("pointerdown", this._onListPointerDown, this);
146
158
  control.getChildControl("pane").addListener("tap", this.close, this);
147
159
  break;
148
-
160
+ }
149
161
  case "popup":
150
162
  control = new qx.ui.popup.Popup(new qx.ui.layout.VBox());
151
163
  control.setAutoHide(false);
@@ -292,8 +304,8 @@ qx.Class.define("qx.ui.form.AbstractSelectBox",
292
304
  e.stopPropagation();
293
305
  }
294
306
 
295
- // hide the list always on escape
296
- else if (!listPopup.isHidden() && identifier == "Escape")
307
+ // hide the list always on escape and tab
308
+ else if (!listPopup.isHidden() && (identifier == "Escape" || identifier == "Tab"))
297
309
  {
298
310
  this.close();
299
311
  e.stop();
@@ -315,7 +327,23 @@ qx.Class.define("qx.ui.form.AbstractSelectBox",
315
327
  _onResize : function(e){
316
328
  this.getChildControl("popup").setMinWidth(e.getData().width);
317
329
  },
318
-
330
+
331
+ /**
332
+ * Sets ARIA attributes on the item
333
+ *
334
+ * @param e {qx.event.type.Data} Data Event
335
+ */
336
+ _onListAddItem : function(e) {
337
+ const item = e.getData();
338
+ const contentEl = item.getContentElement();
339
+ contentEl.setAttribute("id", "list-item-" + item.toHashCode());
340
+ contentEl.setAttribute("role", "option");
341
+ const ariaSelected = contentEl.getAttribute("aria-selected");
342
+ // aria-selected may be already set from changeSelection listener
343
+ if (ariaSelected === null || ariaSelected === undefined) {
344
+ contentEl.setAttribute("aria-selected", false);
345
+ }
346
+ },
319
347
 
320
348
  /**
321
349
  * Syncs the own property from the list change
@@ -343,7 +371,11 @@ qx.Class.define("qx.ui.form.AbstractSelectBox",
343
371
  * @param e {qx.event.type.Data} Property change event
344
372
  */
345
373
  _onPopupChangeVisibility : function(e) {
346
- e.getData() == "visible" ? this.addState("popupOpen") : this.removeState("popupOpen");
374
+ const visible = e.getData() == "visible";
375
+ visible ? this.addState("popupOpen") : this.removeState("popupOpen");
376
+
377
+ // ARIA attrs
378
+ this.getContentElement().setAttribute("aria-expanded", visible);
347
379
  }
348
380
  }
349
381
  });
@@ -75,6 +75,9 @@ qx.Class.define("qx.ui.form.Button",
75
75
  this.setCommand(command);
76
76
  }
77
77
 
78
+ // ARIA attrs
79
+ this.getContentElement().setAttribute("role", "button");
80
+
78
81
  // Add listeners
79
82
  this.addListener("pointerover", this._onPointerOver);
80
83
  this.addListener("pointerout", this._onPointerOut);
@@ -54,6 +54,12 @@ qx.Class.define("qx.ui.form.CheckBox",
54
54
  // Initialize the checkbox to a valid value (the default is null which
55
55
  // is invalid)
56
56
  this.setValue(false);
57
+
58
+ // ARIA attrs
59
+ const contentEl = this.getContentElement();
60
+ contentEl.setAttribute("role", "checkbox");
61
+ contentEl.removeAttribute("aria-pressed");
62
+ contentEl.setAttribute("aria-checked", false);
57
63
  },
58
64
 
59
65
 
@@ -107,6 +113,24 @@ qx.Class.define("qx.ui.form.CheckBox",
107
113
  "toolTipText",
108
114
  "value",
109
115
  "menu"
110
- ]
116
+ ],
117
+
118
+ // overridden
119
+ _applyValue : function(value, old) {
120
+ value ? this.addState("checked") : this.removeState("checked");
121
+
122
+ let ariaChecked = Boolean(value);
123
+ if (this.isTriState()) {
124
+ if (value === null) {
125
+ ariaChecked = "mixed";
126
+ this.addState("undetermined");
127
+ } else if (old === null) {
128
+ this.removeState("undetermined");
129
+ }
130
+ }
131
+
132
+ // ARIA attrs
133
+ this.getContentElement().setAttribute("aria-checked", ariaChecked);
134
+ },
111
135
  }
112
136
  });
@@ -155,8 +155,9 @@ qx.Class.define("qx.ui.form.CheckedList", {
155
155
  __onItemChangeCheckedImpl(item, removing) {
156
156
  let hash = item.toHashCode();
157
157
  let checked = item.getValue();
158
- if (removing)
158
+ if (removing) {
159
159
  checked = false;
160
+ }
160
161
  let changed = false;
161
162
  let oldData = this.getChecked();
162
163
  if (checked) {
@@ -50,6 +50,9 @@ qx.Class.define("qx.ui.form.ComboBox",
50
50
  var textField = this._createChildControl("textfield");
51
51
  this._createChildControl("button");
52
52
 
53
+ // ARIA attrs
54
+ this.getContentElement().setAttribute("role", "combobox");
55
+
53
56
  this.addListener("tap", this._onTap);
54
57
 
55
58
  // forward the focusin and focusout events to the textfield. The textfield
@@ -242,26 +245,25 @@ qx.Class.define("qx.ui.form.ComboBox",
242
245
  var popup = this.getChildControl("popup");
243
246
  var iden = e.getKeyIdentifier();
244
247
 
245
- if (iden == "Down" && e.isAltPressed())
246
- {
247
- this.getChildControl("button").addState("selected");
248
- this.toggle();
249
- e.stopPropagation();
250
- }
251
- else if (iden == "Enter")
252
- {
253
- if (popup.isVisible())
254
- {
248
+ if (popup.isVisible()) {
249
+ const listIdentifier = ["Up", "Down", "PageUp", "PageDown", "Escape", "Tab"];
250
+ if (iden == "Enter") {
255
251
  this._setPreselectedItem();
256
252
  this.resetAllTextSelection();
257
253
  this.close();
258
254
  e.stop();
255
+ } else if (listIdentifier.includes(iden)) {
256
+ this.base(arguments, e);
257
+ } else {
258
+ this.close();
259
+ }
260
+ } else {
261
+ if (iden == "Down") {
262
+ this.getChildControl("button").addState("selected");
263
+ this.open();
264
+ e.stop();
259
265
  }
260
266
  }
261
- else if (popup.isVisible())
262
- {
263
- this.base(arguments, e);
264
- }
265
267
  },
266
268
 
267
269
 
@@ -333,6 +335,13 @@ qx.Class.define("qx.ui.form.ComboBox",
333
335
  this.__preSelectedItem = null;
334
336
  }
335
337
  }
338
+
339
+ // Set aria-activedescendant
340
+ if (current && current[0]) {
341
+ this.getChildControl("textfield").getContentElement().setAttribute("aria-activedescendant", current[0].getContentElement().getAttribute("id"));
342
+ } else {
343
+ this.getChildControl("textfield").getContentElement().removeAttribute("aria-activedescendant");
344
+ }
336
345
  },
337
346
 
338
347
 
@@ -363,16 +372,6 @@ qx.Class.define("qx.ui.form.ComboBox",
363
372
  list.resetSelection();
364
373
  }
365
374
  }
366
- else
367
- {
368
- // When closing the popup text should selected and field should
369
- // have the focus. Identical to when reaching the field using the TAB key.
370
- //
371
- // Only focus if popup was visible before. Fixes [BUG #4453].
372
- if (e.getOldData() == "visible") {
373
- this.tabFocus();
374
- }
375
- }
376
375
 
377
376
  // In all cases: Remove focused state from button
378
377
  this.getChildControl("button").removeState("selected");
@@ -390,11 +389,12 @@ qx.Class.define("qx.ui.form.ComboBox",
390
389
  var value = e.getData();
391
390
 
392
391
  var list = this.getChildControl("list");
392
+ let current = null;
393
393
  if (value != null) {
394
394
  // Select item when possible
395
- var item = list.findItem(value, false);
396
- if (item) {
397
- list.setSelection([item]);
395
+ current = list.findItem(value, false);
396
+ if (current) {
397
+ list.setSelection([current]);
398
398
  } else {
399
399
  list.resetSelection();
400
400
  }
@@ -402,6 +402,15 @@ qx.Class.define("qx.ui.form.ComboBox",
402
402
  list.resetSelection();
403
403
  }
404
404
 
405
+ // ARIA attrs
406
+ const old = e.getOldData() ? list.findItem(e.getOldData(), false) : null;
407
+ if (old && old !== current) {
408
+ old.getContentElement().setAttribute("aria-selected", false);
409
+ }
410
+ if (current) {
411
+ current.getContentElement().setAttribute("aria-selected", true);
412
+ }
413
+
405
414
  // Fire event
406
415
  this.fireDataEvent("changeValue", value, e.getOldData());
407
416
  },
@@ -277,6 +277,9 @@ qx.Class.define("qx.ui.form.List",
277
277
  // property apply
278
278
  _applyOrientation : function(value, old)
279
279
  {
280
+ // ARIA attrs
281
+ this.getContentElement().setAttribute("aria-orientation", value);
282
+
280
283
  var content = this.__content;
281
284
 
282
285
  // save old layout for disposal
@@ -45,6 +45,9 @@ qx.Class.define("qx.ui.form.MenuButton",
45
45
  if (menu != null) {
46
46
  this.setMenu(menu);
47
47
  }
48
+
49
+ // ARIA attrs
50
+ this.getContentElement().setAttribute("role", "button");
48
51
  },
49
52
 
50
53
 
@@ -112,6 +115,7 @@ qx.Class.define("qx.ui.form.MenuButton",
112
115
  old.resetOpener();
113
116
  }
114
117
 
118
+ const contentEl = this.getContentElement();
115
119
  if (value)
116
120
  {
117
121
  value.addListener("changeVisibility", this._onMenuChange, this);
@@ -119,6 +123,16 @@ qx.Class.define("qx.ui.form.MenuButton",
119
123
 
120
124
  value.removeState("submenu");
121
125
  value.removeState("contextmenu");
126
+
127
+ // ARIA attrs
128
+ contentEl.setAttribute("aria-haspopup", "menu");
129
+ contentEl.setAttribute("aria-expanded", value.isVisible());
130
+ contentEl.setAttribute("aria-controls", value.getContentElement().getAttribute("id"));
131
+ } else {
132
+ // ARIA attrs
133
+ contentEl.removeAttribute("aria-haspopup");
134
+ contentEl.removeAttribute("aria-expanded");
135
+ contentEl.removeAttribute("aria-controls");
122
136
  }
123
137
  },
124
138
 
@@ -142,6 +156,10 @@ qx.Class.define("qx.ui.form.MenuButton",
142
156
 
143
157
  if (menu)
144
158
  {
159
+ // Focus this button when the menu opens
160
+ if (this.isFocusable() && !qx.ui.core.FocusHandler.getInstance().isFocused(this)) {
161
+ this.focus();
162
+ }
145
163
  // Hide all menus first
146
164
  qx.ui.menu.Manager.getInstance().hideAll();
147
165
 
@@ -177,12 +195,15 @@ qx.Class.define("qx.ui.form.MenuButton",
177
195
  _onMenuChange : function(e)
178
196
  {
179
197
  var menu = this.getMenu();
180
-
181
- if (menu.isVisible()) {
198
+ const menuVisible = menu.isVisible()
199
+ if (menuVisible) {
182
200
  this.addState("pressed");
183
201
  } else {
184
202
  this.removeState("pressed");
185
203
  }
204
+
205
+ // ARIA attrs
206
+ this.getContentElement().setAttribute("aria-expanded", menuVisible);
186
207
  },
187
208
 
188
209
 
@@ -241,6 +262,7 @@ qx.Class.define("qx.ui.form.MenuButton",
241
262
  {
242
263
  switch(e.getKeyIdentifier())
243
264
  {
265
+ case "Space":
244
266
  case "Enter":
245
267
  this.removeState("abandoned");
246
268
  this.addState("pressed");
@@ -68,6 +68,12 @@ qx.Class.define("qx.ui.form.RadioButton",
68
68
 
69
69
  this.base(arguments, label);
70
70
 
71
+ // ARIA attrs
72
+ // Important: (Grouped) radio btns should be children of a div with role 'radiogroup'
73
+ const contentEl = this.getContentElement();
74
+ contentEl.setAttribute("role", "radio");
75
+ contentEl.setAttribute("aria-checked", false);
76
+
71
77
  // Add listeners
72
78
  this.addListener("execute", this._onExecute);
73
79
  this.addListener("keypress", this._onKeyPress);
@@ -164,6 +170,7 @@ qx.Class.define("qx.ui.form.RadioButton",
164
170
  value ?
165
171
  this.addState("checked") :
166
172
  this.removeState("checked");
173
+ this.getContentElement().setAttribute("aria-checked", Boolean(value));
167
174
  },
168
175
 
169
176
 
@@ -55,6 +55,9 @@ qx.Class.define("qx.ui.form.RadioButtonGroup",
55
55
  this.setLayout(layout);
56
56
  }
57
57
 
58
+ // ARIA attrs
59
+ this.getContentElement().setAttribute("role", "radiogroup");
60
+
58
61
  // create the radio group
59
62
  this.__radioGroup = new qx.ui.form.RadioGroup();
60
63
 
@@ -522,7 +522,26 @@ qx.Class.define("qx.ui.form.RadioGroup",
522
522
 
523
523
  if (value) {
524
524
  value.set(groupedProperty, true);
525
+
526
+ // If Group is focused, the selection was changed by keyboard. Switch focus to new value
527
+ if (this.__isGroupFocused() && value.isFocusable()) {
528
+ value.focus();
529
+ }
530
+ }
531
+ },
532
+
533
+ /**
534
+ * Checks if this group is focused by checking focused state of each item
535
+ * @returns {Boolean} result
536
+ */
537
+ __isGroupFocused: function () {
538
+ const focusHandler = qx.ui.core.FocusHandler.getInstance();
539
+ for (const item of this._getItems()) {
540
+ if (focusHandler.isFocused(item)) {
541
+ return true;
542
+ }
525
543
  }
544
+ return false;
526
545
  }
527
546
  },
528
547
 
@@ -221,6 +221,16 @@ qx.Class.define("qx.ui.form.SelectBox",
221
221
 
222
222
  this.__updateIcon();
223
223
  this.__updateLabel();
224
+
225
+ // ARIA attrs
226
+ const old = e.getOldData() ? e.getOldData()[0] : null;
227
+ const current = this.getSelection()[0];
228
+ if (old && old !== current) {
229
+ old.getContentElement().setAttribute("aria-selected", false);
230
+ }
231
+ if (current) {
232
+ current.getContentElement().setAttribute("aria-selected", true);
233
+ }
224
234
  },
225
235
 
226
236
 
@@ -327,7 +337,11 @@ qx.Class.define("qx.ui.form.SelectBox",
327
337
  _onKeyPress : function(e)
328
338
  {
329
339
  var iden = e.getKeyIdentifier();
330
- if(iden == "Enter" || iden == "Space")
340
+ if ((iden == "Down" || iden == "Up") && e.isAltPressed()) {
341
+ this.toggle();
342
+ e.stop();
343
+ }
344
+ else if (iden == "Enter" || iden == "Space")
331
345
  {
332
346
  // Apply pre-selected item (translate quick selection to real selection)
333
347
  if (this.__preSelectedItem)
@@ -337,6 +351,7 @@ qx.Class.define("qx.ui.form.SelectBox",
337
351
  }
338
352
 
339
353
  this.toggle();
354
+ e.stop();
340
355
  }
341
356
  else
342
357
  {
@@ -413,6 +428,13 @@ qx.Class.define("qx.ui.form.SelectBox",
413
428
  {
414
429
  this.resetSelection();
415
430
  }
431
+
432
+ // Set aria-activedescendant
433
+ if (current && current[0]) {
434
+ this.getContentElement().setAttribute("aria-activedescendant", current[0].getContentElement().getAttribute("id"));
435
+ } else {
436
+ this.getContentElement().removeAttribute("aria-activedescendant");
437
+ }
416
438
  },
417
439
 
418
440
  // overridden