Giter Site home page Giter Site logo

Comments (38)

WebReflection avatar WebReflection commented on May 23, 2024

that's actually expected and I've no idea why native would do that, if the node is not live.

Unfortunately there's also no way I am going to replace all DOM methods, getters, and setters, to support such edge/rare case, specially because I would need to place mutators in every DOM node.

There are ways to workaround this "issue", but I'd like to understand what's your use case.

from document-register-element.

einarq avatar einarq commented on May 23, 2024

Had the same issue I believe, that was during testing of Backbone views.
Testing of the is views is best done without adding them to the DOM for a
couple of reasons, mainly performance and ensuring isolation of code.

On Wed, May 13, 2015 at 7:02 PM, Andrea Giammarchi <[email protected]

wrote:

that's actually expected and I've no idea why native would do that, if the
node is not live.

Unfortunately there's also no way I am going to replace all DOM methods,
getters, and setters, to support such edge/rare case, specially because I
would need to place mutators in every DOM node.

There are ways to workaround this "issue", but I'd like to understand
what's your use case.


Reply to this email directly or view it on GitHub
#21 (comment)
.

from document-register-element.

WebReflection avatar WebReflection commented on May 23, 2024

adding mutators to every node that is not live will kill real-world/production performance ... which one would you pick? ;-)

Like I've said, there are workarounds, like invoking createdCallback manually after feature detecting that is not invoked otherwise, then you have the attached and detached that might not work as well.

Actually, I am not sure how native does when nodes are not live, regarding attribute changes and other two callbacks. If it's just a matter of asynchronous createdCallback invocation, then I might put back the ugly rAF/timer when nodes were created non live.

from document-register-element.

tunderdomb avatar tunderdomb commented on May 23, 2024

I believe they should be called no matter if the parent is live or not. The created callback at the very least would make sense, because the element did get just instantiated after all.
If you create a new instance with the constructor:

new MyElement()
// created
var div = document.createElement("div");
div.appendChild(new MyElement())
// created
// no attached callback was fired

but native calls the attached callback even outside the document too.

Real world use case:

There's a custom element which is being displayed periodically for the user. This element has an initial state that's need to be re-set every time it's shown, but the values of its state is dynamic each time. The element's state is managed with the element's API. The element can't be added to the DOM before it's re-set, but it can't be initialized outside of the DOM either, because the element's API is not available until it's inserted.

I understand the performance implications.
The quick and dirty workaround I used was to insert and immediately remove the element to and from the DOM so it gets initialized, because I didn't want to implement flags just for checking if the element is native or not.

So as I understand, until widespread native support, we have to keep this in mind.

from document-register-element.

WebReflection avatar WebReflection commented on May 23, 2024

do you know if webcomponents.js works as you would expect?

I need to double check the code because it was there and got removed at some point when somebody pointed out it should not have initialized the node if not live.

I also would like to understand if this is the entry point for problems: attribute changes without initialization, attached without having control over all possible node if not via overwrite of all possible methods in order to trigger checks, etc etc ... if it's as it is, it's a caveat that should be documented but a consistent one. Meaning until the node goes live, nothing happens.

This is IMO better than "just init happens" then nothing else work offline, what do you think?

from document-register-element.

WebReflection avatar WebReflection commented on May 23, 2024

also relevant ... since partially already discussed:
#15 (comment)

it turned out that innerHTML overrides cause also tons of problems, so even fixing createElement gotcha, it's hard to fix all the things that could happen via innerHTML

Moreover, innerHTML is still used only because it's faster, wrapping it in not so fast/updatede browsers would result in perfromance problems.

IIRC Polymer had already faced performance issues with real world apps, I really would like to avoid to find this polyfill there too, and I'd like to understand if there's a design to improve in your logic.

What I mean is the following:

  1. why do you track and change states of nodes that might never been showed?
  2. why cannot you do the same and make the createdCallback the activator of the rest of the logic?
  3. since you want to register offline nodes, why would you need an attachedCallback anyway?

Don't get me wrong, I understand this is how native behaves, but if there is an alternative, let's say webcomponents, that is closer to native but slower and bigger than this, I rather suggest developers that need offline features to move in there and leave a choice, instead of two slower, bigger, less compatible, more problematic, also identical polyfills.

https://github.com/WebComponents/webcomponentsjs

Thanks for your patience

from document-register-element.

tunderdomb avatar tunderdomb commented on May 23, 2024

I'll check webcomponents.js again today, but if I remember correctly I had the same issue there with attachedCallbacks not firing. But I'll take a look again later.

Regarding your questions about the design:

I think there sure are alternatives, and I'll look into them.
I'm happy that at least I have a better understanding of the situation.

  1. It might never shown, but the first time its shown, it needs to be initialized offline.
  2. The problem is that the element's api is not available at the time, not just createdCallback
  3. The attachedCallback may contain logic that initializes the element according to it's parent's state

Consider this:

document.registerElement('my-element', {
    prototype: Object.create(
        HTMLElement.prototype, {
            createdCallback: {
                value: function () {
                    // set default values..
                }
            },
            attachedCallback: {
                value: function () {
                    if (this.parentNode.hasAttribute("custom-attribute")) {
                        // set values depending on the parent's state
                    }
                }
            },
            customApi: {
                value: function (values) {
                    // set element's state dynamically
                }
            }
        })
});

var div;
var myElement;

function showElement (dynamicValues) {
    if (!div) {
        // initialize a widget the first time it's requested
        // save references because they won't change, 
        // just internal state like texts and attributes
        div = document.createElement("div");
        // imagine this is coming from a complex string template
        div.innerHTML = "<span><my-element></my-element></span>";
        myElement = div.getElementsByTagName("my-element")[0];
    }
    // set the state of the element according to dynamic values
    // it's expected that the element has the custom API methods here
    myElement.customApi(dynamicValues);
    // insert the element into the dom
    document.body.appendChild(div);
}

// when not needed, hide the element
function hideElement () {
    if (div) {
        div.remove();
    }
}

I think consistency's better, even when it comes with limitations.
If overriding methods to provide this behavior would introduce performance drops I vote for a documented caveat + possible workarounds.

Thank you for your reply.

from document-register-element.

WebReflection avatar WebReflection commented on May 23, 2024

Wait a second ... if you put console.log in the prototype you'll have this sequence on a natively supported browser: created, custom, attached

This means that attached is indeed invoked only once the node is live, as specs say, not when is appended or created inside other nodes. This also means that your customApi method does different things accordingly with the node parent attributes, as example, you might have surprises.

You are also probably trusting a synchronous createdCallback which is not actually necessarily the case, specially when the polyfill uses observers to avoid performance issue, as discussed in the other bug I've liked before.

What I think is that you should detach custom API live interactions with the node itself if this has not been created, and eventually verify all the things at runtime when the live DOM knows the element.

This should not compromise your logic, and guard against polyfill with asynchronous behavior. Please bear in mind both polyfills and some early implementation might have an asynchronous behavior too so it's good to create components that react accordingly with these methods, and not the other way round.

As example, here is how I'd solve your problem if you really need to use innerHTML

// keep the custom element constructor reference
var MyElement = document.registerElement('my-element', {
    prototype: Object.create(
        HTMLElement.prototype, {
            createdCallback: {
                value: function () {
                    if (this._values) {
                        // do things values related
                    }
                }
            },
            attachedCallback: {
                value: function () {
                    if (this.parentNode.hasAttribute("custom-attribute")) {
                        // set values depending on the parent's state
                    }
                }
            },
            customApi: {
                value: function (values) {
                    this._values = values;
                }
            },
            _values: {
                writable: true,
                value: null // or defaults values
            }
        })
});

var div;
var myElement;

function showElement (dynamicValues) {
    if (!div) {
        // initialize a widget the first time it's requested
        // save references because they won't change, 
        // just internal state like texts and attributes
        div = document.createElement("div");
        // imagine this is coming from a complex string template
        div.innerHTML = "<span><my-element></my-element></span>";
        myElement = div.getElementsByTagName("my-element")[0];
    }
    // set the state of the element according to dynamic values
    // it's expected that the element has the custom API methods here
    // be sure the method is correct one through the prototype
    MyElement.prototype.customApi.call(myElement, dynamicValues);
    // insert the element into the dom
    document.body.appendChild(div);
}

// when not needed, hide the element
function hideElement () {
    if (div) {
        div.remove();
    }
}

Moreover

If you ditch innerHTML when you create your DOM at runtime you would have the API directly exposed and the created directly invoked.

document.registerElement('my-element', {
    prototype: Object.create(
        HTMLElement.prototype, {
            createdCallback: {
                value: function () {
                    console.log('created');
                }
            },
            attachedCallback: {
                value: function () {
                    console.log('attached');
                    if (this.parentNode.hasAttribute("custom-attribute")) {
                        // set values depending on the parent's state
                    }
                }
            },
            customApi: {
                value: function (values) {
                    console.log('custom');
                }
            }
        })
});

var div;
var myElement;

function showElement (dynamicValues) {
    if (!div) {
        // initialize a widget the first time it's requested
        // save references because they won't change, 
        // just internal state like texts and attributes
        div = document.createElement("div");
        // imagine this is coming from a complex string template
        div.innerHTML = "<span><my-element></my-element></span>";
        myElement = div.querySelector("my-element");
        if (!myElement.customApi) {
            myElement.replaceWith(
              myElement = document.createElement('my-element')
            );
        }
    }
    // set the state of the element according to dynamic values
    // it's expected that the element has the custom API methods here
    myElement.customApi(dynamicValues);
    // insert the element into the dom
    document.body.appendChild(div);
}

// when not needed, hide the element
function hideElement () {
    if (div) {
        div.remove();
    }
}

On non native browsers, this will log created, custom, and then attached
It's a workaround, but also a preferred solution compared to an innerHTML based one.

Please note that you can make the check generic via

function isCustomElement(el) {
  return 'createdCallback' in el            ||
         'attachedCallback' in el           ||
         'detachedCallback' in el           ||
         'attributeChangedCallback' in el;
}

and verify with same code shown before ...

        myElement = div.querySelector("my-element");
        if (!isCustomElement(myElement)) {
            myElement.replaceWith(
              myElement = document.createElement('my-element')
            );
        }

About complex templates

This is the most tricky part and what you basically need is an array of registered elements, and an helper to set innerHTML.

You might find better or more elegant solutions but this is the hint, you wrap upfront once document.registerElement and you use innerHTML(el, html) instead of el.innerHTML = html.

// right after this poly, before any other script you have in place
var innerHTML = (function (document) {
    // feature detect the problem
    var
        register = document.registerElement,
        div = document.createElement('div'),
        dre = 'document-register-element',
        initialize,
        registered
    ;
    register.call(
        document,
        dre,
        {prototype: Object.create(
            HTMLElement.prototype,
            {createdCallback: {value: Object}}
        )}
    );
    div.innerHTML = '<' + dre + '></' + dre + '>';
    // if natively supported, nothing to do
    if (div.querySelector(dre).createdCallback) {
        // return just an innerHTML wrap
        return function (el, html) {
            el.innerHTML = html;
            return el;
        };
    }
    // in other cases
    registered = [];
    initialize = function (el) {
        if (
            'createdCallback' in el         ||
            'attachedCallback' in el        ||
            'detachedCallback' in el        ||
            'attributeChangedCallback' in el
        ) return;
        for (var
            type = el.getAttribute('is'),
            name = el.nodeName,
            node = document.createElement.apply(
                document,
                type ? [name, type] : [name]
            ),
            attributes = el.attributes,
            i = 0,
            length = attributes.length,
            attr;
            i < length; i++
        ) {
            attr = attributes[i];
            node.setAttribute(attr.name, attr.value);
        }
        el.replaceWith(node);
    };
    // augment the document.registerElement method
    document.registerElement = function registerElement(name, info) {
        var type = info.extends;
        name = (type ? (type + '[is=' + name + ']') : name).toLowerCase();
        if (registered.indexOf(name) < 0) registered.push(name);
        return register.apply(document, arguments);
    };
    return function (el, html) {
        el.innerHTML = html;
        registered.forEach.call(
            el.querySelectorAll(
                registered.join(',')
            ),
            initialize
        );
        return el;
    };
}(document));

Now we've gone full circle, and we can go back to your initial example just changing one switch.

document.registerElement('my-element', {
    prototype: Object.create(
        HTMLElement.prototype, {
            createdCallback: {
                value: function () {
                    console.log('created');
                }
            },
            attachedCallback: {
                value: function () {
                    console.log('attached');
                    if (this.parentNode.hasAttribute("custom-attribute")) {
                        // set values depending on the parent's state
                    }
                }
            },
            customApi: {
                value: function (values) {
                    console.log('custom');
                    // set element's state dynamically
                }
            }
        })
});

var div;
var myElement;

function showElement (dynamicValues) {
    if (!div) {
        // initialize a widget the first time it's requested
        // save references because they won't change, 
        // just internal state like texts and attributes
        div = document.createElement("div");
        // imagine this is coming from a complex string template
        innerHTML(div, "<span><my-element></my-element></span>"); // <=== there !
        myElement = div.getElementsByTagName("my-element")[0];
    }
    // set the state of the element according to dynamic values
    // it's expected that the element has the custom API methods here
    myElement.customApi(dynamicValues);
    // insert the element into the dom
    document.body.appendChild(div);
}

The result will be identical in both native and polyfilled.

I hope this helps at least a little bit.

from document-register-element.

tunderdomb avatar tunderdomb commented on May 23, 2024

Not just a little bit! I really appreciate your effort.
Wrapping innerHTML into a helper and patching elements is clever. I can go on with it from here.

Also, your suggestion not to rely on synchronous callbacks is a good warning too.

Thanks for the reply and the workaround solution!

from document-register-element.

WebReflection avatar WebReflection commented on May 23, 2024

Please have a look at the new README, specifically this section related to a better and tested version of the function I've written in here.

Full helper source code and its minified version

Once again that should be placed after the poly, and before the rest of the logic.

Here new tests and please note Webkit based browsers will invoke createdCallback asynchronously, be carefull with custom APIs used before an element has been created.

If this works, please close this bug as it will remain, at this point, a won't fix.

from document-register-element.

SerkanSipahi avatar SerkanSipahi commented on May 23, 2024

@tunderdomb I havent tried it but it should work:

var docfrag = document.createDocumentFragment();
var myElement = document.createElement("my-element");
docfrag.appendChild(myElement);
// created
// attached

from document-register-element.

tunderdomb avatar tunderdomb commented on May 23, 2024

Checked webcomponents.js, does the same thing; same problem: not calling callbacks outside the DOM.

A note regarding attachedCallback:

Unless specified otherwise, this callback must be enqueued whenever custom element is inserted into a document and this document has a browsing context.

Yes, it doesn't say it should be called on offline nodes.

I tried the innerHTML helper, and found two issues with it:

  • replaceWith is not a standard method
  • innerHTML doesn't handle nested custom elements
<custom-element>
  <another-element>
      <span></span>
  </another-element>
</custom-element>

The helper you provided creates a new element for every custom element it finds in the string provided (node = document.createElement.apply). It ignores the innerHTML of those elements. In the above example the innerHTML value of the newly created node will be empty. But it should contain a span. Also, if you run it on the above string template, it returns an empty custom-element too, which should contain another custom element with a span.

So I tweaked it a little and added recursion to it.
Didn't find contribution notes in the readme, so I paste it here, but if you'd prefer a pr I'd do that too when I find time for it.

var
        register = document.registerElement,
        div = document.createElement('div'),
        dre = 'document-register-element',
        innerHTML = register.innerHTML,
        initialize,
        registered
        ;

    // avoid duplicated wrappers
    if (innerHTML) return innerHTML;

    // feature detect the problem
    register.call(
        document,
        dre,
        {prototype: Object.create(
            HTMLElement.prototype,
            {createdCallback: {value: Object}}
        )}
    );

    div.innerHTML = '<' + dre + '></' + dre + '>';

    // if natively supported, nothing to do
    if ('createdCallback' in div.querySelector(dre)) {
        // return just an innerHTML wrap
        return (register.innerHTML = function (el, html) {
            el.innerHTML = html;
            return el;
        });
    }

    // in other cases
    registered = [];
    initialize = function (el) {
        if (
            'createdCallback' in el         ||
            'attachedCallback' in el        ||
            'detachedCallback' in el        ||
            'attributeChangedCallback' in el
        ) return;
        for (var
                 type = el.getAttribute('is'),
                 name = el.nodeName,
                 node = document.createElement.apply(
                     document,
                     type ? [name, type] : [name]
                 ),
                 attributes = el.attributes,
                 i = 0,
                 length = attributes.length,
                 attr;
             i < length; i++
        ) {
            attr = attributes[i];
            node.setAttribute(attr.name, attr.value);
        }
        // run the createdCallback so it can work with the correct attributes
        node.createdCallback();
        // initialize children too
        innerHTML(node, el.innerHTML);
        // swap nodes
        el.parentNode.replaceChild(node, el);
    };

    innerHTML = function (el, html) {
        el.innerHTML = html;

        var children = el.children;
        var i = -1;
        var l = children.length;

        while (++i < l) {
            if (registered.indexOf(children[i].nodeName.toLocaleLowerCase()) !== -1) {
                initialize(children[i])
            }
        }

        return el;
    };

    var registerElement = function(type, options) {
        var name = (options.extends ?
            (options.extends + '[is="' + type + '"]') : type
        ).toLowerCase();
        if (registered.indexOf(name) < 0) registered.push(name);
        return register.apply(document, arguments);
    };

    document.registerElement = registerElement;
    // augment the document.registerElement method
    registerElement.innerHTML = innerHTML;

from document-register-element.

WebReflection avatar WebReflection commented on May 23, 2024

replaceWith is not a standard method

it is standard, and there's more standard you might want to use (like append, that's new DOM4 stuff too)

I use dom4 since quite ever, I strongly suggest you to do the same. Tests have it in too.

I should probably specify it as dependency or maybe just use replaceChild, but I believe if you want to use Custom Elements you want to use modern DOM in all its glory.

innerHTML doesn't handle nested custom elements

I'll check that ... your code won't work anyway, there are 2 ways to register elements, via node name and via extends.

Please read more about this here:
https://github.com/WebReflection/document-register-element#htmltablerowinputselectotherselement

Thanks for the report

from document-register-element.

tunderdomb avatar tunderdomb commented on May 23, 2024

Sorry about that, I just noticed that it was undefined in Chrome, so immediately assumed it wasn't standard. My apologies.

With the modifications I did, it worked for me. Elements registered correctly, even a template with nested custom elements. Anyway, thank you for your suggestion, it helped me a great deal.

from document-register-element.

WebReflection avatar WebReflection commented on May 23, 2024

it won't work if you have <input is="x-date"> as example, 'casue nodeName will be input, but you register x-date instead ;-)

I'll have a look as soon as I can and try to figure out how to solve "all the things"

Cheers

from document-register-element.

tunderdomb avatar tunderdomb commented on May 23, 2024

Now that I didn't try, and you're right it won't work.
The loop might check for the is attribute of the node at hand, and use it to see if it's a registered custom element. Like:

if (
  registered.indexOf(children[i].nodeName.toLowerCase()) !== -1 
  || (registered.indexOf(children[i].getAttribute("is")||"").toLowerCase() !== -1
) {
  initialize(children[i])
}

Just improvised.

"All the thing" shall come when browsers implement standards :3

from document-register-element.

WebReflection avatar WebReflection commented on May 23, 2024

so, I haven't pushed/bumped new version yet, but could you please verify the current innerHTML.js version works as expected? (there's still need for dom4 here, but nested nodes should be just fine)

from document-register-element.

SerkanSipahi avatar SerkanSipahi commented on May 23, 2024

Is this really standard (innerHTML/NestedElements/createdCallback/etc) ? where the specified?

from document-register-element.

WebReflection avatar WebReflection commented on May 23, 2024

@SerkanSipahi I am not sure I understand your question ... innerHTML is a helper function to avoid problems when you use innerHTML instead of creating nodes via DOM.

Nested elements is something that needs to be solved within the helper.

createdCallback is part of Custom Elements standard together with others

from document-register-element.

smilland avatar smilland commented on May 23, 2024

@WebReflection Thanks so much for providing the innerHTML workaround. Would you please bump up the version with the newest fix so that we could point to that?

from document-register-element.

smilland avatar smilland commented on May 23, 2024

@WebReflection Thanks for you quick response! However, when we were trying to use the innerHTML function, there is an error "el.replaceWith is not a function". Do you have any idea on what is causing that? Thanks!

from document-register-element.

WebReflection avatar WebReflection commented on May 23, 2024

you should upgrade your DOM ... and I should mention this somewhere

from document-register-element.

WebReflection avatar WebReflection commented on May 23, 2024

actually, you know what? never mind, I've updated using good old replaceChild instead, however I still strongly suggest you to upgrade your DOM ;-)

from document-register-element.

smilland avatar smilland commented on May 23, 2024

@WebReflection Thanks. And another question, we notice that the sequence is a little different. In this innerHTML function, the createdCallback function is called before binding the attributes. Our tests are failing since we are testing in createdCallback whether the attributes have already been bound. And in Chrome, looks like it also binds the attributes first. Any thoughts on that?

from document-register-element.

WebReflection avatar WebReflection commented on May 23, 2024

not sure I udnerstand what you mean ... if it's not created, how can it has attributes? any little example to verify?

from document-register-element.

WebReflection avatar WebReflection commented on May 23, 2024

OK @smilland I see what you mean ... so here the thing: in order to copy over attributes I need a node. In order to have a node I need to create one and when I create a node, the createdCallback triggers.

For the current logic it's expected, but I understand is not ideal in your case because you expect everything to be there.

Please bear in mind this innerHTML helper is some sort of "magic wrap" but the underlying logic is not touched. These are two different files indeed, and I need to think carefully how to do what you expect without causing troubles to the rest of the logic that is not based to innerHTML

Meanwhile, I wonder if in your case you could simply move the attributes related logic to attachedCallback instead of createdCallback as temporary work around until we find a better solution?

from document-register-element.

WebReflection avatar WebReflection commented on May 23, 2024

I believe 0.3.5 should work as expected ... is a bit hacky solution, but this whole poly is some sort of big hack so probably I won't care much. Please let me know if latest works, thanks.

from document-register-element.

WebReflection avatar WebReflection commented on May 23, 2024

P.S. you need to update both files, document-register-element and innerHTML

from document-register-element.

smilland avatar smilland commented on May 23, 2024

Thanks so much for all your help. We tried it out, it definitely works! We appreciate all your efforts.

from document-register-element.

WebReflection avatar WebReflection commented on May 23, 2024

no problem ... btw, who is "we", if I might? :-)

from document-register-element.

WebReflection avatar WebReflection commented on May 23, 2024

added enhancement label, will close still as won't fix since I've provided a work around. Feel free to reopen if you find something wrong. Will try to push again to the CDN so 0.3.6 will have everything in.

Cheers

from document-register-element.

trusktr avatar trusktr commented on May 23, 2024

@WebReflection What's the difference between appendChild and append from DOM4?

from document-register-element.

WebReflection avatar WebReflection commented on May 23, 2024

It's in standards , append accepts strings too and doesn't return the
appended child. WebKit has it already

On Sunday, 11 September 2016, Joseph Orbegoso Pea [email protected]
wrote:

@WebReflection https://github.com/WebReflection What's the difference
between appendChild and append from DOM4?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#21 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAFO9Y-PvCtPoXJXYqnJym4FU7LG3RfEks5qpGLWgaJpZM4EZYEI
.

from document-register-element.

trusktr avatar trusktr commented on May 23, 2024

So it's effectively the same as innerHTML and appendChild combined into a single shortcut method. Cool!

Not returning the child could possibly be unhelpful in the case of strings. Would be nice to do like jQuery:

let div = someEl.append('<div>blah</div>')
console.log(div.innerHTML) // blah

from document-register-element.

WebReflection avatar WebReflection commented on May 23, 2024

That's not what specs were written. It's not going to change.

On Wednesday, 14 September 2016, Joseph Orbegoso Pea <
[email protected]> wrote:

So it's effectively the same as innerHTML and appendChild combined into a
single shortcut method. Cool!

Not returning the child could possibly be unhelpful in the case of
strings. Would be nice to do like jQuery:

let div = someEl.append('

blah
')console.log(div.innerHTML) // blah


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#21 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAFO9eLnmGBTlG_wRTKgQFTHeuV0pSvdks5qp1yfgaJpZM4EZYEI
.

from document-register-element.

WebReflection avatar WebReflection commented on May 23, 2024

BTW, append() is more like appendChild and textContent, not innerHTML

You should've tried it first ;-)

It use to be on specs, it has been put on hold but it shipped regardless in WebKit so it's already adopted.

This, together with prepend and remove, replaceWith, before and after

from document-register-element.

trusktr avatar trusktr commented on May 23, 2024

What's the advantage of having both appendChild and append? When would we rather use append than appendChild?

from document-register-element.

WebReflection avatar WebReflection commented on May 23, 2024

legacy will keep appendChild around forever. Other shortcuts have been around for years but for some reason commented out recently.

DOM4 poly, for legacy reasons, won't drop these. You can use whatever you want if dom4 is included.

Bear in mind this is CustomElements polyfill, not the DOM4 one.

from document-register-element.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.