WebReflection / wicked-elements

Components for the DOM as you've never seen before
https://medium.com/@WebReflection/a-wicked-custom-elements-alternative-6d1504b5857f
ISC License
244 stars 12 forks source link

Can we expose handleEvent and Bootstrap methods. #13

Closed MikeVaz closed 5 years ago

MikeVaz commented 5 years ago

In the context of web components using this library is not very handy IMHO. But a pattern of delegating event handling using handleEvent is a great find.

I suggest to expose handleEvent pattern and Bootstrap method from the library.

E.g.

// Composition just to make example work
function mixin(cls, obj) {
  class cls1 extends cls {};
  Object.assign(cls1.prototype, obj);
  return cls1; 
}

// Could be a reusable behavior from the wicked elements library
var handleEvent = {
  handleEvent(event) {
    var type = 'on' + event.type;
    if (type in this)
      this[type](event);
  }
}

// Define a component extending HTMLElement and mixing with handleEvent behavior
class MyComponent extends mixin(HTMLElement, handleEvent) {
  onclick(event) {
    alert('click');
  }
  constructor() {
    super();
    this.addEventListener('click', this) // We could use this.bootstrapEvents('click', ... ) instead from the wicked elements library.

  }  
}

customElements.define('my-component',MyComponent);

document.body.innerHTML += '<my-component>Click me</my-component>';

https://codepen.io/MikeVaz/pen/xmmOEr

WebReflection commented 5 years ago

In the context of web components using this library is not very handy IMHO.

Why?

I suggest to expose handleEvent pattern and Bootstrap method from the library.

If you define your own handleEvent that'd be used. In case it's not clear, the bootstrap passes through the object you use to define the component, you have full control over everything, and the handleEvent pattern is there to stay.

MikeVaz commented 5 years ago

I just didn't want to create more libraries to use code which you already have in the wicked elements repo. So I tried to explain what we want to use from the library in our case. As of now this is not possible. So my only choice is to copy paste the code.

WebReflection commented 5 years ago

I think you should rather understand the code before complaining about it.

If you copy and paste though, remember the license.

MikeVaz commented 5 years ago

Hey Andrea. I wasn't complaining. It feels like you considering every opened case as an personal insult. If you'd show me how to use your library in the case I mentioned above that would be great... :peace_symbol:

WebReflection commented 5 years ago

@MikeVaz you haven't asked anything and your code is not a question or something that has much to do with this library. I've asked you what is it that makes wicked elements hard to work with components and received no answer, just a "we'll copy and paste then" answer.

Can you explain what are you trying to do and why do you have any issue?

Can you also explain to me why are you even using custom elements at all with wicked elements , when custom elements provide already connected and disconnected callbacks, together with attributeChanged and you can add a handleEvent to any object, class, or prototype you want?

When I'll understand what's your issue, I can answer properly. If you go directly too the "we gonna copy and paste", how do you expect me to answer?

MikeVaz commented 5 years ago

You answered the questions "Why" yourself "Can you also explain to me why are you even using custom elements at all with wicked elements , when custom elements provide already connected and disconnected callbacks, together with attributeChanged and you can add a handleEvent to any object, class, or prototype you want?"

This is one of the reasons why. Custom elements already have some features of wicked elements. There are several other reasons like #9, and we can't create elements in memory and call methods on instances keeping the context.

But I suggested to expose handleEvent pattern and bootstrap method from the library since those can be used in wicked elements and in custom elements.

WebReflection commented 5 years ago

But I suggested to expose handleEvent pattern

that's just a method !!! anyone can have it since year 2000 https://medium.com/@WebReflection/dom-handleevent-a-cross-platform-standard-since-year-2000-5bf17287fd38

what do you want me to extract, exactly?

And about the bootstrap, it makes no sense outside this library.

Once again, what are you trying to do?

Also the #9 makes no sense because you don't have those issues with Custom Elements.

This is not Custom Elements, this is something different.

I guess I should write that on top of the README 🤔

MikeVaz commented 5 years ago

Bootstrap makes sense if you want to delegate several events using this pattern.

From my code sample above. We use this pattern from the library in a custom element

var handleEvent = {
  handleEvent(event) {
    var type = 'on' + event.type;
    if (type in this)
      this[type](event);
  }
}

Now this custom element can become a delegate for many different events from other elements. Let's say I want to react on URL changes.

// I would delegate it to my custom element
window.addEventListener('pushstate', this);
window.addEventListener('hashchange', this);
....

Now this is where bootstrap can be handy since I just need to list all events I want to listen to and elements to delegate from.

WebReflection commented 5 years ago

I don't understand what has a DOM element to do with a window listener, so unless you write down a real world use case of what you are trying to achieve (even pseudo code with the changes you want me to imagine, 'cause I don't get what you need), maybe I can suggest a different approach.

Until that example happens, I have the feeling you didn't grasp what is this library about. pushstate and global listeners for a library based in CSS gives me that hint.

MikeVaz commented 5 years ago

Modifying my example to showcase why it can be handy. Now our component can react to window hash changes and to clicks.

// Composition just to make example work
function mixin(cls, obj) {
  class cls1 extends cls {};
  Object.assign(cls1.prototype, obj);
  return cls1; 
}

// Could be a reusable behavior from the wicked elements library
var handleEvent = {
  handleEvent(event) {
    var type = 'on' + event.type;
    if (type in this)
      this[type](event);
  }
}

// Define a component extending HTMLElement and mixing with handleEvent behavior
class MyComponent extends mixin(HTMLElement, handleEvent) {
  onclick(event) {
    this.innerHTML = "click";
  }
  onhashchange(event) {
    this.innerHTML = "hashchanged";
  }
  constructor() {
    super();
    this.addEventListener('click', this);
    window.addEventListener('hashchange', this);    
  }  
}

customElements.define('my-component',MyComponent);

document.body.innerHTML += '<my-component>Click me</my-component>';
MikeVaz commented 5 years ago

Now adding bootstrap to the picture to show case why it could be useful.

        // Composition just to make example work
        function mixin(cls, obj) {
            class cls1 extends cls { };
            Object.assign(cls1.prototype, obj);
            return cls1;
        }

        // Could be a reusable behavior from the wicked elements library
        var getOwnPropertyNames = Object.getOwnPropertyNames;
        var getPrototypeOf = Object.getPrototypeOf;
        var root = Object.prototype;
        var handleEvent = {
            handleEvent(event) {
                var type = 'on' + event.type;
                if (type in this && typeof this[type] == 'function') // Tweak here
                    this[type](event);
            },
            bootstrap(handler, proto, event, el, method) {
                var invoke = false;
                while (proto !== root) {
                    var keys = getOwnPropertyNames(proto);
                    var i = 0;
                    var length = keys.length;
                    while (i < length) {
                        var key = keys[i++];
                        if (key.slice(0, 2) === 'on' && typeof handler[key] == 'function') { // Tweak here
                            el.addEventListener(key.slice(2), handler, false);
                            if (key === method && !invoke)
                                invoke = !invoke;
                        }
                    }
                    proto = getPrototypeOf(proto);
                }
                // Comment the rest.
                /*
                handler.init(event);
                if (invoke)
                handler.handleEvent(event);*/
            }

        }

        // Define a component extending HTMLElement and mixing with handleEvent behavior
        class MyComponent extends mixin(HTMLElement, handleEvent) {
            onmousedown(event) {
                this.innerHTML += " mousedown";
            }
            onmouseup(event) {
                this.innerHTML += " mouseup";
            }
            onclick(event) {
                this.innerHTML += " click";
            }
            onhashchange(event) {
                this.innerHTML += " hashchanged";
            }

            constructor() {
                super();

                // Handle everything we have methods for (mousedown, mouseup, click)
                this.bootstrap(this,this,null,this); 

                // Handle hashchange
                window.addEventListener('hashchange', this);
            }
        }

        customElements.define('my-component', MyComponent);

        document.body.innerHTML += '<my-component>Click me</my-component>';
WebReflection commented 5 years ago

so, if I understand correctly, you want this library to export something that won't use this library but it's part of it ... and all to have a typeof guard ?

if that would happen it's not here, you can create your own pattern a part and maybe wicked elements will use such pattern to also bootstrap and setup its own methods.

Feel free to copy and paste part of this logic, but remember the license/credits to the library.

Not interested right now in favoring 3rd parts solutions here so I'll stop here about this topic.