You are here

a11y.module in Accessibility toolkit 7

A11y accessibiliy toolkit module to help people.

File

a11y.module
View source
<?php

/**
 * @file A11y accessibiliy toolkit module to help people.
 */

/**
 * Implements hook_permission().
 */
function a11y_permission() {
  return array(
    'view a11y simulations' => array(
      'title' => t('View A11y simulations'),
      'description' => t('User can see the different simulators that the a11y module provides. These are intended to help people understand different accessibility concerns and should not be enabled for general site users unless the intention is teaching about the different conditions.'),
    ),
  );
}

/**
 * Implements hook_block_info().
 */
function a11y_block_info() {
  $blocks['a11y'] = array(
    'info' => t('Accessibility suite'),
    'cache' => DRUPAL_CACHE_GLOBAL,
  );
  return $blocks;
}

/**
 * Implements hook_block_view().
 */
function a11y_block_view($delta = '') {
  $block = array();
  switch ($delta) {
    case 'a11y':
      $block['subject'] = t('Accessibility options');
      $block['content'] = a11y_a11y_block();
      break;
  }
  return $block;
}

/**
 * Renders the default a11y block.
 */
function a11y_a11y_block($render = TRUE) {

  // apply the css / js as selected
  a11y_apply_a11y();
  if ($render) {
    $output = '';
  }
  else {
    $output = array();
  }

  // assemble the user alterations to the interface
  $alters = array(
    '#type' => 'fieldset',
    '#title' => t('Interface'),
    '#description' => t('Adjust the interface to make it easier to use for different conditions.'),
    '#collapsed' => TRUE,
    '#collapsible' => TRUE,
    '#weight' => -10,
    '#attributes' => array(
      'class' => array(
        'collapsible',
        'form-wrapper',
      ),
    ),
    '#materialize' => array(
      'type' => 'collapsible',
      'icon' => 'brightness_medium',
    ),
  );

  // textsize default state
  if (variable_get('a11y_textsize', 1)) {
    $icon_path = base_path() . drupal_get_path('module', 'a11y') . '/plugins/icons/';
    $alters['textsize'] = array(
      '#markup' => '
      <div class="a11y-textsize-controls">
        <div class="a11y-textsize-controls-label">' . t('Interface Size') . '</div>
        <div class="a11y-textsize-controls-body row">
          <div class="col s4">
            <a data-voicecommand="smaller text" href="#textsizesmaller" onclick="Drupal.a11y.textsize(-1);" class="a11y-operation-icons a11y-decrease">
              <span>Smaller</span>
              <img alt="' . t('Decrease text size') . '" title="' . t('Decrease') . '" src="' . $icon_path . 'text-decrease.png" width="24" height="24" />
            </a>
          </div>
          <div class="col s4">
            <a data-voicecommand="larger text" href="#textsizelarger" onclick="Drupal.a11y.textsize(1);" class="a11y-operation-icons a11y-increase">
              <span>Larger</span>
              <img alt="' . t('Increase text size') . '" title="' . t('Increase') . '" src="' . $icon_path . 'text-increase.png" width="24" height="24" />
            </a>
          </div>
          <div class="col s4">
            <a data-voicecommand="normal text" href="#textsizereset" onclick="Drupal.a11y.textsize(0);" class="a11y-operation-icons a11y-reset">
              <span>Reset</span>
              <img alt="' . t('Reset text size') . '" title="' . t('Reset') . '" src="' . $icon_path . 'text-reset.png" width="24" height="24" />
            </a>
          </div>
        </div>
      </div>',
      '#weight' => -10,
    );
  }

  // support contrast settings
  if (variable_get('a11y_contrast', 1)) {
    $alters['contrast'] = array(
      '#type' => 'checkbox',
      '#id' => 'a11y_contrast_checkbox',
      '#title' => t('High contrast mode'),
      '#default_value' => 0,
      '#description' => t('This renders the document in high contrast mode.'),
      '#weight' => -9,
      '#attributes' => array(
        'data-voicecommand' => 'high contrast mode (on)(off)',
      ),
    );
    $alters['invert'] = array(
      '#type' => 'checkbox',
      '#id' => 'a11y_invert_checkbox',
      '#title' => t('Invert colors'),
      '#default_value' => 0,
      '#description' => t('This renders the document as white on black'),
      '#weight' => -8,
      '#attributes' => array(
        'data-voicecommand' => 'invert colors (again)',
      ),
    );
  }

  // support animation disabling
  if (variable_get('a11y_animation', 1)) {

    // animation default state
    $alters['animation'] = array(
      '#type' => 'checkbox',
      '#id' => 'a11y_animation_checkbox',
      '#title' => t('Disable interface animations'),
      '#default_value' => 0,
      '#description' => t('This can help those with trouble processing rapid screen movements.'),
      '#weight' => -7,
      '#attributes' => array(
        'data-voicecommand' => 'toggle interface animations',
      ),
    );
  }

  // open dyslexic font
  if (variable_get('a11y_opendyslexic', 1)) {
    $alters['opendyslexic'] = array(
      '#type' => 'checkbox',
      '#id' => 'a11y_opendyslexic_checkbox',
      '#title' => t('Optimize fonts for dyslexia'),
      '#default_value' => 0,
      '#description' => t('This loads a font easier to read for people with dyslexia.'),
      '#weight' => -6,
      '#attributes' => array(
        'data-voicecommand' => 'toggle dyslexic (font)',
      ),
    );
  }

  // support voicecommander disabling
  if (user_access('use voice commander')) {

    // voicecommander default state
    $alters['voicecommander'] = array(
      '#type' => 'checkbox',
      '#id' => 'a11y_voicecommander_checkbox',
      '#title' => t('Continuously listen for voice commands'),
      '#default_value' => 0,
      '#description' => t('This allows for more natural speech with working with the system.'),
      '#weight' => -5,
      '#attributes' => array(
        'data-voicecommand' => 'toggle always listening',
      ),
    );

    // speechSynth seting
    if (variable_get('a11y_speechsynth', 1)) {
      $alters['a11y_speechsynth'] = array(
        '#type' => 'checkbox',
        '#id' => 'a11y_speechsynth_checkbox',
        '#title' => t('Read to me'),
        '#default_value' => 0,
        '#description' => t('This will speak the page\'s content to you.'),
        '#weight' => -4,
        '#attributes' => array(
          'data-voicecommand' => 'read to me',
        ),
      );
    }
  }
  if ($render) {

    // render any aleration array items we have
    $output .= drupal_render($alters);
  }
  else {
    $output['alters'] = $alters;
  }

  // add in the simulations if they are allowed to see them
  if (user_access('view a11y simulations')) {
    $sim = array(
      '#type' => 'fieldset',
      '#title' => t('Simulators'),
      '#description' => t('Simulate different accessibility conditions. This is useful to see how your site would possibly be viewed by people with different conditions.'),
      '#collapsed' => TRUE,
      '#collapsible' => TRUE,
      '#weight' => -9,
      '#attributes' => array(
        'class' => array(
          'collapsible',
          'form-wrapper',
          'collapsed',
        ),
      ),
      '#materialize' => array(
        'type' => 'collapsible',
        'icon' => 'videogame_asset',
      ),
    );

    // support for dyslexia simulator
    if (variable_get('a11y_sim_dyslexia', 1)) {
      $sim['dyslexia'] = array(
        '#type' => 'checkbox',
        '#id' => 'a11y_sim_dyslexia_checkbox',
        '#title' => t('Dyslexia'),
        '#default_value' => 0,
        '#description' => t('This will simulate how a dyslexic might view your material.'),
        '#weight' => -10,
      );
      drupal_add_js(drupal_get_path('module', 'a11y') . '/simulations/dyslexia/dyslexia.js');
    }

    // support for field-loss simulator
    if (variable_get('a11y_sim_field_loss', 1)) {
      $sim['field_loss'] = array(
        '#type' => 'select',
        '#id' => 'a11y_sim_field_loss_select',
        '#title' => t('Field loss'),
        '#default_value' => '',
        '#options' => array(
          '' => t('No field loss'),
          'central' => t('Central loss'),
          'peripheral' => t('Peripheral loss'),
        ),
        '#description' => t('This will simulate how someone with vision field loss might view your material.'),
        '#weight' => -10,
      );
      drupal_add_js(drupal_get_path('module', 'a11y') . '/simulations/field-loss/field-loss.js');
      drupal_add_css(drupal_get_path('module', 'a11y') . '/simulations/field-loss/field-loss.css');
    }

    // support for colorblind simulator
    if (variable_get('a11y_sim_colorblind', 1)) {
      $options = array(
        '' => t('No color blindness'),
        'achromatopsia' => t('Achromatopsia'),
        'achromatomaly' => t('Achromatomaly'),
        'deuteranopia' => t('Deuteranopia'),
        'deuteranomaly' => t('Deuteranomaly'),
        'protanopia' => t('Protanopia'),
        'protanomaly' => t('Protanomaly'),
        'tritanopia' => t('Tritanopia'),
        'tritanomaly' => t('Tritanomaly'),
      );
      $sim['colorblind'] = array(
        '#type' => 'select',
        '#id' => 'a11y_sim_colorblind_select',
        '#title' => t('Color blind'),
        '#default_value' => '',
        '#options' => $options,
        '#description' => t('This will simulate different variations of color blindness.'),
        '#weight' => -11,
      );

      // add in the JS
      drupal_add_js(drupal_get_path('module', 'a11y') . '/simulations/colorblind/colorblind.js');

      // seems weird but we need to build the CSS dynamically
      $filterpath = url(drupal_get_path('module', 'a11y') . '/simulations/colorblind/filters.svg', array(
        'absolute' => TRUE,
      ));
      $colorblindcss = '';
      array_shift($options);
      foreach ($options as $option => $name) {
        $colorblindcss .= '.' . $option . ' {
          -webkit-filter: url("' . $filterpath . '#' . $option . '");
          filter: url("' . $filterpath . '#' . $option . '"); }';
      }

      // kick it out inline
      drupal_add_css($colorblindcss, array(
        'type' => 'inline',
      ));
    }
    if ($render) {

      // render any aleration array items we have
      $output .= drupal_render($sim);
    }
    else {
      $output['sim'] = $sim;
    }
  }
  return $output;
}

/**
 * Implements hook_menu().
 */
function a11y_menu() {
  $items['admin/config/system/a11y'] = array(
    'title' => 'Accessibility settings',
    'description' => 'Change which accessibility settings to apply.',
    'type' => MENU_NORMAL_ITEM,
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'a11y_admin_settings',
    ),
    'access arguments' => array(
      'access administration pages',
    ),
  );
  return $items;
}

/**
 * Admin settings form.
 */
function a11y_admin_settings($form, &$form_state) {
  $form['sim'] = array(
    '#type' => 'fieldset',
    '#title' => t('Simulators'),
    '#description' => t('Allow for simulating different accessibility issues. This is useful to see how your site would possibly be viewed by people with different conditions. This is a mode intended for developers and site builders as the modes produce accessibility issues by design to help you empathize.'),
    '#collapsed' => TRUE,
    '#collapsible' => TRUE,
  );
  $form['sim']['a11y_sim_dyslexia'] = array(
    '#type' => 'checkbox',
    '#title' => t('Allow dyslexia simulator'),
    '#default_value' => variable_get('a11y_sim_dyslexia', 1),
    '#description' => t('This produces an effect to content that attempts to simulate the affects of dyslexia.'),
    '#required' => FALSE,
  );
  $form['sim']['a11y_sim_field_loss'] = array(
    '#type' => 'checkbox',
    '#title' => t('Allow field loss simulator'),
    '#default_value' => variable_get('a11y_sim_field_loss', 1),
    '#description' => t('This produces an effect to content that attempts to simulate the affects of field loss.'),
    '#required' => FALSE,
  );
  $form['sim']['a11y_sim_colorblind'] = array(
    '#type' => 'checkbox',
    '#title' => t('Allow color blind simulator'),
    '#default_value' => variable_get('a11y_sim_colorblind', 1),
    '#description' => t('Manipulates content to filter it through different types of color blindness.'),
    '#required' => FALSE,
  );
  $form['config'] = array(
    '#type' => 'fieldset',
    '#title' => t('Button configuration'),
    '#description' => t('Which accessibility options appear in the block.'),
    '#collapsed' => FALSE,
    '#collapsible' => TRUE,
  );

  // domain default state
  $form['config']['a11y_domain'] = array(
    '#type' => 'textfield',
    '#title' => t('Cookie domain'),
    '#default_value' => variable_get('a11y_domain', ''),
    '#description' => t('Define the scope of the accessibility settings. This way you can keep UX patterns the same across subdomains for example.'),
    '#required' => FALSE,
  );

  // opendyslexic default state
  $form['config']['a11y_opendyslexic'] = array(
    '#type' => 'checkbox',
    '#title' => t('Allow open dyslexic font'),
    '#default_value' => variable_get('a11y_opendyslexic', 1),
    '#description' => t('This loads a css file that allows the user to forcibly override the font used by your site to be Open dyslexic, a font developed for those with dyslexia. You can find out more at http://opendyslexic.org/'),
    '#required' => FALSE,
  );

  // a11y_speechsynth default state
  $form['config']['a11y_speechsynth'] = array(
    '#type' => 'checkbox',
    '#title' => t('Allow reading body of text to the user'),
    '#default_value' => variable_get('a11y_speechsynth', 1),
    '#description' => t('This will use a browser based computer voice in order to read the text of the page to the user.'),
    '#required' => FALSE,
  );
  $form['config']['a11y_speechsynthSelector'] = array(
    '#type' => 'textfield',
    '#title' => t('jQuery Selector for what to read when selected.'),
    '#default_value' => variable_get('a11y_speechsynthSelector', 'article'),
    '#description' => t('This targets the field, converts it to just text() and then will read it to the end user.'),
    '#required' => FALSE,
  );

  // contrast default state
  $form['config']['a11y_contrast'] = array(
    '#type' => 'checkbox',
    '#title' => t('Allow contrast'),
    '#default_value' => variable_get('a11y_contrast', 1),
    '#description' => t('Allow the user to adjust the contrast of your site.'),
    '#required' => FALSE,
  );

  // textsize default state
  $form['config']['a11y_textsize'] = array(
    '#type' => 'checkbox',
    '#title' => t('Allow Text resize'),
    '#default_value' => variable_get('a11y_textsize', 1),
    '#description' => t('Allow the user to adjust the text size of your content.'),
    '#required' => FALSE,
  );

  // animation default state
  $form['config']['a11y_animation'] = array(
    '#type' => 'checkbox',
    '#title' => t('Allow disabling animation'),
    '#default_value' => variable_get('a11y_animation', 1),
    '#description' => t('Allow the user to disable css/js animations on your site.'),
    '#required' => FALSE,
  );
  return system_settings_form($form);
}

/**
 * Callback to load the right js / css needed for supported plugins.
 */
function a11y_apply_a11y() {
  drupal_add_library('system', 'jquery.cookie');
  drupal_add_js(drupal_get_path('module', 'a11y') . '/a11y.js', array(
    'type' => 'file',
    'scope' => 'footer',
    'weight' => -1000,
  ));

  // pass variables to js
  $js_variables = array(
    'a11y' => array(
      'path' => base_path() . drupal_get_path('module', 'a11y') . '/',
      'domain' => variable_get('a11y_domain', ''),
      'factor' => 1,
    ),
  );
  $plugin_path = drupal_get_path('module', 'a11y') . '/plugins/';
  $plugin_js_opts = array(
    'type' => 'file',
    'scope' => 'footer',
    'weight' => 1000,
  );
  $sim_path = drupal_get_path('module', 'a11y') . '/simulations/';
  if (variable_get('a11y_opendyslexic', 1)) {
    $js_variables['a11y']['opendyslexic'] = 1;
    drupal_add_js($plugin_path . 'opendyslexic/opendyslexic.js', $plugin_js_opts);
  }
  if (variable_get('a11y_contrast', 1)) {
    $js_variables['a11y']['contrast'] = 1;
    drupal_add_js($plugin_path . 'contrast/contrast.js', $plugin_js_opts);
  }
  if (variable_get('a11y_animation', 1)) {
    $js_variables['a11y']['animation'] = 1;
    drupal_add_js($plugin_path . 'animation/animation.js', $plugin_js_opts);
  }
  if (user_access('use voice commander')) {
    $js_variables['a11y']['voicecommander'] = 1;
    drupal_add_js($plugin_path . 'voicecommander/voicecommander.js', $plugin_js_opts);
    if (variable_get('a11y_speechsynth', 1)) {
      $js_variables['a11y']['speechsynth'] = 1;
      $js_variables['a11y']['speechSynthSelector'] = variable_get('a11y_speechsynthSelector', 'article');
      drupal_add_js($plugin_path . 'speechsynth/speechsynth.js', $plugin_js_opts);
    }
  }
  if (variable_get('a11y_textsize', 1)) {
    $js_variables['a11y']['textsize'] = 1;
    drupal_add_js($plugin_path . 'textsize/textsize.js', $plugin_js_opts);
  }
  if (variable_get('a11y_sim_dyslexia', 1)) {
    $js_variables['a11y']['sim']['dyslexia'] = 1;
  }
  if (variable_get('a11y_sim_field_loss', 1)) {
    $js_variables['a11y']['sim']['field_loss'] = 1;
  }
  if (variable_get('a11y_sim_colorblind', 1)) {
    $js_variables['a11y']['sim']['colorblind'] = 1;
  }
  drupal_add_js($js_variables, array(
    'type' => 'setting',
    'scope' => 'footer',
    'weight' => 1000,
  ));
}

/**
 * Implements hook_fa_a11y().
 * Returns the accessibility block to foundation access.
 */
function a11y_fa_a11y() {
  return a11y_a11y_block(FALSE);
}

Functions

Namesort descending Description
a11y_a11y_block Renders the default a11y block.
a11y_admin_settings Admin settings form.
a11y_apply_a11y Callback to load the right js / css needed for supported plugins.
a11y_block_info Implements hook_block_info().
a11y_block_view Implements hook_block_view().
a11y_fa_a11y Implements hook_fa_a11y(). Returns the accessibility block to foundation access.
a11y_menu Implements hook_menu().
a11y_permission Implements hook_permission().