title: Long process blocks waiting icon render in ExtJS
body: <p>The feature I'm implementing is not a really required, so I won't include an extra library of threads just for that. But if someone knows a workaround I will appreciate it.</p>
  
  <p>So I have a grid of 256 rows and 3 columns; one those columns is a <strong>checkboxColumn</strong> (similar to the one used <a href="http://dev.sencha.com/deploy/ext-3.4.0/examples/grid/edit-grid.html" rel="nofollow noreferrer">here</a>). But that checkboxColumn plugin has being modified to show a checkbox in the header in order to allow a kind of <code>Check-All</code> and <code>Check-None</code> features.</p>
  
  <p>Because there are so many rows, the check-all process is taking to long. So I decided to put a "Spinning wheel" (waiting gif-animation). And now the problem is that the animation doesn't work. So I put a <code>defer</code> call to allow the rendering of the animated icon, but it seems like that <code>defer</code> is not enough for the animation to run. Although this <code>defer</code> at least allows showing the first frame of the waiting gif, instead of showing the checked-state for about a minute until the unchecked-state is show when everything is done.</p>
  
  <p>Here is the expensive method:</p>
  
  <pre><code>internalSetAllColumn: function(column, newValue) {
      column.masterValue = newValue;
      column.header = '&lt;div class="x-grid3-check-col-td loading-indicator"&gt;&amp;#160;&lt;/div&gt;'; // loading icon
      this.grid.getView().updateHeaders();
      (function() {
          this.grid.getStore().each(function(rec) {
              if (this.isCellEditable(rec)) {
                  rec.set(this.dataIndex, newValue);
              }
          }, this);
          column.renderHeaderCheck();
          this.grid.getView().updateHeaders();
      }).defer(50, this);
  }
  </code></pre>
  
  <p>And you can see a working example at the following code snippet:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="true" data-console="true" data-babel="false">
  <div class="snippet-code snippet-currently-hidden">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>/*global Ext */
  
  Ext.grid.CheckColumn = function(config){
      Ext.apply(this, config);
      if(!this.id){
          this.id = Ext.id();
      }
      this.headerText = this.headerText || this.header || '&amp;#160;';
      this.renderer = this.renderer.createDelegate(this);
  };
  Ext.grid.CheckColumn.prototype = {
      init: function(grid) {
          this.grid = grid;
          var column = this.grid.getColumnModel().getColumnById(this.id);
          column.masterValue = false;
          if (this.headerCheck) {
              column.renderHeaderCheck();
          }
          this.grid.on('headerclick', this.onHeaderClick, this);
          this.grid.on('render', function() {
              var view = this.grid.getView();
              view.mainBody.on('mousedown', this.onMouseDown, this);
              view.updateHeaders();
          }, this);
      }
      , dataIndex: ''
      , masterValue: false
      , width: 90
      , fixed: true
      , headerCheck: false
      , enableHeaderControl: true
      , onMouseDown: function(e, t) {
          if (!this.readonly) {
              if (Ext.fly(t).hasClass('x-grid3-cc-' + this.id)) {
                  e.stopEvent();
                  var editEvent = {};
                  editEvent.row = this.grid.getView().findRowIndex(t);
                  editEvent.column = this.grid.getColumnModel().findColumnIndex(this.dataIndex);
                  editEvent.grid = this.grid;
                  editEvent.field = this.dataIndex;
                  editEvent.record = this.grid.store.getAt(editEvent.row);
                  editEvent.originalValue = editEvent.record.data[this.dataIndex];
                  editEvent.value = !editEvent.originalValue;
                  editEvent.record.set(editEvent.field, editEvent.value);
                  editEvent.grid.fireEvent('afteredit', editEvent);
              }
          }
      },
  
      getCheckedCls: function(v) {
          return v === -1 ? 'x-grid3-check-col-gray' : (v ? 'x-grid3-check-col-on' : 'x-grid3-check-col');
      },
  
      renderHeaderCheck: function() {
          this.header = '&lt;div class="' + this.getCheckedCls(this.masterValue) + '"&gt;' + this.headerText + '&lt;/div&gt;';
      },
  
      onHeaderClick: function(grid, columnIndex, event) {
          var colModel = grid.getColumnModel();
          var cIndex = colModel.getIndexById(this.id);
          if (cIndex == columnIndex &amp;&amp; this.enableHeaderControl !== false &amp;&amp; this.headerCheck) {
              var column = colModel.getColumnById(this.id);
              var newValue = !column.masterValue;
              this.internalSetAllColumn(column, newValue);
              colModel.fireEvent("headerchange", colModel, columnIndex, column.header);
              this.grid.getView().updateHeaders();
          }
      },
  
      renderer: function(v, p, record, rowIndex, colIndex, store) {
          p.css += ' x-grid3-check-col-td';
          return '&lt;div class="' + this.getCheckedCls(v) + ' x-grid3-cc-' + this.id + '"&gt; &lt;/div&gt;';
      },
  
      internalSetAllColumn: function(column, newValue) {
          column.masterValue = newValue;
          column.header = '&lt;div class="x-grid3-check-col-td loading-indicator"&gt;&amp;#160;&lt;/div&gt;'; // loading icon
          this.grid.getView().updateHeaders();
          (function() {
              this.grid.getStore().each(function(rec) {
                  rec.set(this.dataIndex, newValue);
              }, this);
              column.renderHeaderCheck();
              this.grid.getView().updateHeaders();
          }).defer(50, this);
      },
  
      setAllColumn: function(columnIndex, newValue) {
          var colModel = this.grid.getColumnModel();
          var colId = colModel.getColumnId(columnIndex);
          var column = colModel.getColumnById(colId);
          this.internalSetAllColumn(column, newValue);
          this.grid.getView().updateHeaders();
      }
  };
  
  // -----------------------------------------
  // End of plugin - Beginning of example code
  // -----------------------------------------
  
          var chkColCountry = new Ext.grid.CheckColumn({ dataIndex: 'State.After', width: 50, headerCheck: true });
  
          var dsCountries = new Ext.data.ArrayStore({
              fields: ['Id', 'Name']
              , data: [["US","United States"],["CA","Canada"],["AF","Afghanistan"],["AL","Albania"],["DZ","Algeria"],["DS","American Samoa"],["AD","Andorra"],["AO","Angola"],["AI","Anguilla"],["AQ","Antarctica"],["AG","Antigua and/or Barbuda"],["AR","Argentina"],["AM","Armenia"],["AW","Aruba"],["AU","Australia"],["AT","Austria"],["AZ","Azerbaijan"],["BS","Bahamas"],["BH","Bahrain"],["BD","Bangladesh"],["BB","Barbados"],["BY","Belarus"],["BE","Belgium"],["BZ","Belize"],["BJ","Benin"],["BM","Bermuda"],["BT","Bhutan"],["BO","Bolivia"],["BA","Bosnia and Herzegovina"],["BW","Botswana"],["BV","Bouvet Island"],["BR","Brazil"],["IO","British lndian Ocean Territory"],["BN","Brunei Darussalam"],["BG","Bulgaria"],["BF","Burkina Faso"],["BI","Burundi"],["KH","Cambodia"],["CM","Cameroon"],["CV","Cape Verde"],["KY","Cayman Islands"],["CF","Central African Republic"],["TD","Chad"],["CL","Chile"],["CN","China"],["CX","Christmas Island"],["CC","Cocos (Keeling) Islands"],["CO","Colombia"],["KM","Comoros"],["CG","Congo"],["CK","Cook Islands"],["CR","Costa Rica"],["HR","Croatia (Hrvatska)"],["CU","Cuba"],["CY","Cyprus"],["CZ","Czech Republic"],["DK","Denmark"],["DJ","Djibouti"],["DM","Dominica"],["DO","Dominican Republic"],["TP","East Timor"],["EC","Ecudaor"],["EG","Egypt"],["SV","El Salvador"],["GQ","Equatorial Guinea"],["ER","Eritrea"],["EE","Estonia"],["ET","Ethiopia"],["FK","Falkland Islands (Malvinas)"],["FO","Faroe Islands"],["FJ","Fiji"],["FI","Finland"],["FR","France"],["FX","France, Metropolitan"],["GF","French Guiana"],["PF","French Polynesia"],["TF","French Southern Territories"],["GA","Gabon"],["GM","Gambia"],["GE","Georgia"],["DE","Germany"],["GH","Ghana"],["GI","Gibraltar"],["GR","Greece"],["GL","Greenland"],["GD","Grenada"],["GP","Guadeloupe"],["GU","Guam"],["GT","Guatemala"],["GN","Guinea"],["GW","Guinea-Bissau"],["GY","Guyana"],["HT","Haiti"],["HM","Heard and Mc Donald Islands"],["HN","Honduras"],["HK","Hong Kong"],["HU","Hungary"],["IS","Iceland"],["IN","India"],["ID","Indonesia"],["IR","Iran (Islamic Republic of)"],["IQ","Iraq"],["IE","Ireland"],["IL","Israel"],["IT","Italy"],["CI","Ivory Coast"],["JM","Jamaica"],["JP","Japan"],["JO","Jordan"],["KZ","Kazakhstan"],["KE","Kenya"],["KI","Kiribati"],["KP","Korea, Democratic People's Republic of"],["KR","Korea, Republic of"],["KW","Kuwait"],["KG","Kyrgyzstan"],["LA","Lao People's Democratic Republic"],["LV","Latvia"],["LB","Lebanon"],["LS","Lesotho"],["LR","Liberia"],["LY","Libyan Arab Jamahiriya"],["LI","Liechtenstein"],["LT","Lithuania"],["LU","Luxembourg"],["MO","Macau"],["MK","Macedonia"],["MG","Madagascar"],["MW","Malawi"],["MY","Malaysia"],["MV","Maldives"],["ML","Mali"],["MT","Malta"],["MH","Marshall Islands"],["MQ","Martinique"],["MR","Mauritania"],["MU","Mauritius"],["TY","Mayotte"],["MX","Mexico"],["FM","Micronesia, Federated States of"],["MD","Moldova, Republic of"],["MC","Monaco"],["MN","Mongolia"],["MS","Montserrat"],["MA","Morocco"],["MZ","Mozambique"],["MM","Myanmar"],["NA","Namibia"],["NR","Nauru"],["NP","Nepal"],["NL","Netherlands"],["AN","Netherlands Antilles"],["NC","New Caledonia"],["NZ","New Zealand"],["NI","Nicaragua"],["NE","Niger"],["NG","Nigeria"],["NU","Niue"],["NF","Norfork Island"],["MP","Northern Mariana Islands"],["NO","Norway"],["OM","Oman"],["PK","Pakistan"],["PW","Palau"],["PA","Panama"],["PG","Papua New Guinea"],["PY","Paraguay"],["PE","Peru"],["PH","Philippines"],["PN","Pitcairn"],["PL","Poland"],["PT","Portugal"],["PR","Puerto Rico"],["QA","Qatar"],["RE","Reunion"],["RO","Romania"],["RU","Russian Federation"],["RW","Rwanda"],["KN","Saint Kitts and Nevis"],["LC","Saint Lucia"],["VC","Saint Vincent and the Grenadines"],["WS","Samoa"],["SM","San Marino"],["ST","Sao Tome and Principe"],["SA","Saudi Arabia"],["SN","Senegal"],["SC","Seychelles"],["SL","Sierra Leone"],["SG","Singapore"],["SK","Slovakia"],["SI","Slovenia"],["SB","Solomon Islands"],["SO","Somalia"],["ZA","South Africa"],["GS","South Georgia South Sandwich Islands"],["ES","Spain"],["LK","Sri Lanka"],["SH","St. Helena"],["PM","St. Pierre and Miquelon"],["SD","Sudan"],["SR","Suriname"],["SJ","Svalbarn and Jan Mayen Islands"],["SZ","Swaziland"],["SE","Sweden"],["CH","Switzerland"],["SY","Syrian Arab Republic"],["TW","Taiwan"],["TJ","Tajikistan"],["TZ","Tanzania, United Republic of"],["TH","Thailand"],["TG","Togo"],["TK","Tokelau"],["TO","Tonga"],["TT","Trinidad and Tobago"],["TN","Tunisia"],["TR","Turkey"],["TM","Turkmenistan"],["TC","Turks and Caicos Islands"],["TV","Tuvalu"],["UG","Uganda"],["UA","Ukraine"],["AE","United Arab Emirates"],["GB","United Kingdom"],["UM","United States minor outlying islands"],["UY","Uruguay"],["UZ","Uzbekistan"],["VU","Vanuatu"],["VA","Vatican City State"],["VE","Venezuela"],["VN","Vietnam"],["VG","Virigan Islands (British)"],["VI","Virgin Islands (U.S.)"],["WF","Wallis and Futuna Islands"],["EH","Western Sahara"],["YE","Yemen"],["YU","Yugoslavia"],["ZR","Zaire"],["ZM","Zambia"],["ZW","Zimbabwe"]]
              , autoLoad: false
          });
  
          var cmCountry = new Ext.grid.ColumnModel([
              chkColCountry
              , { id: 'Id', header: 'Id', dataIndex: 'Id', width: 40 }
              , { id: 'Name', header: 'CountryName', dataIndex: 'Name', width: 460 }
              , { id: 'After', header: 'After', dataIndex: 'State.After', hidden: true }
          ]);
  
          var grdCountries = new Ext.grid.GridPanel({
              store: dsCountries
              , cm: cmCountry
              , plugins: chkColCountry
              , enableHdMenu: false
          });
  
          var win = new Ext.Window({
            layout: 'fit'
            , height: 190
            , width: 600
            , items: [grdCountries]
          });
          win.show();</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;link href="//cdnjs.cloudflare.com/ajax/libs/extjs/3.4.1-1/resources/css/ext-all.css" rel="stylesheet"/&gt;
  &lt;script src="//cdnjs.cloudflare.com/ajax/libs/extjs/3.4.1-1/adapter/ext/ext-base.js"&gt;&lt;/script&gt;
  &lt;script src="//cdnjs.cloudflare.com/ajax/libs/extjs/3.4.1-1/ext-all.js"&gt;&lt;/script&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>Click on the column checkbox (the one on the header) and see the gif that isn't spinning <a href="https://cdnjs.cloudflare.com/ajax/libs/extjs/3.4.1-1/resources/images/access/grid/loading.gif" rel="nofollow noreferrer">as expected</a>.</p>
  
  <p>Note: I have paging functionality in other places but I won't use it here as the 256 rows are always the same. So I rather lose the check all button than paging this.</p>