Convert legacy Polyemer elements to class-based

This commit converts almost all Polymer elements from Polymer-function
based components to class-based components. There are few files which
should be converted manually after this commit.

Change-Id: I9e597e79053e0a6b5d5c0f1b54676d11b9d81db7
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js
index 8eb39891..3ce87f8 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js
@@ -24,57 +24,67 @@
     LARGE: 1000,
   };
 
-  Polymer({
-    is: 'gr-change-list-item',
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.ChangeTableMixin
+    * @appliesMixin Gerrit.PathListMixin
+    * @appliesMixin Gerrit.RESTClientMixin
+    * @appliesMixin Gerrit.URLEncodingMixin
+    */
+  class GrChangeListItem extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+    Gerrit.ChangeTableBehavior,
+    Gerrit.PathListBehavior,
+    Gerrit.RESTClientBehavior,
+    Gerrit.URLEncodingBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-change-list-item'; }
 
-    properties: {
-      visibleChangeTableColumns: Array,
-      labelNames: {
-        type: Array,
-      },
+    static get properties() {
+      return {
+        visibleChangeTableColumns: Array,
+        labelNames: {
+          type: Array,
+        },
 
-      /** @type {?} */
-      change: Object,
-      changeURL: {
-        type: String,
-        computed: '_computeChangeURL(change)',
-      },
-      statuses: {
-        type: Array,
-        computed: 'changeStatuses(change)',
-      },
-      showStar: {
-        type: Boolean,
-        value: false,
-      },
-      showNumber: Boolean,
-      _changeSize: {
-        type: String,
-        computed: '_computeChangeSize(change)',
-      },
-      _dynamicCellEndpoints: {
-        type: Array,
-      },
-    },
-
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-      Gerrit.ChangeTableBehavior,
-      Gerrit.PathListBehavior,
-      Gerrit.RESTClientBehavior,
-      Gerrit.URLEncodingBehavior,
-    ],
+        /** @type {?} */
+        change: Object,
+        changeURL: {
+          type: String,
+          computed: '_computeChangeURL(change)',
+        },
+        statuses: {
+          type: Array,
+          computed: 'changeStatuses(change)',
+        },
+        showStar: {
+          type: Boolean,
+          value: false,
+        },
+        showNumber: Boolean,
+        _changeSize: {
+          type: String,
+          computed: '_computeChangeSize(change)',
+        },
+        _dynamicCellEndpoints: {
+          type: Array,
+        },
+      };
+    }
 
     attached() {
+      super.attached();
       Gerrit.awaitPluginsLoaded().then(() => {
         this._dynamicCellEndpoints = Gerrit._endpoints.getDynamicEndpoints(
             'change-list-item-cell');
       });
-    },
+    }
 
     _computeChangeURL(change) {
       return Gerrit.Nav.getUrlForChange(change);
-    },
+    }
 
     _computeLabelTitle(change, labelName) {
       const label = change.labels[labelName];
@@ -85,7 +95,7 @@
         return labelName + '\nby ' + significantLabel.name;
       }
       return labelName;
-    },
+    }
 
     _computeLabelClass(change, labelName) {
       const label = change.labels[labelName];
@@ -112,7 +122,7 @@
         classes['u-gray-background'] = true;
       }
       return Object.keys(classes).sort().join(' ');
-    },
+    }
 
     _computeLabelValue(change, labelName) {
       const label = change.labels[labelName];
@@ -130,22 +140,22 @@
         return label.value;
       }
       return '';
-    },
+    }
 
     _computeRepoUrl(change) {
       return Gerrit.Nav.getUrlForProjectChanges(change.project, true,
           change.internalHost);
-    },
+    }
 
     _computeRepoBranchURL(change) {
       return Gerrit.Nav.getUrlForBranch(change.branch, change.project, null,
           change.internalHost);
-    },
+    }
 
     _computeTopicURL(change) {
       if (!change.topic) { return ''; }
       return Gerrit.Nav.getUrlForTopic(change.topic, change.internalHost);
-    },
+    }
 
     /**
      * Computes the display string for the project column. If there is a host
@@ -162,7 +172,7 @@
       if (change.internalHost) { str += change.internalHost + '/'; }
       str += truncate ? this.truncatePath(change.project, 2) : change.project;
       return str;
-    },
+    }
 
     _computeSizeTooltip(change) {
       if (change.insertions + change.deletions === 0 ||
@@ -171,7 +181,7 @@
       } else {
         return `+${change.insertions}, -${change.deletions}`;
       }
-    },
+    }
 
     /**
      * TShirt sizing is based on the following paper:
@@ -193,7 +203,7 @@
       } else {
         return 'XL';
       }
-    },
+    }
 
     toggleReviewed() {
       const newVal = !this.change.reviewed;
@@ -203,6 +213,8 @@
         composed: true,
         detail: {change: this.change, reviewed: newVal},
       }));
-    },
-  });
+    }
+  }
+
+  customElements.define(GrChangeListItem.is, GrChangeListItem);
 })();
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.js b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.js
index 02e9a04..49aa1eb 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.js
@@ -29,44 +29,49 @@
 
   const LIMIT_OPERATOR_PATTERN = /\blimit:(\d+)/i;
 
-  Polymer({
-    is: 'gr-change-list-view',
-
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.URLEncodingMixin
+    */
+  class GrChangeListView extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+    Gerrit.FireBehavior,
+    Gerrit.URLEncodingBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-change-list-view'; }
     /**
      * Fired when the title of the page should change.
      *
      * @event title-change
      */
 
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-      Gerrit.FireBehavior,
-      Gerrit.URLEncodingBehavior,
-    ],
-
-    properties: {
+    static get properties() {
+      return {
       /**
        * URL params passed from the router.
        */
-      params: {
-        type: Object,
-        observer: '_paramsChanged',
-      },
+        params: {
+          type: Object,
+          observer: '_paramsChanged',
+        },
 
-      /**
+        /**
        * True when user is logged in.
        */
-      _loggedIn: {
-        type: Boolean,
-        computed: '_computeLoggedIn(account)',
-      },
+        _loggedIn: {
+          type: Boolean,
+          computed: '_computeLoggedIn(account)',
+        },
 
-      account: {
-        type: Object,
-        value: null,
-      },
+        account: {
+          type: Object,
+          value: null,
+        },
 
-      /**
+        /**
        * State persisted across restamps of the element.
        *
        * Need sub-property declaration since it is used in template before
@@ -74,66 +79,71 @@
        * @type {{ selectedChangeIndex: (number|undefined) }}
        *
        */
-      viewState: {
-        type: Object,
-        notify: true,
-        value() { return {}; },
-      },
+        viewState: {
+          type: Object,
+          notify: true,
+          value() { return {}; },
+        },
 
-      preferences: Object,
+        preferences: Object,
 
-      _changesPerPage: Number,
+        _changesPerPage: Number,
 
-      /**
+        /**
        * Currently active query.
        */
-      _query: {
-        type: String,
-        value: '',
-      },
+        _query: {
+          type: String,
+          value: '',
+        },
 
-      /**
+        /**
        * Offset of currently visible query results.
        */
-      _offset: Number,
+        _offset: Number,
 
-      /**
+        /**
        * Change objects loaded from the server.
        */
-      _changes: {
-        type: Array,
-        observer: '_changesChanged',
-      },
+        _changes: {
+          type: Array,
+          observer: '_changesChanged',
+        },
 
-      /**
+        /**
        * For showing a "loading..." string during ajax requests.
        */
-      _loading: {
-        type: Boolean,
-        value: true,
-      },
+        _loading: {
+          type: Boolean,
+          value: true,
+        },
 
-      /** @type {?String} */
-      _userId: {
-        type: String,
-        value: null,
-      },
+        /** @type {?String} */
+        _userId: {
+          type: String,
+          value: null,
+        },
 
-      /** @type {?String} */
-      _repo: {
-        type: String,
-        value: null,
-      },
-    },
+        /** @type {?String} */
+        _repo: {
+          type: String,
+          value: null,
+        },
+      };
+    }
 
-    listeners: {
-      'next-page': '_handleNextPage',
-      'previous-page': '_handlePreviousPage',
-    },
+    created() {
+      super.created();
+      this.addEventListener('next-page',
+          () => this._handleNextPage());
+      this.addEventListener('previous-page',
+          () => this._handlePreviousPage());
+    }
 
     attached() {
+      super.attached();
       this._loadPreferences();
-    },
+    }
 
     _paramsChanged(value) {
       if (value.view !== Gerrit.Nav.View.SEARCH) { return; }
@@ -170,7 +180,7 @@
         this._changes = changes;
         this._loading = false;
       });
-    },
+    }
 
     _loadPreferences() {
       return this.$.restAPI.getLoggedIn().then(loggedIn => {
@@ -182,20 +192,20 @@
           this.preferences = {};
         }
       });
-    },
+    }
 
     _replaceCurrentLocation(url) {
       window.location.replace(url);
-    },
+    }
 
     _getChanges() {
       return this.$.restAPI.getChanges(this._changesPerPage, this._query,
           this._offset);
-    },
+    }
 
     _getPreferences() {
       return this.$.restAPI.getPreferences();
-    },
+    }
 
     _limitFor(query, defaultLimit) {
       const match = query.match(LIMIT_OPERATOR_PATTERN);
@@ -203,7 +213,7 @@
         return defaultLimit;
       }
       return parseInt(match[1], 10);
-    },
+    }
 
     _computeNavLink(query, offset, direction, changesPerPage) {
       // Offset could be a string when passed from the router.
@@ -211,32 +221,32 @@
       const limit = this._limitFor(query, changesPerPage);
       const newOffset = Math.max(0, offset + (limit * direction));
       return Gerrit.Nav.getUrlForSearchQuery(query, newOffset);
-    },
+    }
 
     _computePrevArrowClass(offset) {
       return offset === 0 ? 'hide' : '';
-    },
+    }
 
     _computeNextArrowClass(changes) {
       const more = changes.length && changes[changes.length - 1]._more_changes;
       return more ? '' : 'hide';
-    },
+    }
 
     _computeNavClass(loading) {
       return loading || !this._changes || !this._changes.length ? 'hide' : '';
-    },
+    }
 
     _handleNextPage() {
       if (this.$.nextArrow.hidden) { return; }
       page.show(this._computeNavLink(
           this._query, this._offset, 1, this._changesPerPage));
-    },
+    }
 
     _handlePreviousPage() {
       if (this.$.prevArrow.hidden) { return; }
       page.show(this._computeNavLink(
           this._query, this._offset, -1, this._changesPerPage));
-    },
+    }
 
     _changesChanged(changes) {
       this._userId = null;
@@ -255,28 +265,30 @@
       if (REPO_QUERY_PATTERN.test(this._query)) {
         this._repo = changes[0].project;
       }
-    },
+    }
 
     _computeHeaderClass(id) {
       return id ? '' : 'hide';
-    },
+    }
 
     _computePage(offset, changesPerPage) {
       return offset / changesPerPage + 1;
-    },
+    }
 
     _computeLoggedIn(account) {
       return !!(account && Object.keys(account).length > 0);
-    },
+    }
 
     _handleToggleStar(e) {
       this.$.restAPI.saveChangeStarred(e.detail.change._number,
           e.detail.starred);
-    },
+    }
 
     _handleToggleReviewed(e) {
       this.$.restAPI.saveChangeReviewed(e.detail.change._number,
           e.detail.reviewed);
-    },
-  });
+    }
+  }
+
+  customElements.define(GrChangeListView.is, GrChangeListView);
 })();
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
index 5006f1e..5ac4fcd 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list/gr-change-list.js
@@ -22,9 +22,25 @@
   const LABEL_PREFIX_INVALID_PROLOG = 'Invalid-Prolog-Rules-Label-Name--';
   const MAX_SHORTCUT_CHARS = 5;
 
-  Polymer({
-    is: 'gr-change-list',
-
+  /**
+    * @appliesMixin Gerrit.BaseUrlMixin
+    * @appliesMixin Gerrit.ChangeTableMixin
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.KeyboardShortcutMixin
+    * @appliesMixin Gerrit.RESTClientMixin
+    * @appliesMixin Gerrit.URLEncodingMixin
+    */
+  class GrChangeList extends Polymer.mixinBehaviors( [
+    Gerrit.BaseUrlBehavior,
+    Gerrit.ChangeTableBehavior,
+    Gerrit.FireBehavior,
+    Gerrit.KeyboardShortcutBehavior,
+    Gerrit.RESTClientBehavior,
+    Gerrit.URLEncodingBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-change-list'; }
     /**
      * Fired when next page key shortcut was pressed.
      *
@@ -37,28 +53,25 @@
      * @event previous-page
      */
 
-    hostAttributes: {
-      tabindex: 0,
-    },
-
-    properties: {
+    static get properties() {
+      return {
       /**
        * The logged-in user's account, or an empty object if no user is logged
        * in.
        */
-      account: {
-        type: Object,
-        value: null,
-      },
-      /**
+        account: {
+          type: Object,
+          value: null,
+        },
+        /**
        * An array of ChangeInfo objects to render.
        * https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#change-info
        */
-      changes: {
-        type: Array,
-        observer: '_changesChanged',
-      },
-      /**
+        changes: {
+          type: Array,
+          observer: '_changesChanged',
+        },
+        /**
        * ChangeInfo objects grouped into arrays. The sections and changes
        * properties should not be used together.
        *
@@ -68,56 +81,46 @@
        *   results: !Array<!Object>
        * }>}
        */
-      sections: {
-        type: Array,
-        value() { return []; },
-      },
-      labelNames: {
-        type: Array,
-        computed: '_computeLabelNames(sections)',
-      },
-      _dynamicHeaderEndpoints: {
-        type: Array,
-      },
-      selectedIndex: {
-        type: Number,
-        notify: true,
-      },
-      showNumber: Boolean, // No default value to prevent flickering.
-      showStar: {
-        type: Boolean,
-        value: false,
-      },
-      showReviewedState: {
-        type: Boolean,
-        value: false,
-      },
-      keyEventTarget: {
-        type: Object,
-        value() { return document.body; },
-      },
-      changeTableColumns: Array,
-      visibleChangeTableColumns: Array,
-      preferences: Object,
-    },
+        sections: {
+          type: Array,
+          value() { return []; },
+        },
+        labelNames: {
+          type: Array,
+          computed: '_computeLabelNames(sections)',
+        },
+        _dynamicHeaderEndpoints: {
+          type: Array,
+        },
+        selectedIndex: {
+          type: Number,
+          notify: true,
+        },
+        showNumber: Boolean, // No default value to prevent flickering.
+        showStar: {
+          type: Boolean,
+          value: false,
+        },
+        showReviewedState: {
+          type: Boolean,
+          value: false,
+        },
+        keyEventTarget: {
+          type: Object,
+          value() { return document.body; },
+        },
+        changeTableColumns: Array,
+        visibleChangeTableColumns: Array,
+        preferences: Object,
+      };
+    }
 
-    behaviors: [
-      Gerrit.BaseUrlBehavior,
-      Gerrit.ChangeTableBehavior,
-      Gerrit.FireBehavior,
-      Gerrit.KeyboardShortcutBehavior,
-      Gerrit.RESTClientBehavior,
-      Gerrit.URLEncodingBehavior,
-    ],
-
-    listeners: {
-      keydown: '_scopedKeydownHandler',
-    },
-
-    observers: [
-      '_sectionsChanged(sections.*)',
-      '_computePreferences(account, preferences)',
-    ],
+    static get observers() {
+      return [
+        '_sectionsChanged(sections.*)',
+        '_computePreferences(account, preferences)',
+      ];
+    }
 
     keyboardShortcuts() {
       return {
@@ -130,14 +133,26 @@
         [this.Shortcut.TOGGLE_CHANGE_STAR]: '_toggleChangeStar',
         [this.Shortcut.REFRESH_CHANGE_LIST]: '_refreshChangeList',
       };
-    },
+    }
+
+    created() {
+      super.created();
+      this.addEventListener('keydown',
+          e => this._scopedKeydownHandler(e));
+    }
+
+    ready() {
+      super.ready();
+      this._ensureAttribute('tabindex', 0);
+    }
 
     attached() {
+      super.attached();
       Gerrit.awaitPluginsLoaded().then(() => {
         this._dynamicHeaderEndpoints = Gerrit._endpoints.getDynamicEndpoints(
             'change-list-header');
       });
-    },
+    }
 
     /**
      * Iron-a11y-keys-behavior catches keyboard events globally. Some keyboard
@@ -151,11 +166,11 @@
         // Enter.
         this._openChange(e);
       }
-    },
+    }
 
     _lowerCase(column) {
       return column.toLowerCase();
-    },
+    }
 
     _computePreferences(account, preferences) {
       // Polymer 2: check for undefined
@@ -175,13 +190,13 @@
         this.showNumber = false;
         this.visibleChangeTableColumns = this.columnNames;
       }
-    },
+    }
 
     _computeColspan(changeTableColumns, labelNames) {
       if (!changeTableColumns || !labelNames) return;
       return changeTableColumns.length + labelNames.length +
           NUMBER_FIXED_COLUMNS;
-    },
+    }
 
     _computeLabelNames(sections) {
       if (!sections) { return []; }
@@ -198,7 +213,7 @@
         }
       }
       return labels.sort();
-    },
+    }
 
     _computeLabelShortcut(labelName) {
       if (labelName.startsWith(LABEL_PREFIX_INVALID_PROLOG)) {
@@ -210,11 +225,11 @@
             return a + i[0].toUpperCase();
           }, '')
           .slice(0, MAX_SHORTCUT_CHARS);
-    },
+    }
 
     _changesChanged(changes) {
       this.sections = changes ? [{results: changes}] : [];
-    },
+    }
 
     _processQuery(query) {
       let tokens = query.split(' ');
@@ -225,11 +240,11 @@
         });
       });
       return tokens.join(' ');
-    },
+    }
 
     _sectionHref(query) {
       return Gerrit.Nav.getUrlForSearchQuery(this._processQuery(query));
-    },
+    }
 
     /**
      * Maps an index local to a particular section to the absolute index
@@ -245,19 +260,19 @@
         idx += this.sections[i].results.length;
       }
       return idx + localIndex;
-    },
+    }
 
     _computeItemSelected(sectionIndex, index, selectedIndex) {
       const idx = this._computeItemAbsoluteIndex(sectionIndex, index);
       return idx == selectedIndex;
-    },
+    }
 
     _computeItemNeedsReview(account, change, showReviewedState) {
       return showReviewedState && !change.reviewed &&
           !change.work_in_progress &&
           this.changeIsOpen(change) &&
           (!account || account._account_id != change.owner._account_id);
-    },
+    }
 
     _computeItemHighlight(account, change) {
       // Do not show the assignee highlight if the change is not open.
@@ -267,7 +282,7 @@
         return false;
       }
       return account._account_id === change.assignee._account_id;
-    },
+    }
 
     _nextChange(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -275,7 +290,7 @@
 
       e.preventDefault();
       this.$.cursor.next();
-    },
+    }
 
     _prevChange(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -283,7 +298,7 @@
 
       e.preventDefault();
       this.$.cursor.previous();
-    },
+    }
 
     _openChange(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -291,7 +306,7 @@
 
       e.preventDefault();
       Gerrit.Nav.navigateToChange(this._changeForIndex(this.selectedIndex));
-    },
+    }
 
     _nextPage(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -301,7 +316,7 @@
 
       e.preventDefault();
       this.fire('next-page');
-    },
+    }
 
     _prevPage(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -311,7 +326,7 @@
 
       e.preventDefault();
       this.fire('previous-page');
-    },
+    }
 
     _toggleChangeReviewed(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -319,7 +334,7 @@
 
       e.preventDefault();
       this._toggleReviewedForIndex(this.selectedIndex);
-    },
+    }
 
     _toggleReviewedForIndex(index) {
       const changeEls = this._getListItems();
@@ -329,18 +344,18 @@
 
       const changeEl = changeEls[index];
       changeEl.toggleReviewed();
-    },
+    }
 
     _refreshChangeList(e) {
       if (this.shouldSuppressKeyboardShortcut(e)) { return; }
 
       e.preventDefault();
       this._reloadWindow();
-    },
+    }
 
     _reloadWindow() {
       window.location.reload();
-    },
+    }
 
     _toggleChangeStar(e) {
       if (this.shouldSuppressKeyboardShortcut(e) ||
@@ -348,7 +363,7 @@
 
       e.preventDefault();
       this._toggleStarForIndex(this.selectedIndex);
-    },
+    }
 
     _toggleStarForIndex(index) {
       const changeEls = this._getListItems();
@@ -358,7 +373,7 @@
 
       const changeEl = changeEls[index];
       changeEl.$$('gr-change-star').toggleStar();
-    },
+    }
 
     _changeForIndex(index) {
       const changeEls = this._getListItems();
@@ -366,12 +381,12 @@
         return changeEls[index].change;
       }
       return null;
-    },
+    }
 
     _getListItems() {
       return Array.from(
           Polymer.dom(this.root).querySelectorAll('gr-change-list-item'));
-    },
+    }
 
     _sectionsChanged() {
       // Flush DOM operations so that the list item elements will be loaded.
@@ -379,14 +394,16 @@
         this.$.cursor.stops = this._getListItems();
         this.$.cursor.moveToStart();
       });
-    },
+    }
 
     _isOutgoing(section) {
       return !!section.isOutgoing;
-    },
+    }
 
     _isEmpty(section) {
       return !section.results.length;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrChangeList.is, GrChangeList);
 })();
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help.js b/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help.js
index 19e7a25..e6caacb 100644
--- a/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help.js
+++ b/polygerrit-ui/app/elements/change-list/gr-create-change-help/gr-create-change-help.js
@@ -17,8 +17,10 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-create-change-help',
+  class GrCreateChangeHelp extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-create-change-help'; }
 
     /**
      * Fired when the "Create change" button is tapped.
@@ -30,6 +32,8 @@
       e.preventDefault();
       this.dispatchEvent(
           new CustomEvent('create-tap', {bubbles: true, composed: true}));
-    },
-  });
+    }
+  }
+
+  customElements.define(GrCreateChangeHelp.is, GrCreateChangeHelp);
 })();
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog.js b/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog.js
index 5abb257..303128b 100644
--- a/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog.js
+++ b/polygerrit-ui/app/elements/change-list/gr-create-commands-dialog/gr-create-commands-dialog.js
@@ -23,37 +23,43 @@
     PUSH_PREFIX: 'git push origin HEAD:refs/for/',
   };
 
-  Polymer({
-    is: 'gr-create-commands-dialog',
+  class GrCreateCommandsDialog extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-create-commands-dialog'; }
 
-    properties: {
-      branch: String,
-      _createNewCommitCommand: {
-        type: String,
-        readonly: true,
-        value: Commands.CREATE,
-      },
-      _amendExistingCommitCommand: {
-        type: String,
-        readonly: true,
-        value: Commands.AMEND,
-      },
-      _pushCommand: {
-        type: String,
-        computed: '_computePushCommand(branch)',
-      },
-    },
+    static get properties() {
+      return {
+        branch: String,
+        _createNewCommitCommand: {
+          type: String,
+          readonly: true,
+          value: Commands.CREATE,
+        },
+        _amendExistingCommitCommand: {
+          type: String,
+          readonly: true,
+          value: Commands.AMEND,
+        },
+        _pushCommand: {
+          type: String,
+          computed: '_computePushCommand(branch)',
+        },
+      };
+    }
 
     open() {
       this.$.commandsOverlay.open();
-    },
+    }
 
     _handleClose() {
       this.$.commandsOverlay.close();
-    },
+    }
 
     _computePushCommand(branch) {
       return Commands.PUSH_PREFIX + branch;
-    },
-  });
+    }
+  }
+
+  customElements.define(GrCreateCommandsDialog.is, GrCreateCommandsDialog);
 })();
diff --git a/polygerrit-ui/app/elements/change-list/gr-create-destination-dialog/gr-create-destination-dialog.js b/polygerrit-ui/app/elements/change-list/gr-create-destination-dialog/gr-create-destination-dialog.js
index d601cad..3652e70 100644
--- a/polygerrit-ui/app/elements/change-list/gr-create-destination-dialog/gr-create-destination-dialog.js
+++ b/polygerrit-ui/app/elements/change-list/gr-create-destination-dialog/gr-create-destination-dialog.js
@@ -23,37 +23,44 @@
    *
    * @event confirm
    */
+  class GrCreateDestinationDialog extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-create-destination-dialog'; }
 
-  Polymer({
-    is: 'gr-create-destination-dialog',
+    static get properties() {
+      return {
+        _repo: String,
+        _branch: String,
+        _repoAndBranchSelected: {
+          type: Boolean,
+          value: false,
+          computed: '_computeRepoAndBranchSelected(_repo, _branch)',
+        },
+      };
+    }
 
-    properties: {
-      _repo: String,
-      _branch: String,
-      _repoAndBranchSelected: {
-        type: Boolean,
-        value: false,
-        computed: '_computeRepoAndBranchSelected(_repo, _branch)',
-      },
-    },
     open() {
       this._repo = '';
       this._branch = '';
       this.$.createOverlay.open();
-    },
+    }
 
     _handleClose() {
       this.$.createOverlay.close();
-    },
+    }
 
     _pickerConfirm() {
       this.$.createOverlay.close();
       const detail = {repo: this._repo, branch: this._branch};
       this.dispatchEvent(new CustomEvent('confirm', {detail, bubbles: false}));
-    },
+    }
 
     _computeRepoAndBranchSelected(repo, branch) {
       return !!(repo && branch);
-    },
-  });
+    }
+  }
+
+  customElements.define(GrCreateDestinationDialog.is,
+      GrCreateDestinationDialog);
 })();
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
index b762ab3..69cc070 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.js
@@ -19,65 +19,72 @@
 
   const PROJECT_PLACEHOLDER_PATTERN = /\$\{project\}/g;
 
-  Polymer({
-    is: 'gr-dashboard-view',
-
+  /**
+    * @appliesMixin Gerrit.FireMixin
+    * @appliesMixin Gerrit.RESTClientMixin
+    */
+  class GrDashboardView extends Polymer.mixinBehaviors( [
+    Gerrit.FireBehavior,
+    Gerrit.RESTClientBehavior,
+  ], Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element))) {
+    static get is() { return 'gr-dashboard-view'; }
     /**
      * Fired when the title of the page should change.
      *
      * @event title-change
      */
 
-    properties: {
-      account: {
-        type: Object,
-        value: null,
-      },
-      preferences: Object,
-      /** @type {{ selectedChangeIndex: number }} */
-      viewState: Object,
-
-      /** @type {{ project: string, user: string }} */
-      params: {
-        type: Object,
-      },
-
-      createChangeTap: {
-        type: Function,
-        value() {
-          return this._createChangeTap.bind(this);
+    static get properties() {
+      return {
+        account: {
+          type: Object,
+          value: null,
         },
-      },
+        preferences: Object,
+        /** @type {{ selectedChangeIndex: number }} */
+        viewState: Object,
 
-      _results: Array,
+        /** @type {{ project: string, user: string }} */
+        params: {
+          type: Object,
+        },
 
-      /**
+        createChangeTap: {
+          type: Function,
+          value() {
+            return this._createChangeTap.bind(this);
+          },
+        },
+
+        _results: Array,
+
+        /**
        * For showing a "loading..." string during ajax requests.
        */
-      _loading: {
-        type: Boolean,
-        value: true,
-      },
+        _loading: {
+          type: Boolean,
+          value: true,
+        },
 
-      _showDraftsBanner: {
-        type: Boolean,
-        value: false,
-      },
+        _showDraftsBanner: {
+          type: Boolean,
+          value: false,
+        },
 
-      _showNewUserHelp: {
-        type: Boolean,
-        value: false,
-      },
-    },
+        _showNewUserHelp: {
+          type: Boolean,
+          value: false,
+        },
+      };
+    }
 
-    observers: [
-      '_paramsChanged(params.*)',
-    ],
-
-    behaviors: [
-      Gerrit.FireBehavior,
-      Gerrit.RESTClientBehavior,
-    ],
+    static get observers() {
+      return [
+        '_paramsChanged(params.*)',
+      ];
+    }
 
     get options() {
       return this.listChangesOptionsToHex(
@@ -85,11 +92,12 @@
           this.ListChangesOption.DETAILED_ACCOUNTS,
           this.ListChangesOption.REVIEWED
       );
-    },
+    }
 
     attached() {
+      super.attached();
       this._loadPreferences();
-    },
+    }
 
     _loadPreferences() {
       return this.$.restAPI.getLoggedIn().then(loggedIn => {
@@ -101,7 +109,7 @@
           this.preferences = {};
         }
       });
-    },
+    }
 
     _getProjectDashboard(project, dashboard) {
       const errFn = response => {
@@ -124,18 +132,18 @@
           }),
         };
       });
-    },
+    }
 
     _computeTitle(user) {
       if (!user || user === 'self') {
         return 'My Reviews';
       }
       return 'Dashboard for ' + user;
-    },
+    }
 
     _isViewActive(params) {
       return params.view === Gerrit.Nav.View.DASHBOARD;
-    },
+    }
 
     _paramsChanged(paramsChangeRecord) {
       const params = paramsChangeRecord.base;
@@ -145,7 +153,7 @@
       }
 
       return this._reload();
-    },
+    }
 
     /**
      * Reloads the element.
@@ -179,7 +187,7 @@
             });
             console.warn(err);
           }).then(() => { this._loading = false; });
-    },
+    }
 
     /**
      * Fetches the changes for each dashboard section and sets this._results
@@ -218,7 +226,7 @@
               !res.sections[i].hideIfEmpty ||
                 section.results.length));
           });
-    },
+    }
 
     _computeSectionCountLabel(changes) {
       if (!changes || !changes.length || changes.length == 0) {
@@ -228,7 +236,7 @@
       const numChanges = changes.length;
       const andMore = more ? ' and more' : '';
       return `(${numChanges}${andMore})`;
-    },
+    }
 
     _computeUserHeaderClass(params) {
       if (!params || !!params.project || !params.user
@@ -236,17 +244,17 @@
         return 'hide';
       }
       return '';
-    },
+    }
 
     _handleToggleStar(e) {
       this.$.restAPI.saveChangeStarred(e.detail.change._number,
           e.detail.starred);
-    },
+    }
 
     _handleToggleReviewed(e) {
       this.$.restAPI.saveChangeReviewed(e.detail.change._number,
           e.detail.reviewed);
-    },
+    }
 
     /**
      * Banner is shown if a user is on their own dashboard and they have draft
@@ -265,15 +273,15 @@
       if (!closedChanges.length) { return; }
 
       this._showDraftsBanner = true;
-    },
+    }
 
     _computeBannerClass(show) {
       return show ? '' : 'hide';
-    },
+    }
 
     _handleOpenDeleteDialog() {
       this.$.confirmDeleteOverlay.open();
-    },
+    }
 
     _handleConfirmDelete() {
       this.$.confirmDeleteDialog.disabled = true;
@@ -281,23 +289,25 @@
         this._closeConfirmDeleteOverlay();
         this._reload();
       });
-    },
+    }
 
     _closeConfirmDeleteOverlay() {
       this.$.confirmDeleteOverlay.close();
-    },
+    }
 
     _computeDraftsLink() {
       return Gerrit.Nav.getUrlForSearchQuery('has:draft -is:open');
-    },
+    }
 
     _createChangeTap(e) {
       this.$.destinationDialog.open();
-    },
+    }
 
     _handleDestinationConfirm(e) {
       this.$.commandsDialog.branch = e.detail.branch;
       this.$.commandsDialog.open();
-    },
-  });
+    }
+  }
+
+  customElements.define(GrDashboardView.is, GrDashboardView);
 })();
diff --git a/polygerrit-ui/app/elements/change-list/gr-embed-dashboard/gr-embed-dashboard.js b/polygerrit-ui/app/elements/change-list/gr-embed-dashboard/gr-embed-dashboard.js
index acc4295..96dcb98 100644
--- a/polygerrit-ui/app/elements/change-list/gr-embed-dashboard/gr-embed-dashboard.js
+++ b/polygerrit-ui/app/elements/change-list/gr-embed-dashboard/gr-embed-dashboard.js
@@ -17,14 +17,20 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-embed-dashboard',
+  class GrEmbedDashboard extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-embed-dashboard'; }
 
-    properties: {
-      account: Object,
-      sections: Array,
-      preferences: Object,
-      showNewUserHelp: Boolean,
-    },
-  });
+    static get properties() {
+      return {
+        account: Object,
+        sections: Array,
+        preferences: Object,
+        showNewUserHelp: Boolean,
+      };
+    }
+  }
+
+  customElements.define(GrEmbedDashboard.is, GrEmbedDashboard);
 })();
diff --git a/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header.js b/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header.js
index 7ae4dab..c603c45 100644
--- a/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header.js
+++ b/polygerrit-ui/app/elements/change-list/gr-repo-header/gr-repo-header.js
@@ -17,18 +17,22 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-repo-header',
+  class GrRepoHeader extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-repo-header'; }
 
-    properties: {
+    static get properties() {
+      return {
       /** @type {?String} */
-      repo: {
-        type: String,
-        observer: '_repoChanged',
-      },
-      /** @type {String|null} */
-      _repoUrl: String,
-    },
+        repo: {
+          type: String,
+          observer: '_repoChanged',
+        },
+        /** @type {String|null} */
+        _repoUrl: String,
+      };
+    }
 
     _repoChanged(repoName) {
       if (!repoName) {
@@ -36,6 +40,8 @@
         return;
       }
       this._repoUrl = Gerrit.Nav.getUrlForRepo(repoName);
-    },
-  });
+    }
+  }
+
+  customElements.define(GrRepoHeader.is, GrRepoHeader);
 })();
diff --git a/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header.js b/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header.js
index 6afc169..af8af3f 100644
--- a/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header.js
+++ b/polygerrit-ui/app/elements/change-list/gr-user-header/gr-user-header.js
@@ -17,40 +17,44 @@
 (function() {
   'use strict';
 
-  Polymer({
-    is: 'gr-user-header',
+  class GrUserHeader extends Polymer.GestureEventListeners(
+      Polymer.LegacyElementMixin(
+          Polymer.Element)) {
+    static get is() { return 'gr-user-header'; }
 
-    properties: {
+    static get properties() {
+      return {
       /** @type {?String} */
-      userId: {
-        type: String,
-        observer: '_accountChanged',
-      },
+        userId: {
+          type: String,
+          observer: '_accountChanged',
+        },
 
-      showDashboardLink: {
-        type: Boolean,
-        value: false,
-      },
+        showDashboardLink: {
+          type: Boolean,
+          value: false,
+        },
 
-      loggedIn: {
-        type: Boolean,
-        value: false,
-      },
+        loggedIn: {
+          type: Boolean,
+          value: false,
+        },
 
-      /**
+        /**
        * @type {?{name: ?, email: ?, registered_on: ?}}
        */
-      _accountDetails: {
-        type: Object,
-        value: null,
-      },
+        _accountDetails: {
+          type: Object,
+          value: null,
+        },
 
-      /** @type {?String} */
-      _status: {
-        type: String,
-        value: null,
-      },
-    },
+        /** @type {?String} */
+        _status: {
+          type: String,
+          value: null,
+        },
+      };
+    }
 
     _accountChanged(userId) {
       if (!userId) {
@@ -65,19 +69,19 @@
       this.$.restAPI.getAccountStatus(userId).then(status => {
         this._status = status;
       });
-    },
+    }
 
     _computeDisplayClass(status) {
       return status ? ' ' : 'hide';
-    },
+    }
 
     _computeDetail(accountDetails, name) {
       return accountDetails ? accountDetails[name] : '';
-    },
+    }
 
     _computeStatusClass(accountDetails) {
       return this._computeDetail(accountDetails, 'status') ? '' : 'hide';
-    },
+    }
 
     _computeDashboardUrl(accountDetails) {
       if (!accountDetails) { return null; }
@@ -85,11 +89,13 @@
       const email = accountDetails.email;
       if (!id && !email ) { return null; }
       return Gerrit.Nav.getUrlForUserDashboard(id ? id : email);
-    },
+    }
 
     _computeDashboardLinkClass(showDashboardLink, loggedIn) {
       return showDashboardLink && loggedIn ?
         'dashboardLink' : 'dashboardLink hide';
-    },
-  });
+    }
+  }
+
+  customElements.define(GrUserHeader.is, GrUserHeader);
 })();