DOMContentLoaded never fires, can not use WebComponentsReady

2,787 views
Skip to first unread message

Darin Hensley

unread,
Dec 22, 2015, 10:44:05 PM12/22/15
to Polymer
stack overflow post


Using polymer 1.2.3,


In linux firefox 42.0, where the polyfill(webcomponents-lite.js) is used:


`WebComponentsReady` fires to soon, because I `querySelect` and `getElementById` elements that do not exist yet in `initialize`.


    window.addEventListener('WebComponentsReady', function() {
      initialize
        .then(attatchListeners)


So I am using `DOMContentLoaded` but it never fires:

       document.addEventListener('DOMContentLoaded', function() {
         initialize
          .then(attatchListeners)
     


Any ideas on how to make initialize run when the elements are available for `querySelect()`? 

Eric Bidelman

unread,
Dec 22, 2015, 11:04:32 PM12/22/15
to Darin Hensley, Polymer
Responded on SO.

Follow Polymer on Google+: plus.google.com/107187849809354688692
---
You received this message because you are subscribed to the Google Groups "Polymer" group.
To unsubscribe from this group and stop receiving emails from it, send an email to polymer-dev...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/polymer-dev/866fb641-5c8f-47bd-ba78-94588daa606b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Darin Hensley

unread,
Dec 23, 2015, 12:14:13 AM12/23/15
to Polymer, darin....@gmail.com
Thanks! I had the DOMContentLoaded event listener run after it fired rather than before. 

Darin Hensley

unread,
Dec 23, 2015, 2:17:00 PM12/23/15
to Polymer, darin....@gmail.com
Still seem to be having a issue in this context.... 
 
'DOMContentLoaded' is firing before the elements are ready....would this have anything to do with polymer? 

document.addEventListener('DOMContentLoaded', function() {
  console.log(document.getElementById('ripple-element'));

Shows null. But the element is there and it exists, if I do `document.getElementById('ripple-element')` in the browsers developer console the element is returned. 

Darin Hensley

unread,
Dec 23, 2015, 3:02:40 PM12/23/15
to Polymer, darin....@gmail.com
Please disregard.... my promise was invoking at the time of creation. I used to use the defer method which is legacy in Mozilla so I learned something new :) 

Darin Hensley

unread,
Dec 23, 2015, 3:43:25 PM12/23/15
to Polymer, darin....@gmail.com
Sorry, about the confusion....there is still a issue:

When using Firefox 42.0 Linux with the  jsbin http://jsbin.com/damego/edit?html,output, the alert(e) never fires. Instead I get browser crash messages. 

Eric Bidelman

unread,
Dec 24, 2015, 9:26:12 AM12/24/15
to Darin Hensley, Polymer
This appears to be an issue with FF 42 Linux. It works fine on FF 43 Mac.

Note that WebComponentsReady is the event to know when all elements are registered and upgraded. DCL won't give you that information and will likely fire before this event.

Daniel Llewellyn

unread,
Dec 24, 2015, 11:33:55 AM12/24/15
to Eric Bidelman, Darin Hensley, Polymer
Jumping in here, is webcomponentsready expected to fire in chrome without the polyfill? If not, as I suspect, what is the best way to get an on load for both scenarios? I.e when you are purposely not including the polyfill for compatible browsers but adding it for those without support...

Sent from my iPhone

Darin Hensley

unread,
Dec 24, 2015, 12:01:37 PM12/24/15
to Polymer, ebi...@gmail.com, darin....@gmail.com
WebComponentsReady will only fire if you are using the polyfill. If you didn't load the polyfill, you would:

Simply place any scripts that manipulate Polymer elements at the end of the page, and all elements should be read


If you are not using the web components polyfills (for example, in a Chrome extension), the WebComponentsReady event will not fire. With native HTML imports and custom elements, elements upgrade synchronously, so the event is not required. Simply place any scripts that manipulate Polymer elements at the end of the page, and all elements should be ready.

Also, check out other unique ways to load in Eric's gists:  https://gist.github.com/ebidel

Darin Hensley

unread,
Dec 24, 2015, 10:32:39 PM12/24/15
to Polymer
I am having  issues(not consistent....random) where the elements are not ready when I attach the listeners. I placed a setTimeout to try and compensate the random race condition. Should these elements be ready during the time of their queries when  WebComponentsReady fires or with the initialize.js script placed last at the bottom of the index.html?
function makeGlobalElements() {
  //elements is not routing list, routing list is elementList
  panel = document.querySelector('paper-header-panel[main]');
  rippleElement = document.getElementById('ripple-element');
  toolbar = document.querySelector('#main-toolbar');
  headerName = document.getElementById('name-title');
  drawer = document.querySelector('paper-drawer-panel');
  mainPanelContent = document.getElementById('mainPanelContent');
};

function attatchListeners() {
  panel.addEventListener("content-scroll", moveTitle);
  ['webkitAnimationEnd', 'animationend']
  .forEach(function(vendor) {
    mainPanelContent.addEventListener(vendor, function (animationEvent) {
      if (animationEvent.animationName === "slide-down") {
        afterSlideDown.runStack();
        mainPanelContent.classList.remove('slide-down-now');
      }
    });
    headerName.addEventListener(vendor, function() { 
      headerName.classList.remove('fade-title'); 
    });
  });
};


function initializeYay() {
  makeGlobalElements();
  setTimeout(attatchListeners, 500);
    setUpRoutes();
  removeSplash();
  //fetchPdfjs();
}

if (!webComponentsSupported) {
  document.addEventListener('WebComponentsReady', initializeYay);
} else {
  initializeYay();
  page('/portfolio');
}

Eric Bidelman

unread,
Dec 25, 2015, 10:37:55 AM12/25/15
to Darin Hensley, Polymer

You can attach listeners to elements before they're upgraded and ready. That's a nice property of custom elements and DOM events. Waiting to attach until WCR means you may miss the event the first time it's fired.


Follow Polymer on Google+: plus.google.com/107187849809354688692
---
You received this message because you are subscribed to the Google Groups "Polymer" group.
To unsubscribe from this group and stop receiving emails from it, send an email to polymer-dev...@googlegroups.com.

Darin Hensley

unread,
Dec 25, 2015, 4:55:05 PM12/25/15
to Polymer, darin....@gmail.com
Thanks, I changed the code to use the polymer api for querying elements... but I am still having a race condition(in regards to the issue where I get "Uncaught TypeError: Cannot read property 'scroller' of undefined" for  "panel.scroller.scrollTop =0". This expression comes from the function  setUpRoutes();. I can use a setTimeout to compensate for it. 

function makeGlobalElements() {
 
//elements is not routing list, routing list is elementList

  panel
= Polymer.dom(parent).querySelector('paper-header-panel[main]');
  rippleElement
= Polymer.dom(parent).querySelector('#ripple-element');
  toolbar
= Polymer.dom(parent).querySelector('#main-toolbar');
  headerName
= Polymer.dom(parent).querySelector('#name-title');
  drawer
= Polymer.dom(parent).querySelector('paper-drawer-panel');
  mainPanelContent
= Polymer.dom(parent).querySelector('#mainPanelContent');

};


function attatchListeners() {
  panel
.addEventListener("content-scroll", moveTitle);
 
['webkitAnimationEnd', 'animationend']
 
.forEach(function(vendor) {
    mainPanelContent
.addEventListener(vendor, function (animationEvent) {
     
if (animationEvent.animationName === "slide-down") {
        afterSlideDown
.runStack();
        mainPanelContent
.classList.remove('slide-down-now');
     
}
   
});
    headerName
.addEventListener(vendor, function() {
      headerName
.classList.remove('fade-title');
   
});
 
});
};




function initializeYay() {
  makeGlobalElements
();

  attatchListeners
;

Darin Hensley

unread,
Dec 25, 2015, 5:03:05 PM12/25/15
to Polymer, darin....@gmail.com
Sorry, I spoke to soon on that.... I had to change it back to panel = document.querySelector('paper-header-panel[main]') and then use a setTimeout. There was no scroller at all when using the Polymer api query. 

Darin Hensley

unread,
Dec 25, 2015, 5:09:54 PM12/25/15
to Polymer, darin....@gmail.com
Sorry, disregard that again.... I needed to use Polymer.dom(document.rootElement) instead. 

Darin Hensley

unread,
Dec 26, 2015, 10:44:45 PM12/26/15
to Polymer, darin....@gmail.com
It's been working for many refreshes...but it just happened again... I got 'Uncaught TypeError: Cannot read property 'addEventListener' of undefined' for 'panel.addEventListener("content-scroll", moveTitle);'. This is in chrome where the initialize.js script is loaded last in the index.html.

function makeGlobalElements() {
 
//elements is not routing list, routing list is elementList

  panel
= Polymer.dom(document.rootElement).querySelector('paper-header-panel[main]');
  rippleElement
= Polymer.dom(document.rootElement).querySelector('#ripple-element');
  toolbar
= Polymer.dom(document.rootElement).querySelector('#main-toolbar');
  headerName
= Polymer.dom(document.rootElement).querySelector('#name-title');
  drawer
= Polymer.dom(document.rootElement).querySelector('paper-drawer-panel');
  mainPanelContent
= Polymer.dom(document.rootElement).querySelector('#mainPanelContent');

};


function attatchListeners() {
  panel
.addEventListener("content-scroll", moveTitle);

  ....

     

function initializeYay() {
  makeGlobalElements();
  attatchListeners();
  setUpRoutes();
  removeSplash();
  //fetchPdfjs();
}

if (!webComponentsSupported) {
  document
.addEventListener('WebComponentsReady', initializeYay);
} else {
  initializeYay
();
  page
('/portfolio');
}



----

On Friday, December 25, 2015 at 9:37:55 AM UTC-6, Eric Bidelman wrote:

Max

unread,
Dec 27, 2015, 4:27:48 PM12/27/15
to Darin Hensley, Polymer
I just thought that my approach to this issue would be to create a promise for each event (each event handler resolves its promise), and then do Promise.all(). If you do this, you can test for native support of web components which means 'webcomponentsready' doesn't fire at all[0], and resolve it immediately, and your code will still work when Polymer change to using native web components...

Max.

Darin Hensley

unread,
Dec 27, 2015, 4:33:21 PM12/27/15
to Polymer, darin....@gmail.com
Thanks, I originally did this but I realized using a promise is a bad fit. The reason being, the queries used are blocking since they are non I/O, which means sync. I am still implementing a function that is checking and redoing if so, but without a promise. 

However, I feel that this might be a bug in polymer because when dom manipulation js script is placed last in chrome, then all elements are garuanteed to be ready. This is from documentation(in the 0.5 to 1.0 migration docs). I will file a bug tonight. 

Max

unread,
Dec 30, 2015, 6:31:51 AM12/30/15
to Darin Hensley, Polymer
Did you file a bug?

Thanks,

Max.

Darin Hensley

unread,
Dec 30, 2015, 9:40:11 AM12/30/15
to Polymer
Naw.... haven't got a chance yet. My cat has diabetes and I've had my hands full trying to get him healthy again. 


On Tuesday, December 22, 2015 at 9:44:05 PM UTC-6, Darin Hensley wrote:

Darin Hensley

unread,
Jan 2, 2016, 1:27:29 AM1/2/16
to Polymer, darin....@gmail.com
Ok, that issue just hit me again so here it is with the details:

Max

unread,
Jan 2, 2016, 5:29:19 AM1/2/16
to Darin Hensley, Polymer

Just thought I'd mention this article on promises...it mentions their use for synchronous stuff too (mixing them), so thought it might be of interest :
<http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html?utm_source=javascriptweekly&utm_medium=email>

Max.


Darin Hensley

unread,
Jan 2, 2016, 10:15:25 AM1/2/16
to Polymer, darin....@gmail.com
Thank you for the suggestion, but there is no reason to use a promise here. The element queries are blocking operations, because they are none I/O. This means the operation is already sync. To use a promise on a sync operation to make it a sync operation is unnecessary code. 

Max

unread,
Jan 2, 2016, 4:17:56 PM1/2/16
to Darin Hensley, Polymer
I wasn't suggesting is as a solution to your problem - I don't know what's going on there and I imagine Eric will get to the bottom of it - more as a matter of interest (as I mentioned) for all...

I'm watching the issue with interest :)

Max.

Darin Hensley

unread,
Jan 3, 2016, 12:01:00 AM1/3/16
to Polymer, darin....@gmail.com
Well, I'm not getting the sync behavior I was expecting.....even though I should by the laws of event loop. So, I resorted back to using a promise. So far so good...although it's a little premature I'm excited that this will fix it so I'll post my new code now. Coming from python, I'm not a fan of functions over 5 lines...but in this case it's a hackish fix so anything goes.


function makeGlobalElements() {
  var noNameFoo = new Promise(function(resolve, reject) {
    //elements is not routing list, routing list is elementList
    function _createElements() {
      panel = document.querySelector('paper-header-panel[main]');
      rippleElement = document.querySelector('#ripple-element');
      toolbar = document.querySelector('#main-toolbar');
      headerName = document.querySelector('#name-title');
      drawer = document.querySelector('paper-drawer-panel');
      mainPanelContent = document.querySelector('#mainPanelContent');
    }

    var iteration = 1;
    var completed = false;

    function _checkElements() {
      var elements = [panel, rippleElement, toolbar, headerName,
       drawer, mainPanelContent];

      completed = elements.every(function(el) {
        if (el !== null && typeof el !== 'undefined' && el.nodeType === 1) {
          return true;
        } else {
          return false;
        }
      });
    }

      var NUMBER_CHECKS = 100;
      do {
        _createElements();
        _checkElements();
        iteration++;
        if (!completed) {
          console.log(iteration);
          console.log(iteration < NUMBER_CHECKS && completed);
          console.log('Elements weren\'t ready, running again');
          console.log('Trying attempt # ' + iteration);
        } else {
          console.log('yay! elements good');
          resolve();
        }
      } while(iteration < NUMBER_CHECKS && !completed);
  });
  return noNameFoo;
};

function attatchListeners() {
  panel.addEventListener("content-scroll", moveTitle);
  ['webkitAnimationEnd', 'animationend']
  .forEach(function(vendor) {
    mainPanelContent.addEventListener(vendor, function (animationEvent) {
      if (animationEvent.animationName === "slide-down") {
        afterSlideDown.runStack();
        mainPanelContent.classList.remove('slide-down-now');
      }
    });
    headerName.addEventListener(vendor, function() { 
      headerName.classList.remove('fade-title'); 
    });
  });
};

//polymer bug where elements aren't ready in time

function initializeYay() {
  makeGlobalElements().then(function() {;
    attatchListeners();
    setUpRoutes();
    removeSplash();
    //fetchPdfjs();
Reply all
Reply to author
Forward
0 new messages