whole_func_string: function(key, value, writeAttr, attrName) {
          // TODO: decide whether or not to throw an error if "class"
          // is set through this function since it may cause $updateClass to
          // become unstable.
  
          var node = this.$$element[0],
              booleanKey = getBooleanAttrName(node, key),
              aliasedKey = getAliasedAttrName(key),
              observer = key,
              nodeName;
  
          if (booleanKey) {
            this.$$element.prop(key, value);
            attrName = booleanKey;
          } else if (aliasedKey) {
            this[aliasedKey] = value;
            observer = aliasedKey;
          }
  
          this[key] = value;
  
          // translate normalized key to actual key
          if (attrName) {
            this.$attr[key] = attrName;
          } else {
            attrName = this.$attr[key];
            if (!attrName) {
              this.$attr[key] = attrName = snake_case(key, '-');
            }
          }
  
          nodeName = nodeName_(this.$$element);
  
          // Sanitize img[srcset] values.
          if (nodeName === 'img' && key === 'srcset') {
            this[key] = value = sanitizeSrcset(value, '$set(\'srcset\', value)');
          }
  
          if (writeAttr !== false) {
            if (value === null || isUndefined(value)) {
              this.$$element.removeAttr(attrName);
            } else {
              if (SIMPLE_ATTR_NAME.test(attrName)) {
                this.$$element.attr(attrName, value);
              } else {
                setSpecialAttr(this.$$element[0], attrName, value);
              }
            }
          }
  
          // fire observers
          var $$observers = this.$$observers;
          if ($$observers) {
            forEach($$observers[observer], function(fn) {
              try {
                fn(value);
              } catch (e) {
                $exceptionHandler(e);
              }
            });
          }
        }
func_code_string: function(key, value, writeAttr, attrName) {
          // TODO: decide whether or not to throw an error if "class"
          // is set through this function since it may cause $updateClass to
          // become unstable.
  
          var node = this.$$element[0],
              booleanKey = getBooleanAttrName(node, key),
              aliasedKey = getAliasedAttrName(key),
              observer = key,
              nodeName;
  
          if (booleanKey) {
            this.$$element.prop(key, value);
            attrName = booleanKey;
          } else if (aliasedKey) {
            this[aliasedKey] = value;
            observer = aliasedKey;
          }
  
          this[key] = value;
  
          // translate normalized key to actual key
          if (attrName) {
            this.$attr[key] = attrName;
          } else {
            attrName = this.$attr[key];
            if (!attrName) {
              this.$attr[key] = attrName = snake_case(key, '-');
            }
          }
  
          nodeName = nodeName_(this.$$element);
  
          // Sanitize img[srcset] values.
          if (nodeName === 'img' && key === 'srcset') {
            this[key] = value = sanitizeSrcset(value, '$set(\'srcset\', value)');
          }
  
          if (writeAttr !== false) {
            if (value === null || isUndefined(value)) {
              this.$$element.removeAttr(attrName);
            } else {
              if (SIMPLE_ATTR_NAME.test(attrName)) {
                this.$$element.attr(attrName, value);
              } else {
                setSpecialAttr(this.$$element[0], attrName, value);
              }
            }
          }
  
          // fire observers
          var $$observers = this.$$observers;
          if ($$observers) {
            forEach($$observers[observer], function(fn) {
              try {
                fn(value);
              } catch (e) {
                $exceptionHandler(e);
              }
            });
          }
        }
func_documentation_string: Set a normalized attribute on the element in a way such that all directives
  can share the attribute. This function properly handles boolean attributes.
  @param {string} key Normalized key. (ie ngAttribute)
  @param {string|boolean} value The value to set. If `null` attribute will be deleted.
  @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.
  Defaults to true.
  @param {string=} attrName Optional none normalized name. Defaults to key.