nothrem/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);