Polymer 1.x: Pre-load element attributes
<p><em>Notice: This question <a href="https://stackoverflow.com/q/35284274/1640892">is <strong>not a duplicate</strong> of this SO question</a> because the first question was solved with a syntax correction in the markup. This question involves the JavaScript and has a different error message.</em></p>

<hr>

<h3>My Goal</h3>

<p>I am trying to preset a custom element property named <code>selected</code> to a value of <code>["Colorado", "South Dakota"]</code> via a declarative attribute.</p>

<h3>Expected vs Actual Behavior</h3>

<p>I expect to see the page load a map with an outline of all the U.S. states. With no errors in the console. And the states of Colorado and South Dakota pre-selected and colored blue.</p>

<p>Instead, I see a blank page with no map at all. The page prints the correct <code>selected</code> variable: <code>Colorado,South Dakota</code>. A set of errors in the console begins with the following:</p>

console.error

<blockquote>
  <p><code>TypeError: Cannot read property 'length' of undefined</code></p>
</blockquote>

<h3>Possible problems and solutions</h3>

<p>The problem is that the <code>items</code> property has not yet been populated by the <code>ready</code> function before <code>_doAll</code> tries to access it to set the selected states.</p>

<p>I tracked the issue to the following spot in the code:</p>

http://jsbin.com/qezogimude/1/edit?html,console,output

<pre><code>_doAll: function(verb) {
  ...
  var items = this.items, // undefined
      i = items.length; // error, crashes
  ...
</code></pre>

<p>I also (unsuccessfully) tried the following (separately):</p>

<ul>
<li><code>async</code></li>
<li><code>while(this.items === undefined){...</code></li>
</ul>

<h3>Recreating the problem</h3>

<p>The following steps will recreate the problem:</p>

<ol>
<li><a href="http://jsbin.com/qezogimude/1/edit?html,console,output" rel="nofollow noreferrer">Open this jsBin</a>.</li>
<li>Notice the map loads properly in the output pane. (And works properly when states are selected and de-selected.)</li>
<li>Scroll down to the bottom of the page to the <code>&lt;x-element&gt;</code> tag.</li>
<li>Delete the <code>x</code> character in front of the <code>selected</code> attribute so the complete attribute reads: <code>selected='["Colorado", "South Dakota"]'</code>.</li>
<li>Notice the map disappeared, no longer loads properly and the errors described above appear in the console.</li>
<li>Replace the <code>x</code> you just deleted and notice the map loads and works properly again.</li>
</ol>

<h1>Question</h1>

<p>How do I get <code>_doAll</code> to wait for <code>ready</code> to populate the <code>items</code> property? Please include a working jsBin example of your solution if you can.</p>

http://jsbin.com/qezogimude/1/edit?html,console,output

<pre><code>&lt;!DOCTYPE html&gt;

&lt;head&gt;
  &lt;meta charset="utf-8"&gt;
  &lt;base href="https://polygit.org/components/"&gt;
  &lt;script src="webcomponentsjs/webcomponents-lite.min.js"&gt;&lt;/script&gt;
  &lt;link href="polymer/polymer.html" rel="import"&gt;
  &lt;link href="google-chart/google-chart.html" rel="import"&gt;
&lt;/head&gt;

&lt;body&gt;

  &lt;dom-module id="x-element"&gt;

    &lt;template&gt;
      &lt;style&gt;
        google-chart {
          width: 100%;
          max-height: 300px;
        }
      &lt;/style&gt;
      &lt;button on-tap="_show"&gt;Show&lt;/button&gt;
      &lt;div&gt;[[selected]]&lt;/div&gt;
      &lt;google-chart
        id="geochart"
        type="geo"
        options="{{options}}"
        data="{{items}}"
        xon-google-chart-select="_onGoogleChartSelect"&gt;&lt;/google-chart&gt;
    &lt;/template&gt;

    &lt;script&gt;
      (function(){
        Polymer({
          is: 'x-element',
          /** /
           * Fired when user selects chart item.
           *
           * @event us-map-select
           * @param {object} detail Alpabetized array of selected state names.
          /**/
          properties: {
            selected: {
              type: Array,
              notify: true,
              //reflectToAttribute: true,
            },
            items: {
              type: Array,
              notify: true,
              reflectToAttribute: true,
            },
            color: {
              type: String, // '#455A64'
              value: function() {
                return 'blue';
              }
            },
            options: {
              type: Object,
              notify: true,
              reflectToAttribute: true,
              computed: '_computeOptions(color)'
            },
            itemIndices: {
              type: Object,
              computed: '_computeItemIndices(items)',
            },
          },

          observers: [
            '_selectedChanged(selected.*)'
          ],

          ready: function() {
            var a = [['State', 'Select'], ['Alabama', 0], ['Alaska', 0], ['Arizona', 0], ['Arkansas', 0], ['California', 0], ['Colorado', 0], ['Connecticut', 0], ['Delaware', 0], ['Florida', 0], ['Georgia', 0], ['Hawaii', 0], ['Idaho', 0],  ['Illinois', 0], ['Indiana', 0], ['Iowa', 0], ['Kansas', 0], ['Kentucky', 0], ['Louisiana', 0], ['Maine', 0], ['Maryland', 0], ['Massachusetts', 0], ['Michigan', 0], ['Minnesota', 0], ['Mississippi', 0], ['Missouri', 0], ['Montana', 0], ['Nebraska', 0], ['Nevada', 0], ['New Hampshire', 0], ['New Jersey', 0], ['New Mexico', 0], ['New York', 0], ['North Carolina', 0], ['North Dakota', 0], ['Ohio', 0], ['Oklahoma', 0], ['Oregon', 0], ['Pennsylvania', 0], ['Rhode Island', 0], ['South Carolina', 0], ['South Dakota', 0], ['Tennessee', 0], ['Texas', 0], ['Utah', 0], ['Vermont', 0], ['Virginia', 0], ['Washington', 0], ['West Virginia', 0], ['Wisconsin', 0], ['Wyoming', 0]];
            this.set('items', a);
            var _this = this; 
            this.$.geochart.addEventListener('google-chart-select', function(e){this._onGoogleChartSelect(e)}.bind(_this));
          },

          _computeItemIndices: function(a) {
            var out = {},
                i = a.length;
            while(i--){
              out[a[i][0]] = i;
            }
            return out;
          },

          _onGoogleChartSelect: function(e) {
            var s = e.path[0].textContent.split('Select')[0].trim(), // e.g. 'Ohio'
                temp = [],
                a = this.items,
                index = this.itemIndices[s], // e.g. 35
                i = a.length;
            this.set('items.' + index + '.1', a[index][1] ? 0 : 1);
            while(i---1){
              /** /
              if(s === a[i][0]){
                this.set('items.' + i + '.1', a[i][1] ? 0 : 1);
                //this.items[i][1] = a[i][1] ? 0 : 1;
              }
              /**/
              if(a[i][1]){
                temp.push(a[i][0]);
              }
            }
            temp.sort();
            this.set('selected', temp);
            this._drawChart();
            //console.log(this.selected);
          },

          _drawChart: function() {
            this.$.geochart._dataTable=this.$.geochart._createDataTable(this.items);
            this.$.geochart._chartObject.draw(this.$.geochart._dataTable,
                                              this.$.geochart.options);
          },

          doAll: function(verb) {
            verb = verb || 'clear'; // verb: 'clear'(default)|'select'
            verb = (verb === 'select') ? 'select' : 'clear';
            this._doAll(verb);
            this._drawChart();
          },

          _doAll: function(verb) {
            var resetSelect = (verb &amp;&amp; verb === 'some') ? false : true;
            verb = verb || 'clear'; // verb: 'clear'(default)|'select'|'some'
            verb = (verb === 'select') ? 'select' : 'clear';
            var temp = [];
            var items = this.items, // undefined
                i = items.length; // error, crashes
            switch(verb) {
              case 'select':
                while(i---1){
                  items[i][1] = 1;
                  temp.push(items[i][0]);
                }
                break;
              case 'clear':
                while(i---1){
                  items[i][1] = 0;
                }
                break;
              default:
                break;
            }
            this.set('items', items);
            if(resetSelect){
              temp.sort();
              this.set('selected', temp);
            }
          },

          _selectedChanged: function(e) {
            var a = e.base,
                i = a.length;
            this._doAll('some');
            while(i--){
              var index = this.itemIndices[a[i]];
              this.set('items.' + index + '.1', 1);
            }
            this._drawChart();
            this.fire('us-map-select', this.selected)
            console.log(this.selected);
          },

          _computeOptions: function(str) {
            return {
              region: 'US',
              displayMode: 'regions',
              resolution: 'provinces',
              legend: 'none',
              defaultColor: '#F5F5F5',
              colorAxis: {
                colors: ['#F5F5F5', str],
                minValue: 0,  
                maxValue: 1,
              }
            }
          },

          _show: function(){
            //this.set('selected', ['Ohio', 'New Mexico']);
            this.doAll();
            //console.log(this.itemIndices);
          },
        });
      })();
    &lt;/script&gt;

  &lt;/dom-module&gt;

  &lt;x-element xcolor="#455A64"
             xselected='["Colorado", "South Dakota"]'&gt;&lt;/x-element&gt;

&lt;/body&gt;
&lt;/html&gt;
</code></pre>