text: define([
      "../core",
      "../core/access",
      "./support",
      "../var/rnothtmlwhite",
      "../selector"
  ], function (jQuery, access, support, rnothtmlwhite) {
  
      "use strict";
  
      var boolHook,
          attrHandle = jQuery.expr.attrHandle;
  
      jQuery.fn.extend({
          attr: function (name, value) {
              return access(this, jQuery.attr, name, value, arguments.length > 1);
          },
  
          removeAttr: function (name) {
              return this.each(function () {
                  jQuery.removeAttr(this, name);
              });
          }
      });
  
      jQuery.extend({
          attr: function (elem, name, value) {
              var ret, hooks,
                  nType = elem.nodeType;
  
              // Don't get/set attributes on text, comment and attribute nodes
              if (nType === 3 || nType === 8 || nType === 2) {
                  return;
              }
  
              // Fallback to prop when attributes are not supported
              if (typeof elem.getAttribute === "undefined") {
                  return jQuery.prop(elem, name, value);
              }
  
              // Attribute hooks are determined by the lowercase version
              // Grab necessary hook if one is defined
              if (nType !== 1 || !jQuery.isXMLDoc(elem)) {
                  hooks = jQuery.attrHooks[name.toLowerCase()] ||
                      ( jQuery.expr.match.bool.test(name) ? boolHook : undefined );
              }
  
              if (value !== undefined) {
                  if (value === null) {
                      jQuery.removeAttr(elem, name);
                      return;
                  }
  
                  if (hooks && "set" in hooks &&
                      ( ret = hooks.set(elem, value, name) ) !== undefined) {
                      return ret;
                  }
  
                  elem.setAttribute(name, value + "");
                  return value;
              }
  
              if (hooks && "get" in hooks && ( ret = hooks.get(elem, name) ) !== null) {
                  return ret;
              }
  
              ret = jQuery.find.attr(elem, name);
  
              // Non-existent attributes return null, we normalize to undefined
              return ret == null ? undefined : ret;
          },
  
          attrHooks: {
              type: {
                  set: function (elem, value) {
                      if (!support.radioValue && value === "radio" &&
                          jQuery.nodeName(elem, "input")) {
                          var val = elem.value;
                          elem.setAttribute("type", value);
                          if (val) {
                              elem.value = val;
                          }
                          return value;
                      }
                  }
              }
          },
  
          removeAttr: function (elem, value) {
              var name,
                  i = 0,
  
              // Attribute names can contain non-HTML whitespace characters
              // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
                  attrNames = value && value.match(rnothtmlwhite);
  
              if (attrNames && elem.nodeType === 1) {
                  while (( name = attrNames[i++] )) {
                      elem.removeAttribute(name);
                  }
              }
          }
      });
  
  // Hooks for boolean attributes
      boolHook = {
          set: function (elem, value, name) {
              if (value === false) {
  
                  // Remove boolean attributes when set to false
                  jQuery.removeAttr(elem, name);
              } else {
                  elem.setAttribute(name, name);
              }
              return name;
          }
      };
  
      jQuery.each(jQuery.expr.match.bool.source.match(/\w+/g), function (i, name) {
          var getter = attrHandle[name] || jQuery.find.attr;
  
          attrHandle[name] = function (elem, name, isXML) {
              var ret, handle,
                  lowercaseName = name.toLowerCase();
  
              if (!isXML) {
  
                  // Avoid an infinite loop by temporarily removing this function from the getter
                  handle = attrHandle[lowercaseName];
                  attrHandle[lowercaseName] = ret;
                  ret = getter(elem, name, isXML) != null ?
                      lowercaseName :
                      null;
                  attrHandle[lowercaseName] = handle;
              }
              return ret;
          };
      });
  
  });
  