diff --git a/src/autocomplete/popup.js b/src/autocomplete/popup.js index 51a491ec987..196191eea17 100644 --- a/src/autocomplete/popup.js +++ b/src/autocomplete/popup.js @@ -7,6 +7,7 @@ var event = require("../lib/event"); var lang = require("../lib/lang"); var dom = require("../lib/dom"); var nls = require("../config").nls; +var userAgent = require("./../lib/useragent"); var getAriaId = function(index) { return `suggest-aria-id:${index}`; @@ -50,7 +51,8 @@ class AcePopup { popup.renderer.setStyle("ace_autocomplete"); // Set aria attributes for the popup - popup.renderer.$textLayer.element.setAttribute("role", "listbox"); + popup.renderer.$textLayer.element.setAttribute("role", userAgent.isSafari ? "menu" : "listbox"); + popup.renderer.$textLayer.element.setAttribute("aria-roledescription", nls("Autocomplete suggestions")); popup.renderer.$textLayer.element.setAttribute("aria-label", nls("Autocomplete suggestions")); popup.renderer.textarea.setAttribute("aria-hidden", "true"); @@ -128,6 +130,7 @@ class AcePopup { if (selected !== t.selectedNode && t.selectedNode) { dom.removeCssClass(t.selectedNode, "ace_selected"); el.removeAttribute("aria-activedescendant"); + selected.removeAttribute("aria-selected"); t.selectedNode.removeAttribute("id"); } t.selectedNode = selected; @@ -137,11 +140,13 @@ class AcePopup { selected.id = ariaId; t.element.setAttribute("aria-activedescendant", ariaId); el.setAttribute("aria-activedescendant", ariaId); - selected.setAttribute("role", "option"); + selected.setAttribute("role", userAgent.isSafari ? "menuitem" : "option"); + selected.setAttribute("aria-roledescription", nls("item")); selected.setAttribute("aria-label", popup.getData(row).value); selected.setAttribute("aria-setsize", popup.data.length); selected.setAttribute("aria-posinset", row+1); selected.setAttribute("aria-describedby", "doc-tooltip"); + selected.setAttribute("aria-selected", "true"); } }); var hideHoverMarker = function() { setHoverMarker(-1); }; diff --git a/src/autocomplete_test.js b/src/autocomplete_test.js index c16904e24e0..35e9dd4cae4 100644 --- a/src/autocomplete_test.js +++ b/src/autocomplete_test.js @@ -66,16 +66,16 @@ module.exports = { assert.ok(!editor.container.querySelector("style")); sendKey("a"); - checkInnerHTML('arraysort localalooooooooooooooooooooooooooooong_word local', function() { + checkInnerHTML('arraysort localalooooooooooooooooooooooooooooong_word local', function() { sendKey("rr"); - checkInnerHTML('arraysort local', function() { + checkInnerHTML('arraysort local', function() { sendKey("r"); - checkInnerHTML('arraysort local', function() { + checkInnerHTML('arraysort local', function() { sendKey("Return"); assert.equal(editor.getValue(), "arraysort\narraysort alooooooooooooooooooooooooooooong_word"); editor.execCommand("insertstring", " looooooooooooooooooooooooooooong_"); - checkInnerHTML('alooooooooooooooooooooooooooooong_word local', function() { + checkInnerHTML('alooooooooooooooooooooooooooooong_word local', function() { sendKey("Return"); editor.destroy(); editor.container.remove(); diff --git a/src/lib/useragent.js b/src/lib/useragent.js index 8427c076c3a..d3e57adb07a 100644 --- a/src/lib/useragent.js +++ b/src/lib/useragent.js @@ -61,6 +61,8 @@ exports.isWebKit = parseFloat(ua.split("WebKit/")[1]) || undefined; exports.isChrome = parseFloat(ua.split(" Chrome/")[1]) || undefined; +exports.isSafari = parseFloat(ua.split(" Safari/")[1]) && !exports.isChrome || undefined; + exports.isEdge = parseFloat(ua.split(" Edge/")[1]) || undefined; exports.isAIR = ua.indexOf("AdobeAIR") >= 0;