text: // Copyright (c) 2013 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  cr.define('accessibility', function() {
    'use strict';
  
    // Keep in sync with view_message_enums.h
    var AccessibilityModeFlag = {
      Platform: 1 << 0,
      PlatformFullTree: 1 << 1
    }
  
    var AccessibilityMode = {
      Off: 0,
      Complete:
          AccessibilityModeFlag.Platform | AccessibilityModeFlag.PlatformFullTree,
      EditableTextOnly: AccessibilityModeFlag.Platform
    }
  
    function requestData() {
      var xhr = new XMLHttpRequest();
      xhr.open('GET', 'targets-data.json', false);
      xhr.send(null);
      if (xhr.status === 200) {
        console.log(xhr.responseText);
        return JSON.parse(xhr.responseText);
      }
      return [];
    }
  
    // TODO(aboxhall): add a mechanism to request individual and global a11y
    // mode, xhr them on toggle... or just re-requestData and be smarter about
    // ID-ing rows?
  
    function toggleAccessibility(data, element) {
      chrome.send('toggleAccessibility',
                  [String(data.processId), String(data.routeId)]);
      var a11y_was_on = (element.textContent.match(/on/) != null);
      element.textContent = ' accessibility ' + (a11y_was_on ? ' off' : ' on');
      var row = element.parentElement;
      if (a11y_was_on) {
        while (row.lastChild != element)
          row.removeChild(row.lastChild);
      } else {
        row.appendChild(document.createTextNode(' | '));
        row.appendChild(createShowAccessibilityTreeElement(data, row, false));
      }
    }
  
    function requestAccessibilityTree(data, element) {
      chrome.send('requestAccessibilityTree',
                  [String(data.processId), String(data.routeId)]);
    }
  
    function toggleGlobalAccessibility() {
      chrome.send('toggleGlobalAccessibility');
      document.location.reload(); // FIXME see TODO above
    }
  
    function initialize() {
      console.log('initialize');
      var data = requestData();
  
      addGlobalAccessibilityModeToggle(data['global_a11y_mode']);
  
      $('pages').textContent = '';
  
      var list = data['list'];
      for (var i = 0; i < list.length; i++) {
        addToPagesList(list[i]);
      }
    }
  
    function addGlobalAccessibilityModeToggle(global_a11y_mode) {
      var full_a11y_on = ((global_a11y_mode & AccessibilityMode.Complete)
          == AccessibilityMode.Complete);
      $('toggle_global').textContent = (full_a11y_on == 0 ? 'off' : 'on');
      $('toggle_global').addEventListener('click',
                                          toggleGlobalAccessibility);
    }
  
    function addToPagesList(data) {
      // TODO: iterate through data and pages rows instead
      var id = data['processId'] + '.' + data['routeId'];
      var row = document.createElement('div');
      row.className = 'row';
      row.id = id;
      formatRow(row, data);
  
      row.processId = data.processId;
      row.routeId = data.routeId;
  
      var list = $('pages');
      list.appendChild(row);
    }
  
    function formatRow(row, data) {
      if (!('url' in data)) {
        if ('error' in data) {
          row.appendChild(createErrorMessageElement(data, row));
          return;
        }
      }
      var properties = ['favicon_url', 'name', 'url'];
      for (var j = 0; j < properties.length; j++)
        row.appendChild(formatValue(data, properties[j]));
  
      row.appendChild(createToggleAccessibilityElement(data));
      if (data['a11y_mode'] != 0) {
        row.appendChild(document.createTextNode(' | '));
        if ('tree' in data) {
          row.appendChild(createShowAccessibilityTreeElement(data, row, true));
          row.appendChild(document.createTextNode(' | '));
          row.appendChild(createHideAccessibilityTreeElement(row.id));
          row.appendChild(createAccessibilityTreeElement(data));
        }
        else {
          row.appendChild(createShowAccessibilityTreeElement(data, row, false));
          if ('error' in data)
            row.appendChild(createErrorMessageElement(data, row));
        }
      }
    }
  
    function formatValue(data, property) {
      var value = data[property];
  
      if (property == 'favicon_url') {
        var faviconElement = document.createElement('img');
        if (value)
          faviconElement.src = value;
        faviconElement.alt = "";
        return faviconElement;
      }
  
      var text = value ? String(value) : '';
      if (text.length > 100)
        text = text.substring(0, 100) + '\u2026';  // ellipsis
  
      var span = document.createElement('span');
      span.textContent = ' ' + text + ' ';
      span.className = property;
      return span;
    }
  
    function createToggleAccessibilityElement(data) {
      var link = document.createElement('a');
      link.setAttribute('href', '#');
      var a11y_mode = data['a11y_mode'];
      link.textContent = 'accessibility ' + (a11y_mode == 0 ? 'off' : 'on');
      link.addEventListener('click',
                            toggleAccessibility.bind(this, data, link));
      return link;
    }
  
    function createShowAccessibilityTreeElement(data, row, opt_refresh) {
      var link = document.createElement('a');
      link.setAttribute('href', '#');
      if (opt_refresh)
        link.textContent = 'refresh accessibility tree';
      else
        link.textContent = 'show accessibility tree';
      link.id = row.id + ':showTree';
      link.addEventListener('click',
                            requestAccessibilityTree.bind(this, data, link));
      return link;
    }
  
    function createHideAccessibilityTreeElement(id) {
      var link = document.createElement('a');
      link.setAttribute('href', '#');
      link.textContent = 'hide accessibility tree';
      link.addEventListener('click',
                            function() {
          $(id + ':showTree').textContent = 'show accessibility tree';
          var existingTreeElements = $(id).getElementsByTagName('pre');
          for (var i = 0; i < existingTreeElements.length; i++)
            $(id).removeChild(existingTreeElements[i]);
          var row = $(id);
          while (row.lastChild != $(id + ':showTree'))
            row.removeChild(row.lastChild);
      });
      return link;
    }
  
    function createErrorMessageElement(data) {
      var errorMessageElement = document.createElement('div');
      var errorMessage = data.error;
      errorMessageElement.innerHTML = errorMessage + '&nbsp;';
      var closeLink = document.createElement('a');
      closeLink.href='#';
      closeLink.textContent = '[close]';
      closeLink.addEventListener('click', function() {
          var parentElement = errorMessageElement.parentElement;
          parentElement.removeChild(errorMessageElement);
          if (parentElement.childElementCount == 0)
            parentElement.parentElement.removeChild(parentElement);
      });
      errorMessageElement.appendChild(closeLink);
      return errorMessageElement;
    }
  
    function showTree(data) {
      var id = data.processId + '.' + data.routeId;
      var row = $(id);
      if (!row)
        return;
  
      row.textContent = '';
      formatRow(row, data);
    }
  
    function createAccessibilityTreeElement(data) {
      var treeElement = document.createElement('pre');
      var tree = data.tree;
      treeElement.textContent = tree;
      return treeElement;
    }
  
    return {
      initialize: initialize,
      showTree: showTree
    };
  });
  
  document.addEventListener('DOMContentLoaded', accessibility.initialize);
  