rangy icon indicating copy to clipboard operation
rangy copied to clipboard

AMD implies rangy is initialized, but it still waits for readyState == 'complete'

Open thomasbachem opened this issue 10 years ago • 3 comments

When using rangy via AMD module loading, I expect it to be initialized and usable when the AMD callback is fired. But it waits for DOM ready (see core.js#L501), which is problematic.

Test page (assuming rangy is located in a "rangy/" directory next to the test page):

<!DOCTYPE html>
<html>
<head>
    <title>Rangy AMD Test</title>
    <script src="http://requirejs.org/docs/release/2.1.20/comments/require.js"></script>
</head>
<body>
    <img src="http://deelay.me/1000/http://deelay.me/img/1000ms.gif">
    <script>
        requirejs(['rangy/rangy-core'], function(rangy) {
            if(rangy.createRange) {
                alert('rangy.createRange() is available!');
            } else {
                alert('rangy.createRange() is not yet available!');
            }
        });
    </script>
</body>
</html>

Alerts me with rangy.createRange() is not yet available! in Chrome 45 Beta, Safari 8 and Firefox 39 (others not tested).

thomasbachem avatar Aug 12 '15 22:08 thomasbachem

You can initialize Rangy manually with rangy.init(). Rangy needs the DOM to be usable when it initializes so it can't assume it can initialize immediately.

timdown avatar Aug 18 '15 22:08 timdown

@timdown But that would mean that I always have to call rangy.init() whenever I use Rangy just to make sure it's initialized. Since AMD modules are independent from each other, I cannot be sure that another module already called rangy.init().

My experience is that when I include scripts just before </body>, the DOM is usable regardless of readyState == 'complete'. That's a best practice many developers stick to.

I think it would be better if Rangy would always initialize directly but throw an error if a functionality is used and the DOM not loaded yet. Simply returning an object with uninitialized/missing methods feels wrong.

thomasbachem avatar Sep 23 '15 14:09 thomasbachem

I also ran into this issue. I am using the highlighter module and I am getting Uncaught TypeError: f.default.createHighlighter is not a function in my production error log.

Since loading time is variable this issue is very hard to reproduce and debug. I tested my assumption by delaying the initialization at https://github.com/timdown/rangy/blob/master/src/core/core.js#L509:

// Add a fallback in case the DOMContentLoaded event isn't supported
setTimeout(function() {
   addListener(window, "load", loadHandler);
}, 3000);

This should be properly documented in the docs.

LeZuse avatar Mar 01 '16 14:03 LeZuse