From f0928eac13b9161e251a779f229e37ec526fd590 Mon Sep 17 00:00:00 2001
From: Thomas Bruederli <thomas@roundcube.net>
Date: Tue, 03 Jun 2014 13:13:05 -0400
Subject: [PATCH] Fix keyboard navigation and focus/blur behavior in list widgets; register real link element as menu opener

---
 program/js/list.js |   41 ++++++++++++++++++++++++++++++++---------
 1 files changed, 32 insertions(+), 9 deletions(-)

diff --git a/program/js/list.js b/program/js/list.js
index 65d4a92..837a845 100644
--- a/program/js/list.js
+++ b/program/js/list.js
@@ -60,6 +60,7 @@
   this.column_movable = false;
   this.keyboard = false;
   this.toggleselect = false;
+  this.aria_listbox = false;
 
   this.drag_active = false;
   this.col_drag_active = false;
@@ -75,6 +76,9 @@
   if (p && typeof p === 'object')
     for (var n in p)
       this[n] = p[n];
+
+  // register this instance
+  rcube_list_widget._instances.push(this);
 };
 
 
@@ -92,6 +96,12 @@
   }
   else if (this.tagname != 'table' && this.list) {
     this.tbody = this.list;
+  }
+
+  if ($(this.list).attr('role') == 'listbox') {
+    this.aria_listbox = true;
+    if (this.multiselect)
+      $(this.list).attr('aria-multiselectable', 'true');
   }
 
   if (this.tbody) {
@@ -157,6 +167,15 @@
             e.preventDefault();
         }
       }, false);
+    }
+
+    // label the list row with the subject col as descriptive label
+    if (this.aria_listbox) {
+      var lbl_id = 'l:' + row.id;
+      $(row)
+        .attr('role', 'option')
+        .attr('aria-labelledby', lbl_id)
+        .find(this.col_tagname()).eq(this.subject_col).attr('id', lbl_id);
     }
 
     if (document.all)
@@ -881,9 +900,10 @@
  */
 select_row: function(id, mod_key, with_mouse)
 {
-  var select_before = this.selection.join(',');
+  var select_before = this.selection.join(','),
+    in_selection_before = this.in_selection(id);
 
-  if (!this.multiselect)
+  if (!this.multiselect && with_mouse)
     mod_key = 0;
 
   if (!this.shift_start)
@@ -919,21 +939,21 @@
     this.multi_selecting = true;
   }
 
-  // trigger event if selection changed
-  if (this.selection.join(',') != select_before)
-    this.triggerEvent('select');
-
   if (this.last_selected != 0 && this.rows[this.last_selected]) {
     $(this.rows[this.last_selected].obj).removeClass('focused')
       .find(this.col_tagname()).eq(this.subject_col).removeAttr('tabindex');
   }
 
   // unselect if toggleselect is active and the same row was clicked again
-  if (this.toggleselect && this.last_selected == id) {
+  if (this.toggleselect && in_selection_before) {
     this.clear_selection();
-    id = null;
   }
-  else {
+  // trigger event if selection changed
+  else if (this.selection.join(',') != select_before) {
+    this.triggerEvent('select');
+  }
+
+  if (this.rows[id]) {
     $(this.rows[id].obj).addClass('focused');
     // set cursor focus to link inside selected row
     if (this.focused)
@@ -1774,3 +1794,6 @@
 rcube_list_widget.prototype.addEventListener = rcube_event_engine.prototype.addEventListener;
 rcube_list_widget.prototype.removeEventListener = rcube_event_engine.prototype.removeEventListener;
 rcube_list_widget.prototype.triggerEvent = rcube_event_engine.prototype.triggerEvent;
+
+// static
+rcube_list_widget._instances = [];

--
Gitblit v1.9.1