Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / content / browser / resources / accessibility / accessibility.js
blob7277dd2713c0f1ec52a755821a266951d5cfcba0
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 cr.define('accessibility', function() {
6   'use strict';
8   // Keep in sync with view_message_enums.h
9   var AccessibilityModeFlag = {
10     Platform: 1 << 0,
11     FullTree: 1 << 1
12   }
14   var AccessibilityMode = {
15     Off: 0,
16     Complete:
17         AccessibilityModeFlag.Platform | AccessibilityModeFlag.FullTree,
18     EditableTextOnly: AccessibilityModeFlag.Platform,
19     TreeOnly: AccessibilityModeFlag.FullTree
20   }
22   function isAccessibilityComplete(mode) {
23     return ((mode & AccessibilityMode.Complete) == AccessibilityMode.Complete);
24   }
26   function requestData() {
27     var xhr = new XMLHttpRequest();
28     xhr.open('GET', 'targets-data.json', false);
29     xhr.send(null);
30     if (xhr.status === 200) {
31       console.log(xhr.responseText);
32       return JSON.parse(xhr.responseText);
33     }
34     return [];
35   }
37   // TODO(aboxhall): add a mechanism to request individual and global a11y
38   // mode, xhr them on toggle... or just re-requestData and be smarter about
39   // ID-ing rows?
41   function toggleAccessibility(data, element) {
42     chrome.send('toggleAccessibility',
43                 [String(data.processId), String(data.routeId)]);
44     var a11y_was_on = (element.textContent.match(/on/) != null);
45     element.textContent = ' accessibility ' + (a11y_was_on ? ' off' : ' on');
46     var row = element.parentElement;
47     if (a11y_was_on) {
48       while (row.lastChild != element)
49         row.removeChild(row.lastChild);
50     } else {
51       row.appendChild(document.createTextNode(' | '));
52       row.appendChild(createShowAccessibilityTreeElement(data, row, false));
53     }
54   }
56   function requestAccessibilityTree(data, element) {
57     chrome.send('requestAccessibilityTree',
58                 [String(data.processId), String(data.routeId)]);
59   }
61   function toggleGlobalAccessibility() {
62     chrome.send('toggleGlobalAccessibility');
63     document.location.reload(); // FIXME see TODO above
64   }
66   function initialize() {
67     console.log('initialize');
68     var data = requestData();
70     addGlobalAccessibilityModeToggle(data['global_a11y_mode']);
72     $('pages').textContent = '';
74     var list = data['list'];
75     for (var i = 0; i < list.length; i++) {
76       addToPagesList(list[i]);
77     }
78   }
80   function addGlobalAccessibilityModeToggle(global_a11y_mode) {
81     var full_a11y_on = isAccessibilityComplete(global_a11y_mode);
82     $('toggle_global').textContent = (full_a11y_on ? 'on' : 'off');
83     $('toggle_global').setAttribute('aria-pressed',
84                                     (full_a11y_on ? 'true' : 'false'));
85     $('toggle_global').addEventListener('click',
86                                         toggleGlobalAccessibility);
87   }
89   function addToPagesList(data) {
90     // TODO: iterate through data and pages rows instead
91     var id = data['processId'] + '.' + data['routeId'];
92     var row = document.createElement('div');
93     row.className = 'row';
94     row.id = id;
95     formatRow(row, data);
97     row.processId = data.processId;
98     row.routeId = data.routeId;
100     var list = $('pages');
101     list.appendChild(row);
102   }
104   function formatRow(row, data) {
105     if (!('url' in data)) {
106       if ('error' in data) {
107         row.appendChild(createErrorMessageElement(data, row));
108         return;
109       }
110     }
111     var properties = ['favicon_url', 'name', 'url'];
112     for (var j = 0; j < properties.length; j++)
113       row.appendChild(formatValue(data, properties[j]));
115     row.appendChild(createToggleAccessibilityElement(data));
116     if (isAccessibilityComplete(data['a11y_mode'])) {
117       row.appendChild(document.createTextNode(' | '));
118       if ('tree' in data) {
119         row.appendChild(createShowAccessibilityTreeElement(data, row, true));
120         row.appendChild(document.createTextNode(' | '));
121         row.appendChild(createHideAccessibilityTreeElement(row.id));
122         row.appendChild(createAccessibilityTreeElement(data));
123       }
124       else {
125         row.appendChild(createShowAccessibilityTreeElement(data, row, false));
126         if ('error' in data)
127           row.appendChild(createErrorMessageElement(data, row));
128       }
129     }
130   }
132   function formatValue(data, property) {
133     var value = data[property];
135     if (property == 'favicon_url') {
136       var faviconElement = document.createElement('img');
137       if (value)
138         faviconElement.src = value;
139       faviconElement.alt = "";
140       return faviconElement;
141     }
143     var text = value ? String(value) : '';
144     if (text.length > 100)
145       text = text.substring(0, 100) + '\u2026';  // ellipsis
147     var span = document.createElement('span');
148     span.textContent = ' ' + text + ' ';
149     span.className = property;
150     return span;
151   }
153   function createToggleAccessibilityElement(data) {
154     var link = document.createElement('a', 'action-link');
155     link.setAttribute('role', 'button');
156     var full_a11y_on = isAccessibilityComplete(data['a11y_mode']);
157     link.textContent = 'accessibility ' + (full_a11y_on ? 'on' : 'off');
158     link.setAttribute('aria-pressed', (full_a11y_on ? 'true' : 'false'));
159     link.addEventListener('click',
160                           toggleAccessibility.bind(this, data, link));
161     return link;
162   }
164   function createShowAccessibilityTreeElement(data, row, opt_refresh) {
165     var link = document.createElement('a', 'action-link');
166     link.setAttribute('role', 'button');
167     if (opt_refresh)
168       link.textContent = 'refresh accessibility tree';
169     else
170       link.textContent = 'show accessibility tree';
171     link.id = row.id + ':showTree';
172     link.addEventListener('click',
173                           requestAccessibilityTree.bind(this, data, link));
174     return link;
175   }
177   function createHideAccessibilityTreeElement(id) {
178     var link = document.createElement('a', 'action-link');
179     link.setAttribute('role', 'button');
180     link.textContent = 'hide accessibility tree';
181     link.addEventListener('click',
182                           function() {
183         $(id + ':showTree').textContent = 'show accessibility tree';
184         var existingTreeElements = $(id).getElementsByTagName('pre');
185         for (var i = 0; i < existingTreeElements.length; i++)
186           $(id).removeChild(existingTreeElements[i]);
187         var row = $(id);
188         while (row.lastChild != $(id + ':showTree'))
189           row.removeChild(row.lastChild);
190     });
191     return link;
192   }
194   function createErrorMessageElement(data) {
195     var errorMessageElement = document.createElement('div');
196     var errorMessage = data.error;
197     errorMessageElement.innerHTML = errorMessage + '&nbsp;';
198     var closeLink = document.createElement('a');
199     closeLink.href='#';
200     closeLink.textContent = '[close]';
201     closeLink.addEventListener('click', function() {
202         var parentElement = errorMessageElement.parentElement;
203         parentElement.removeChild(errorMessageElement);
204         if (parentElement.childElementCount == 0)
205           parentElement.parentElement.removeChild(parentElement);
206     });
207     errorMessageElement.appendChild(closeLink);
208     return errorMessageElement;
209   }
211   function showTree(data) {
212     var id = data.processId + '.' + data.routeId;
213     var row = $(id);
214     if (!row)
215       return;
217     row.textContent = '';
218     formatRow(row, data);
219   }
221   function createAccessibilityTreeElement(data) {
222     var treeElement = document.createElement('pre');
223     var tree = data.tree;
224     treeElement.textContent = tree;
225     return treeElement;
226   }
228   return {
229     initialize: initialize,
230     showTree: showTree
231   };
234 document.addEventListener('DOMContentLoaded', accessibility.initialize);