Coder Social home page Coder Social logo

berkcanerken / be-enhanced Goto Github PK

View Code? Open in Web Editor NEW

This project forked from bahrus/be-enhanced

0.0 0.0 0.0 269 KB

Provides a base class that enables "casting spells" on DOM elements by enhancing server-rendered DOM elements based on cross-cutting custom attributes. Can also perform "non-verbal" spells programmatically during template instantiation (for example).

License: MIT License

JavaScript 47.46% TypeScript 52.54%

be-enhanced's Introduction

be-enhanced [WIP]

How big is this package in your project? NPM version

be-enhanced provides a base class that enables "casting spells", or enhancing server-rendered DOM elements based on cross-cutting custom attributes. These base classes can also be used during template instantiation for a more optimal repeated web component scenario.

be-enhanced, which focuses on adding custom properties to an element, and be-hive, which focuses on attaching the custom property based on the matching custom attribute, together form a simplified userland implementation of this proposal. Whereas that proposal builds on this really nice idea and allows for a mapping from one "behavior" or "enhancement" to any number of custom attributes (including none), be-enhanced only supports a one-to-one mapping, and doesn't support observing changes to the values of the attributes (as I prefer working through the enhancement property gateway).

be-enhanced provides a much more "conservative" alternative approach to enhancing existing DOM elements, in place of the controversial "is"-based customized built-in element standard-ish. There are, however, a small number of use cases where the is-based built-in approach may be the preferred one.

In contrast to the "is" approach, we can apply multiple behaviors / decorators to the same element:

#shadow-root (open)
<black-eyed-peas 
    be-on-the-next-level=11
    be-rocking-over-that-bass-tremble
    be-chilling-with-my-motherfuckin-crew
></black-eyed-peas>

which seems more readable than:

<is-on-the-next-level level=11>
    <is-rocking-over-that-base-tremble>
        <is-chilling-with-my-motherfunckin-crew>
            <black-eyed-peas></black-eyed-peas>
        </is-chilling-with-my-motherfuckin-crew>
    </is-rocking-over-that-base-tremble>
</is-on-the-next-level>

Not to mention concerns about performance. And then there's this.

Priors

be-enhanced's goals are quite similar to what is achieved via things that go by many names.

We prefer (progressive) "enhancement" as the term, but "decorator", "[cross-cutting] custom attribute", "directive", "behavior" are also acceptable terms.

Differences to these solutions (perhaps):

  1. This can be used independently of any framework (web component based).
  2. Each decorator can be imported independently of others via an ES6 module.
  3. Definition is class-based, but with functional reactive ways of organizing the code ("FROOP")
  4. Applies exclusively within Shadow DOM realms.
  5. Reactive properties are managed declaratively via JSON syntax.
  6. Namespace collisions easily avoidable within each shadow DOM realm.
  7. Use of namespaced properties allows multiple vendors to apply different enhancements simultaneously.
  8. be-enhanced provides "isomorphic" support for using the same declarative syntax while transforming templates during template instantiation, as well as while the DOM is sitting in the live DOM tree. But the critical feature is that if the library is not yet loaded during template instantiation, nuk ka problem, the live DOM decorator can apply the logic progressively when the library is loaded. Meaning we can punt during template instantiation, so that render blocking is avoided. And if the library is loaded prior to template instantiation, it can still be supplemented by the live DOM decorator, but the initial work performed during the template instantiation can be skipped by the live DOM decorator.

Prior to that, there was the heretical htc behaviors.

Examples of constructing a be-enhanced progressive enhancement decorator:

Enhancement Purpose Code
be-adoptive Adopt styles from parent shadow realm code
be-a-beacon Announce arrival of (last) element in HTML Stream code
be-based Adjust URLs from a base URL code
be-bound Provide two-way binding code
be-buttoned-up Make a button link to button menu in popover code
be-channeling Channel events to the host element. code
be-clonable Make DOM element be clonable code
be-committed Trigger a button click on keyboard "enter" code
be-computed Compute values from other HTML signals via local script tags. code
be-counted Track and share how many times button has been clicked. code
be-definitive Define web component from existing DOM in tree. code
be-delible Make DOM element be deletable code
be-derived Derive state from server-rendered HTML code
be-detail-oriented Make the fieldset expandable. code
be-dispatching Dispatch event with specified name. code
be-elevating Elevate local property value to upstream element. code
be-entrusting Derive initial value from server streamed semantic HTML. code
be-exportable Allow script tag to export itself as a module code
be-fetching Fetch resource based on url property code
be-formidable Enhance the form's validation abilities. code
be-functional Connect script to DOM elements. code
be-importing Import Static, Declarative HTML Web Components with Streaming HTML code
be-inclusive Include content from nearby templates code
be-intl Format numbers using intl.NumberFormat. code
be-invoking Invoke method on upstream peer element or the host. code
be-it Forward props to adjacent element. code
be-lazy Load template when it scrolls into view code
be-linked Connect HTML (web) components together with readabe syntax code
be-literate Enhance the input element so it can read local files code
be-memed Cache templates contained within templates code
be-observant One-way-bind from the host or a peer element. code
be-promising Run enhancements in a predictable order code
be-prop-slotting Transfer values from light children to host. code
be-propagating Publish property changes to adorned element. code
be-repeated Repeat section of HTML code
be-scoped Create an EventTarget associated with the adorned element that can hold scoped state. code
be-searching Make a DOM element searchable code
be-sharing Share values from the adorned element to peer elements. code
be-switched Lazy loads content when conditions are met. code
be-typed Allow the user to customize input element during run time. code
be-value-added Add a value property used for formatting. code
be-valued Reflect value of input to the value attribute on input event. code
be-written Stream a url to a target DOM element. code

The be-enhancement api

be-enhancement commits the cardinal sin of attaching a custom property gateway, "beEnhanced" on all Elements. Being that the platform has shown little to no interest in providing support for progressive enhancement over many decades when such solutions have proven useful, we should feel no guilt whatsoever.

Having this property gateway is a life-saver as far as performance and providing an easy way of integrating enhancements into (some) frameworks.

To set a value on a namespaced property (e.g. via a framework), do the following:

await customElements.whenDefined('be-enhanced');
const base = myElement.beEnhanced.by.aButterBeerCounter;
Object.assign(base, {count: 7});

This should work just fine even if the enhancement a-butter-beer-counter hasn't loaded yet. The enhancement will absorb the settings the moment it becomes attached to the element it is enhancing.

Server-rendered HTML vs Template Instantiated HTML

If the HTML we are working with is rendered by the server, the most effective way of activating the custom enhancement is via the associated attribute:

<button be-counted>Count me</button>

However, activating enhancements via attributes is not ideal when using client side api's to build the API, such as during template instantiation.

As we stated so very long ago, the way to do this most effectively programmatically is:

import('be-counted/be-counted.js');
await customElements.whenDefined('be-enhanced');
const base = myElement.beEnhanced.by.beCounted;
Object.assign(base, {value: 7});

In the example above, we are importing the dependency asynchronously using the dynamic import. This means that depending on the timing the hydration of the enhancement may be done during template instantiation (for example), or after the element being enhanced has been added to the live DOM tree.

Using dynamic import as shown above has the benefit that the dependency will not cause the template instantiation to be render blocked.

Event Notifications

Be-enhancement element decorators/behaviors typically don't, by default, emit events that get bubbled up the DOM tree.

To subscribe to an event:

const myEnhancement = await myElement.beEnhanced.whenDefined('my-enhancement');
myEnhancement.addEventListener('resolved', e => {

})

Alternate attribute names

To be HTML5 compliant, use data-[enh-by-name-of-enhancement]. If enhancing a custom element, chances are significant that the custom element may support an attribute that matches your (short name). To make the chances of this approach nil, the companion to be-enhanced mentioned above, be-hive, only recognizes attributes that start with enh-by- or data-enh-by when attached to a custom element.

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.