text: /**
   * @license
   * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
   * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
   * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
   * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
   * Code distributed by Google as part of the polymer project is also
   * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
   */
  
  (function(scope) {
    'use strict';
  
    var ChildNodeInterface = scope.ChildNodeInterface;
    var GetElementsByInterface = scope.GetElementsByInterface;
    var Node = scope.wrappers.Node;
    var ParentNodeInterface = scope.ParentNodeInterface;
    var SelectorsInterface = scope.SelectorsInterface;
    var MatchesInterface = scope.MatchesInterface;
    var addWrapNodeListMethod = scope.addWrapNodeListMethod;
    var enqueueMutation = scope.enqueueMutation;
    var mixin = scope.mixin;
    var oneOf = scope.oneOf;
    var registerWrapper = scope.registerWrapper;
    var unsafeUnwrap = scope.unsafeUnwrap;
    var wrappers = scope.wrappers;
  
    var OriginalElement = window.Element;
  
    var matchesNames = [
      'matches',  // needs to come first.
      'mozMatchesSelector',
      'msMatchesSelector',
      'webkitMatchesSelector',
    ].filter(function(name) {
      return OriginalElement.prototype[name];
    });
  
    var matchesName = matchesNames[0];
  
    var originalMatches = OriginalElement.prototype[matchesName];
  
    function invalidateRendererBasedOnAttribute(element, name) {
      // Only invalidate if parent node is a shadow host.
      var p = element.parentNode;
      if (!p || !p.shadowRoot)
        return;
  
      var renderer = scope.getRendererForHost(p);
      if (renderer.dependsOnAttribute(name))
        renderer.invalidate();
    }
  
    function enqueAttributeChange(element, name, oldValue) {
      // This is not fully spec compliant. We should use localName (which might
      // have a different case than name) and the namespace (which requires us
      // to get the Attr object).
      enqueueMutation(element, 'attributes', {
        name: name,
        namespace: null,
        oldValue: oldValue
      });
    }
  
    var classListTable = new WeakMap();
  
    function Element(node) {
      Node.call(this, node);
    }
    Element.prototype = Object.create(Node.prototype);
    mixin(Element.prototype, {
      createShadowRoot: function() {
        var newShadowRoot = new wrappers.ShadowRoot(this);
        unsafeUnwrap(this).polymerShadowRoot_ = newShadowRoot;
  
        var renderer = scope.getRendererForHost(this);
        renderer.invalidate();
  
        // This is needed for IE - if you put elements directly on the root shadow
        // IE will leak, create head and body so we can append observers, etc.
        newShadowRoot.head = document.createElement('head');
        newShadowRoot.body = document.createElement('body');
  
        return newShadowRoot;
      },
  
      get shadowRoot() {
        return unsafeUnwrap(this).polymerShadowRoot_ || null;
      },
  
      // getDestinationInsertionPoints added in ShadowRenderer.js
  
      setAttribute: function(name, value) {
        var oldValue = unsafeUnwrap(this).getAttribute(name);
        unsafeUnwrap(this).setAttribute(name, value);
        enqueAttributeChange(this, name, oldValue);
        invalidateRendererBasedOnAttribute(this, name);
      },
  
      removeAttribute: function(name) {
        var oldValue = unsafeUnwrap(this).getAttribute(name);
        unsafeUnwrap(this).removeAttribute(name);
        enqueAttributeChange(this, name, oldValue);
        invalidateRendererBasedOnAttribute(this, name);
      },
  
      get classList() {
        var list = classListTable.get(this);
        if (!list) {
          list = unsafeUnwrap(this).classList;
          if (!list) return;
          list.ownerElement_ = this;
          classListTable.set(this, list);
        }
        return list;
      },
  
      get className() {
        return unsafeUnwrap(this).className;
      },
  
      set className(v) {
        this.setAttribute('class', v);
      },
  
      get id() {
        return unsafeUnwrap(this).id;
      },
  
      set id(v) {
        this.setAttribute('id', v);
      }
    });
  
    matchesNames.forEach(function(name) {
      if (name !== 'matches') {
        Element.prototype[name] = function(selector) {
          return this.matches(selector);
        };
      }
    });
  
    if (OriginalElement.prototype.webkitCreateShadowRoot) {
      Element.prototype.webkitCreateShadowRoot =
          Element.prototype.createShadowRoot;
    }
  
    mixin(Element.prototype, ChildNodeInterface);
    mixin(Element.prototype, GetElementsByInterface);
    mixin(Element.prototype, ParentNodeInterface);
    mixin(Element.prototype, SelectorsInterface);
    mixin(Element.prototype, MatchesInterface);
  
    registerWrapper(OriginalElement, Element,
                    document.createElementNS(null, 'x'));
  
    scope.invalidateRendererBasedOnAttribute = invalidateRendererBasedOnAttribute;
    scope.matchesNames = matchesNames;
    scope.originalMatches = originalMatches;
    scope.wrappers.Element = Element;
  })(window.ShadowDOMPolyfill);
  