带复选框的Dojo dijit树不能通过键盘访问

时间:2016-06-10 12:13:44

标签: dojo accessibility dijit.tree

我创建了一个dijit.Tree对象,其中每个节点都是一个复选框。选择/取消选择父节点时,将选择/取消选择子节点; 当取消选择其中一个孩子时,父母会被取消选择;选择所有子项后,将选择父项。它工作得很好。
但是我需要它可以通过键盘访问。当我导航到树节点并按空格键或回车时,没有任何反应。

我尝试将tabindex和aria-role添加到复选框(以编程方式),但它不起作用。

这是小提琴 - http://jsfiddle.net/pdabade/pyz9Lcpv/65/

require([ 
"dojo/_base/window", "dojo/store/Memory",
"dijit/tree/ObjectStoreModel",
"dijit/Tree", "dijit/form/CheckBox", "dojo/dom",
"dojo/domReady!"
], function(win, Memory, ObjectStoreModel, Tree, checkBox, dom) {

// Create test store, adding the getChildren() method required by      ObjectStoreModel
var myStore = new Memory({
data: [{
  id: 'allDocuments',
  name: 'All Documents'
}, {
  id: 'inboxDocuments',
  name: 'Inbox Documents',
  parent: 'allDocuments'
}, {
  id: 'outboxDocuments',
  name: 'Outbox Documents',
  parent: 'allDocuments'
}, {
  id: 'draftDocuments',
  name: 'Draft Documents',
  parent: 'allDocuments'
}, {
  id: 'finalDocuments',
  name: 'Final Documents',
  parent: 'allDocuments'
}],
getChildren: function(object) {
  return this.query({
    parent: object.id
  });
}
});
// Create the model
var myModel = new ObjectStoreModel({
store: myStore,
query: {
  id: 'allDocuments'
}
});

// Create the Tree.
var tree = new Tree({
model: myModel,

autoExpand: true,
getIconClass: function(item, opened) {
  // console.log('tree getIconClass', item, opened);
  // console.log('tree item type', item.id);
},

onClick: function(item, node, event) {
  //node._iconClass= "dijitFolderClosed";
  //node.iconNode.className = "dijitFolderClosed";
  var _this = this;
  console.log(item.id);
  var id = node.domNode.id,
    isNodeSelected = node.checkBox.get('checked');

  dojo.query('#' + id + ' .dijitCheckBox').forEach(function(node) {
    dijit.getEnclosingWidget(node).set('checked', isNodeSelected);
  });

  if (item.id != 'allComments') {
    if (!isNodeSelected) {
      var parent = node.tree.rootNode; // parent node id
      //console.log(node);
      parent.checkBox.set('checked', false);
    } else {
      var parent = node.tree.rootNode;
      var selected = true;
      var i = 0;
      dojo.query('#' + parent.id +  '.dijitCheckBox').forEach(function(node) {
        if (i > 0) {
          var isSet = dijit.getEnclosingWidget(node).get('checked');
          console.log(isSet);
          if (isSet == false) {
            selected = false;
          }
        }
        i++;
      });
      if (selected) {
        parent.checkBox.set('checked', true);
      }
    }

  }
  //console.log(node.id);
},
_createTreeNode: function(args) {
  var tnode = new dijit._TreeNode(args);
  tnode.labelNode.innerHTML = args.label;
  console.log(args);
  var cb = new dijit.form.CheckBox({
    "aria-checked": "false",
    "aria-describedby": args.label
  });
  cb.placeAt(tnode.labelNode, "first");
  tnode.checkBox = cb;


  return tnode;
}

});
tree.placeAt(contentHere);
tree.startup();
tree.checkedItems();
//tree.expandAll();


});

}

有关如何使键盘可访问的任何想法?

谢谢!

3 个答案:

答案 0 :(得分:0)

请勿在复选框中添加data = np.loadtxt('bib', delimiter=','); x=data[:,0:4]; y=data[:,4]; a=np.ones(shape=(y.size,x[0].size+1)); a[:,1:5]=x; A=np.linalg.inv(a.transpose().dot(a)); B=np.dot(a.transpose(),y); q=A.dot(a.transpose()).dot(y); ##print (q[0]*x[0][0])+(q[1]*x[0][1])+(q[2]*x[0][2])+(q[3]*x[0][3])+(q[4]*x[0][4]) rolearia-checked。这些已经内置到控件中,所以你增加了打破它的风险。您也可以摆脱tabindexrole="presentation"<div><span>的所有<label>。最后,如果您希望可以访问此复选框,则每个文本块都需要aria-describedbyUncaught TypeError: tree.checkedItems is not a function不正确,无论如何都是不太好的选择。

我收到错误:Tab(第159行)

您还有一个很大的焦点管理问题。将以下内容放入CSS中,您将看到每个控件需要按两次:focus {outline:2px solid #f00;}键(如果从聚焦复选框开始):<span>

看起来你有包含元素窃取任何点击,这意味着永远不会选择正确的元素。带有dijit dijitReset dijitInline dijitCheckBox类的tabindex一直在关注焦点,因为它将-10切换到$("#list li").hover(function() { $(this).html('<button>button1</button><button>button2</button>'); }, function() { $(this).empty(); });,将自己带入和退出Tab键顺序。这可能是一个因素。

我建议解决脚本错误,然后查看焦点管理。

答案 1 :(得分:0)

使用dijit,背景中可能无法控制的所有事情都会发生。正如aardrian所说,&lt; input type =&#39;复选框&gt;上有很多角色=演示文稿和所有咏叹调标签。是多余的。 dijit可能(错误地)设置所有这些。 &lt; input type =&#39;复选框&gt;已处理选择,它的角色本质上是一个复选框。当您从div / span标签中创建自定义复选框时,这些aria属性适用。

代码中隐藏了一个原生复选框,但它的不透明度设置为0,因此您无法看到它。 dijit可能正在将它用于复选框事件。

原生复选框还有data-dojo-attach-event =&#34; ondijitclick:_onClick&#34;。我不确定这意味着什么,但只要我看到&#34;点击&#34;在一个事件名称中,我怀疑它可能不适用于键盘。

我尝试了https://dojotoolkit.org/reference-guide/1.10/dijit/form/CheckBox.html上的示例,它适用于键盘。命中空格将选中并取消选中该框。是否可以看到对复选框的关注是另一个问题。

作为旁注,如果您的复选框树使用了aria-checked =&#34;混合&#34;为父母分支。任何时候你有儿童复选框,其中一些被选中而有些则没有,你可以使用&#34;混合&#34;对于父复选框,表示选择的混合。不确定dijit是否支持。

答案 2 :(得分:0)

查看dijit / Tree源我发现它将函数_onNodePress()设置为键盘事件的事件处理程序。您可以覆盖它(或在其后面添加一个方面)并手动处理您想要的按键。它使用树节点和事件对象作为参数,您可以使用它来专门检查空格和回车键。

我用一个例子来分析你的jsfiddle:https://jsfiddle.net/pgianna/jjore5sm/1/

_onNodePress: function(/*TreeNode*/ nodeWidget, /*Event*/ e){
    // This is the original implementation of _onNodePress:
    this.focusNode(nodeWidget);

    // This requires "dojo/keys"
    if (e.keyCode == keys.ENTER || e.keyCode == keys.SPACE)
    {
        var cb = nodeWidget.checkBox;
        cb.set('checked', !cb.get('checked'));
    }
}