xml3d / xml3d.js

The WebGL/JS implementation of XML3D
Other
75 stars 25 forks source link

XML3D doesn't load properly with require.js #140

Closed Arsakes closed 9 years ago

Arsakes commented 9 years ago

As In title, require.js provides a way to load non-AMD (Asynchronous module definition) modules, so it should work with XML3D, despite this it doesn't. http://stackoverflow.com/questions/32018311/loading-xml3d-with-require-js

csvurt commented 9 years ago

You're right, this was a simple oversight when initializing XML3D. I've pushed a fix to our upcoming 4.9.4 hotfix that should be released later this week.

Thanks for the bug report!

Arsakes commented 9 years ago

Works as a charm. Closing. Just a comment: This solution works however it seems that one needs to have tag present in document BEFORE xml3d library is actually loaded. Remember this when generating element from script.

csvurt commented 9 years ago

It's supposed to work if you add the <xml3d> element later too. I just extended the example code from your StackOverflow question and it seemed to work with the hotfix-4.9.4 build:

HTML Document:

<html>
  <head>
     ... scripts ...
  </head>
  <body>
    <div id="content"></div>
  </body>
</html>

main.js:

...
requirejs(['xml3d'], function (XML3D) { console.log(XML3D) });

setTimeout(function () {
    var xml = "<xml3d> ...xml3d scene... </xml3d>";
    var doc = $.parseXML(xml);
    $('#content').append(doc.childNodes[0]); //first child is the xml3d element
}, 1000)

Are you doing something different that causes the xml3d element to not be initialized after it's added?

Arsakes commented 9 years ago

Here is my code that doesn't work:

requirejs(['lib1', 'lib2'..., 'xml3'], function (lib1, lib2.... XML3D) {
  var scene = new lib1();  // it generates <xml3d> </xml3d> and the content !
}

Whereas this works:

requirejs(['lib1', 'lib2'...], function (lib1, lib2....) {
  var scene = new lib1(); // it generates <xml3d> </xml3d> and the content !
  requirejs(['xml3d'], function (XML3D) {
    console.log('')
  }
}

The whole code is pretty complex lets just say that libN are Backbone models and views "classes" used to generate xml3d elements and canvas itself (xml3d element).

In first snippet, html elements are properly generated (one can check the html source of the site and its ok). However instead of nice canvas i get only thin stripe with some numbers in it (those numbers are some values i've put elemnt i guess.

csvurt commented 9 years ago

Ok looks like there was another bug that slipped through because I was using $.parseXML, which causes the tagName field of generated elements to be lower case instead of the normal upper case in HTML.

I pushed a fix to the hotfix-4.9.4 branch that should work for both cases. Could you build it again and let me know if that's fixed it for you?

Arsakes commented 9 years ago

It still doesn't work. I think we didn't tackled the issue here. NOTE: this is based on assumption that XML3D requires <xml3d> element to be present in the dom. Now correct if I'm wrong, but I think my problem doesn't have anything to do with document.readyState value. In my case is I use script that at some points creates <xml3d> element - usually after the document is loaded. So it is perfectly possible for <xml3d> to not exist and for variable document.readyState === "complete". In such case XML3D would init to soon and won't work. I've did an experiment, I've put an additional line in front of XML3D library file:

console.log('STATE 0:', document.readyState)

And used my example (main loader for require.js)

requirejs(['lib1', 'xml3d'...], function (lib1, xml3d....) {
  console.log('STATE 1:', document.readyState);
  var scene = new lib1(); // now we generate the <XML3D> element
}

The result is:

STATE 0: completed
STATE 1: completed

and obviously XML3D doesn't work because there was no <xml3d> elem at the time of init.

My conclusion is: you cannot solve this problem by checking document state. You must check if 'xml3d' exists or provide function for user to init xml3d by hand.

csvurt commented 9 years ago

We also register a MutationObserver for inserted nodes the first time xml3d.js is loaded. This should detect any xml3d elements that are added to the DOM after the fact, even if they're "hidden" inside other elements that are appended (ie. a <div> with an <xml3d> element inside). If you search for the function resolveMutations in your xml3d.js you should see it.

The bug I fixed previously was actually inside this listener. It checked for elements that were added to the DOM with the tagName "xml3d" but didn't catch those with tagName "XML3D", that's why I thought it might have been what caused your problem.

Could you check if this works for you using the hotfix build?

requirejs(['jquery-2.1.1', 'xml3d'], function() {
    var xml3dElement = $('<xml3d id="xml3dElem" width: 300px; height: 200px;"></xml3d>');
    $("body").append(xml3dElement);
});

You can change the libraries that are being loaded if you want. I've tried this here and it seems to initialize the XML3D element properly, if it also works for you at least we know the problem must be somewhere else. In that case it would be helpful to see your code that creates the xml3d element and adds it to the DOM, maybe it's doing something that we didn't anticipate.

Arsakes commented 9 years ago

It doesn't work. I assume that the effect should be creation of <canvas> element somewhere in DOM. It is not created. The same html code works if put directly into HTML (without jQuery appending). Maybe its a browser issue. Mutations events are not ver well supported. I'm using latest chromium (not chrome).

NOTE: I've used corrected version of your code:

<xml3d id="xml3dElem" width: 300px; height: 200px;"></xml3d>

->

 <xml3d id="xml3dElem" style="width: 300px; height: 200px;"></xml3d>
csvurt commented 8 years ago

FYI 3f0b1ba8b5b86e141c17f5f15f0792f31a0a77fa fixed another bug in the XML3D init handling, it may have been what was causing the problems here. This fix is now on master and the deployed scripts on xml3d.org.