2016-06-10 75 views
0

我創建了一個dijit.Tree對象,其中每個節點都是複選框。當您選擇/取消選擇父節點時,子節點將被選中/取消選擇; 當其中一個孩子被取消選擇時,父母被取消選擇;當所有的孩子被選中時,父母被選中。它工作得很好。
但是我需要它是鍵盤訪問。當我導航到樹節點並按空格鍵或Enter時,什麼都不會發生。帶複選框的Dojo dijit樹不支持鍵盤訪問

我嘗試添加tabindex和詠歎調角色複選框(以編程方式),但它沒有奏效。

這裏是小提琴 - 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(); 


}); 

} 

任何想法,如何使它鍵盤操作?

謝謝!

回答

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')); 
    } 
} 
+0

正是我需要的!非常感謝。 – pdabade

+0

你能給出一個鏈接到dijit/Tree源嗎? – pdabade

+0

https://github.com/dojo/dijit/blob/master/Tree.js 您也可以從http://download.dojotoolkit.org/下載完整的源代碼。 – pgianna

0

請勿將role,aria-checkedtabindex添加到複選框。這些已經建立在控制之中,所以你增加了破壞道路的風險。您可能也可以擺脫每個role="presentation",因爲這些是<div> s和<span> s,這些都是天生的。最後,如果您希望可以訪問與複選框相關聯的每個文本塊,則需要<label>aria-describedby是不正確的,無論如何是不太好的選擇。

我收到錯誤:Uncaught TypeError: tree.checkedItems is not a function(線159)

你也有一個大集中管理的問題。把下面的在你的CSS,你會看到,它需要的Tab關鍵的兩臺印刷機每個單一控制(如果開始聚焦複選框)::focus {outline:2px solid #f00;}

看起來你有包含元素偷任何點擊,意義正確的元素永遠不會被選中。類別爲dijit dijitReset dijitInline dijitCheckBox<span>持續偷竊焦點,因爲它將tabindex-1切換爲0,將自己放入和放出選項卡順序。這可能是一個因素。

我建議解決腳本錯誤,然後看看焦點管理。

+0

在http://jsfiddle.net/pdabade/pyz9Lcpv/65/修正了錯誤。我明白了你對「每個單一控制按兩次Tab鍵」所說的話。但是,我們如何解決這一重點管理問題? – pdabade

0

隨着dijit,有各種各樣的東西在背景中,可能會超出你的控制。正如阿德里安表示的那樣,有很多角色=演示文稿,並且<輸入類型='複選框>上的所有詠歎調標記都是多餘的。 dijit可能(錯誤地)設置所有這些。一個< input type ='checkbox>已經處理了選擇,它的作用本質上是一個複選框。這些詠歎調屬性適用於當您使用div/span標籤製作自定義複選框時。

在代碼中隱藏了一個本地複選框,但它的不透明度設置爲0,因此您看不到它。 dijit可能使用它作爲複選框事件。

本地複選框還有data-dojo-attach-event =「ondijitclick:_onClick」。我不確定這意味着什麼,但每當我看到事件名稱中的「單擊」時,我都懷疑它可能不適用於鍵盤。

我試過https://dojotoolkit.org/reference-guide/1.10/dijit/form/CheckBox.html上的例子,它可以和鍵盤一起使用。命中空間將檢查並取消選中該框。是否可以看到複選框的焦點是另一個問題。

作爲一個方面說明,如果您的複選框樹對父分支使用了aria-checked =「mixed」,可能會更好。任何時候你有孩子複選框,其中一些被選中,有些則不是,你可以使用父母複選框的「混合」來表示混合的選擇。不知道是否dijit支持。

+0

我已經實現了正常的dijit/form/CheckBox,並且它可以在鍵盤上正常工作。問題是當我在dijit/Tree中使用複選框時。 – pdabade