orgsync/jquery-aria

View on GitHub
src/jquery.aria.js

Summary

Maintainability
C
1 day
Test Coverage
// Copyright (c) 2013 OrgSync, Inc.
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// version: 2.1.6
// homepage: https://github.com/orgsync/jquery-aria
// dependency: jQuery, ~> 1.7.1

(function($) {
  $.extend({
    // Public: Gets and sets ARIA attributes.
    //
    // elem  - The DOM or jQuery element.
    // key   - The String naming the ARIA attribute to get or set (default: null).
    // value - The value used to set the ARIA attribute (default: null).
    //
    // Examples
    //
    //   // get all
    //   jQuery.aria(element)
    //   # => {owns: 'foo', describedby: 'bar'}
    //
    //   // get
    //   jQuery.aria(element, 'owns')
    //   # => 'foo'
    //
    //   // set
    //   jQuery.aria(element, 'owns', 'baz')
    //   # => jQuery(element)
    //
    // Returns an Object.
    aria: function(elem, key, value) {
      elem = $(elem);

      if (arguments.length === 1) {
        var attributes = {};
        $.each(elem[0].attributes, function(i, value) {
          if (value.nodeName.match(/^aria-/)) {
            attributes[value.nodeName.replace(/^aria-/, '')] = value.nodeValue;
          }
        });

        return attributes;
      } else if (arguments.length === 2) {
        return elem.attr('aria-' + key);
      } else {
        return elem.attr('aria-' + key, value);
      }
    },

    // Public: Removes ARIA attributes.
    //
    // elem - The DOM or jQuery element.
    // key  - The String naming the ARIA attribute to remove (default: null).
    //
    // Examples
    //
    //   jQuery.removeAria(element)
    //   # => jQuery(element)
    //
    //   jQuery.removeAria(element, 'owns')
    //   # => jQuery(element)
    //
    // Returns a jQuery Object.
    removeAria: function(elem, keys) {
      elem = $(elem);

      if (arguments.length === 1) {
        keys = $.map(elem.aria(), function(_, k) {return k;});
      } else if (!$.isArray(keys)) {
        keys = keys.split(/\s+/);
      }

      for (var i = keys.length - 1; i >= 0; --i) {
        elem.removeAttr('aria-' + keys[i]);
      }

      return elem;
    },

    // Public: Checks for the existance of an ARIA attribute.
    //
    // elem - The DOM or jQuery element.
    //
    // Examples
    //
    //   jQuery.hasAria(element, 'owns')
    //   # => true
    //
    // Returns a Boolean.
    hasAria: function(elem) {
      elem = elem[0] || elem;

      for (var i = elem.attributes.length - 1; i >= 0; --i) {
        if (/^aria-/.test(elem.attributes[i].nodeName)) {
          return true;
        }
      }

      return false;
    }
  });

  $.fn.extend({
    // Public: Gets and sets ARIA attributes.
    //
    // key   - The String naming the ARIA attribute to get or set (default: null).
    // value - The value used to set the ARIA attribute (default: null).
    //
    // Examples
    //
    //   // get all
    //   element.aria()
    //   # => {owns: 'foo', describedby: 'bar'}
    //
    //   // get
    //   element.aria('owns')
    //   # => 'foo'
    //
    //   // set
    //   element.aria('owns', 'baz')
    //   # => element
    //
    // Returns an Object.
    aria: function() {
      var i, args = $.makeArray(arguments);

      if (arguments.length === 2) {
        for(i = this.length - 1; i >= 0; --i) {
          $.aria.apply($, [this[i]].concat(args));
        }

        return this;
      } else {
        return $.aria.apply($, [this].concat(args));
      }
    },

    // Public: Removes ARIA attributes.
    //
    // key - The String naming the ARIA attribute to remove (default: null).
    //
    // Examples
    //
    //   elements.removeAria()
    //   # => elements
    //
    //   element.removeAria('owns')
    //   # => element
    //
    // Returns the element(s).
    removeAria: function() {
      var i, args = $.makeArray(arguments);

      for(i = this.length - 1; i >= 0; --i) {
        $.removeAria.apply($, [this[i]].concat(args));
      }

      return this;
    },

    // Public: Adds roles to the ARIA "role" attribute.
    //
    // value - The String or Function returning a String of space separated
    //         roles. Functions are provided the index position of the element
    //         in the set and the existing role name(s) as arguments. Within the
    //         function, `this` refers to the current element in the set.
    //
    // Examples
    //
    //   element.addRole('menu navigation')
    //   # => element
    //
    //   elements.addRole(function(index, current_roles) {
    //     return 'menu navigation';
    //   })
    //   # => elements
    //
    // Returns the element(s).
    addRole: function(value) {
      var roles, i, elem, current_roles, j, roles_length;

      if ($.isFunction(value)) {
        return this.each(function(i) {
          elem = $(this);
          elem.addRole(value.call(this, i, elem.attr('role')));
        });
      }

      if (value && typeof value === 'string' && value !== '') {
        roles = value.split(/\s+/);

        for (i = this.length - 1; i >= 0; --i) {
          elem = this[i];
          current_roles = elem.getAttribute('role');

          if (current_roles && current_roles !== '') {
            current_roles = ' ' + current_roles + ' ';

            for (j = 0, roles_length = roles.length; j < roles_length; ++j) {
              if (current_roles.indexOf(' ' + roles[j] + ' ') < 0) {
                current_roles += roles[j] + ' ';
              }
            }

            elem.setAttribute('role', current_roles.trim());
          } else {
            elem.setAttribute('role', value);
          }
        }
      }

      return this;
    },

    // Public: Checks for the existance of a role.
    //
    // role_name - The String containing a role name.
    //
    // Examples
    //
    //   element.hasrole('menu')
    //   # => false
    //
    //   jQuery('div').hasrole('menu')
    //   # => true
    //
    // Returns a Boolean.
    hasRole: function(role_name) {
      var i, roles;

      for (i = this.length - 1; i >= 0; --i) {
        roles = this[i].getAttribute('role');

        if (roles && roles !== '') {
          roles = ' ' + roles + ' ';

          if (roles.indexOf(' ' + role_name + ' ') >= 0) {
            return true;
          }
        }
      }

      return false;
    },

    // Public: Removes roles from the ARIA "role" attribute.
    //
    // value - The String or Function returning a String of space separated
    //         roles. Functions are provided the index position of the element
    //         in the set and the existing role name(s) as arguments. Within the
    //         function, `this` refers to the current element in the set
    //         (default: null).
    //
    // Examples
    //
    //   // remove all roles
    //   element.removeRole()
    //   # => element
    //
    //   element.removeRole('menu navigation')
    //   # => element
    //
    //   elements.removeRole(function(index, current_roles) {
    //     return 'menu navigation';
    //   })
    //   # => elements
    //
    // Returns the element(s).
    removeRole: function(value) {
      var i, elem, current_roles, roles, j;

      if (arguments.length === 0) {
        for (i = this.length - 1; i >= 0; --i) {
          this[i].setAttribute('role', '');
        }

        return this;
      }

      if ($.isFunction(value)) {
        return this.each(function(i) {
          elem = $(this);
          elem.removeRole(value.call(this, i, elem.attr('role')));
        });
      }

      if (value && typeof value === 'string' && value !== '') {
        roles = value.split(/\s+/);

        for (i = this.length - 1; i >= 0; --i) {
          elem = this[i];

          current_roles = elem.getAttribute('role');

          if (current_roles && current_roles !== '') {
            current_roles = ' ' + current_roles + ' ';

            for (j = roles.length - 1; j >= 0; --j) {
              current_roles = current_roles.replace(' ' + roles[j] + ' ', ' ');
            }

            elem.setAttribute('role', current_roles.replace(/\s+/, ' ').trim());
          }
        }
      }

      return this;
    },

    // Public: Adds or removes roles from the ARIA "role" attribute.
    //
    // value - The String or Function returning a String of space separated
    //         roles. Functions are provided the index position of the element
    //         in the set, the existing role name(s) and the value of the `add`
    //         argument provided in the original function call as arguments.
    //         Within the function, `this` refers to the current element in the
    //         set (default: null).
    // add   - The Boolean indicating the forced addition or removal of roles.
    //         Passing `true` forces the roles to be added. Passing `false`
    //         forces the roles to be removed (default: null).
    //
    // Examples
    //
    //   // add "menu" to all roles
    //   element.toggleRole('menu', true)
    //   # => element
    //
    //   // remove "menu" from all roles
    //   element.toggleRole('menu', false)
    //   # => element
    //
    //   // toggle "menu" role
    //   elements.toggleRole('menu')
    //   # => elements
    //
    //   elements.toggleRole(function(index, current_roles, add) {
    //     return 'menu navigation';
    //   })
    //   # => elements
    //
    // Returns the element(s).
    toggleRole: function(value, add) {
      if ($.isFunction(value)) {
        return this.each(function(i) {
          var elem = $(this);
          elem.toggleRole(value.call(this, i, elem.attr('role'), add), add);
        });
      }

      if (add === true) {
        this.addRole(value);
      } else if (add === false) {
        this.removeRole(value);
      } else {
        var current_roles, roles, i;

        current_roles = ' ' + this.attr('role') + ' ';
        roles = value.split(/\s+/);

        for (i = roles.length - 1; i >= 0; --i) {
          current_roles.indexOf(' ' + roles[i] + ' ') < 0 ?
            this.addRole(roles[i]) :
            this.removeRole(roles[i]);
        }
      }

      return this;
    }
  });
})(jQuery);