From f433afd279b7533fe6d04dc2cf45823088137daf Mon Sep 17 00:00:00 2001 From: KIP Date: Sun, 8 Apr 2018 01:32:03 -0500 Subject: [PATCH 1/5] Update index.html removed unfinished sentence. Added `Creating your own Extension` Heading did not finish content. --- index.html | 954 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 839 insertions(+), 115 deletions(-) diff --git a/index.html b/index.html index 4543c5e..8b2b21f 100644 --- a/index.html +++ b/index.html @@ -1,725 +1,1449 @@ + + + + + + + + X-Tag - Web Components Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +

X-Tag is a + lightweight, power-packed + Web Components library + that gets you there fast, and stays in its own lane.

+ +
+ +
    +
  • + + + + +

    Standard

    +
    Built on Web Components APIs
    +
  • + + + +

    Efficient

    +
    Powerful features in 3k min/gzip
    +
  • + + + +

    Pluggable

    +
    Plays nice with other libraries
    +
  • +
+ +
+ +

What is X-Tag?

+ +

Originally developed at Mozilla, now supported by devs at Microsoft, X-Tag is an open source JavaScript library that wraps the W3C standard Web Components family of APIs + to provide a compact, feature-rich interface for component development. While X-Tag makes it easy to leverage all the Web Components APIs + (Custom Elements, Shadow DOM, Templates, and HTML Imports), it only requires Custom Elements API support to operate. + In the absence of the native Custom Elements APIs, X-Tag uses the same polyfill + Google's Polymer framework relies on. You can view our package options in the Builds section

+ + +
+ + + +

+
 xtag.create('x-clock', class extends XTagElement {
+
   connectedCallback () {
+
     this.start();
+
   }
+
   start (){
+
     this.update();
+
     this._interval = setInterval(() => this.update(), 1000);
+
   }
+
   stop (){
+
     this._interval = clearInterval(this._data.interval);
+
   }
+
   update (){
+
     this.textContent = new Date().toLocaleTimeString();
+
   }
+
   'tap::event' (){
+
     if (this._interval) this.stop();
+
     else this.start();
+
   }
+
 });
+
 
+ +
+ +

Browser Support

+
+
+ + + + Edge +
+ + + + Chrome (desktop and mobile) +
+ + + + Firefox (desktop and mobile) +
+ + + + Safari (Mac and iOS) +
+ + + + Opera (desktop and mobile) +
+ + + + Android Browser (OS version 5+) +
+
+ +
+ +
+ +
+ +

Install from NPM:

+

npm install x-tag

+ +
+ +
+ +
+

Download the build that works best for you:

+
+ + + + +

X-Tag
+
Polyfills

+
X-Tag + Custom Elements polyfill
6k min/gzip
+
+ + +

Just X-Tag

No Polyfills

+
Run it raw on native APIs
3k min/gzip
+
+
+
+ +
+ + +

Getting Started

+ +

+ The most important method in the X-Tag library is xtag.create(). The create function on the X-Tag object is what you'll use - to create new custom element definitions, which can include things like lifecycle callbacks, attribute-linked getters/setters (accessors), + + to create new custom element definitions that can be enhanced by using the built in lifecycle callbacks, attribute-linked getters/setters (accessors), rendering features, cached templating, + and event listeners. Here's what defining a simple custom element looks like with X-Tag: +

+ +

+
 const Frank = xtag.create('x-frankenstein', class extends XTagElement {
+
   constructor (){
+
     alert("It's moving...it's alive!");
+
   }
+
 });
+
 
+ +

+ Notice the class definition extends the class XTagElement. If you are not extending from a previously defined Custom Element, + you must always extend from the XTagElement class for X-Tag to properly construct your Custom Element definition. The tag name argument (and subsequent automatic + element registration) is optional - here's what it looks like without it, and how to register your element with a tag name separately: +

+ +

+
 const Frank = xtag.create(class extends XTagElement {
+
   constructor (){
+
     alert("Muhahaha!");
+
   }
+
 });
 
-xtag.register('x-frankenstein', Frank);
+
+
+xtag.register('x-frankenstein', Frank);
+
 

-

A Word on Extensions and Pseudos

+ + + + + + +

Gettin' Jedi with Pseudos and Extensions

+ +

+ + Two advanced features of X-Tag you need to be aware of in detail are the pseudos and extensions API. + + Here are examples:

+ + + +

Create your own Pseudo:

+ + + +

+ + Once you create a pseudo and add it to the main xtag.pseudos object, as shown below, + + you can then use it on any key of your custom element definition objects that has a + + function as its value. + +

+ + + +

+
+xtag.pseudos.foo = {
+
+  onParse: function(ctor, property, args, fn){
+    /*
+      Description:
+
+      onParse is called when the pseudos specified in a declaration are being 
+
+      compiled and wrapped around the function they are being applied to.
+
+      Parameters:
+
+      ctor: the Custom Element Class definition
+
+      property: property the pseudo is being applied to (ex: ping:foo, property = ping)
+
+      args: arguments from the pseudo definition (ex: prop:foo(1, 2), args = [1, 2])
+
+      fn: the function the pseudo is wrapping in the pseudo chain
+    */
+
+  },
+
+  onInvoke: function(node, obj){
+
+    /*
+      Description:
+
+      Invoke is called any time the pseudo-wrapped function is called. This is where 
+
+      you perform whatever action you desire on the node or object the pseudo targets.
+
+      Parameters:
+
+      node: the element
+
+      obj: object composed of these properties: { fn: fn, args: args, detail: detail } 
+
+    */
+
+  }
+
+};
+
+xtag.create("x-foo", class extends XTagElement{
+
+  "godzilla:foo"(){/* TODO APPLICATION LOGIC */}
+
+});
+
+

+ + + +

To an Extended Voyage

+ +

+ + X-Tag uses the standard Custom Elements mechanism for inheritance: ES6 class extension. The return value of the create method is an X-Tag compiled ES6 class, which + + can be itself extended either via generic ES6 class declaration, or by again passing it into create, if you wanted to add additional features to your new extended class + + using X-Tag APIs. + +

+ + + +

+
+const Foo = xtag.create('x-foo', class extends XTagElement {
+
+  set 'foo::attr' (){ /* Handle foo attribute change */ }
+
+});
+
+
+
+Bar extends Foo {
+
+  bar (){ }
+
+}
+
+
+
+const Zaz = xtag.create('x-zaz', class extends Bar {
+
+  'click::event' (){ /* do something when clicked */ }
+
+});
+
+
+ + + +

+ In the next sections you're going to hear about a few features that are delivered via two different types of modular extensibility systems the + library offers for imbuing your elements with advanced functionality. These two systems are called extensions and pseudos. + Both are different in their intent, scope of effect, range of capabilities. You will use them frequently in your Custom Element class definition + blocks, here's what they look like: +

+ +

+
 xtag.create('x-foo', class extends XTagElement {
+
   'alert::foo' (){
 
+
+
   }
+
   'count:bar' (){
 
+
+
   }
-  'send::attr:bar:zaz' (){
+
+  'send::foo:bar:zaz' (){
+
     
+
   }
+
 });
+
 
+ +

+ Notice how the alert method has a ::foo attached to it - this is an extension. Extensions are little modules you can created that are called + into service by tagging a property with :: + the name of the extension. Extensions are a sizable API of their own that let's you manipulate + far more than just the property they are tagged to. You can only use one extension per property. +

+ +

+ The other API for adding custom functionality to components is called pseudos, which are seen above in the example property count:bar. When a pseudo is tagged to a property, the pseudo's + own function wraps the target function so that the pseudo is executed first, then the target, which receives its return value. You can chain pseudos, and - they are compiled from left to right so that they left most pseudo function wrapper fires first, passing each function's return value down to the next, until + + they are compiled from left to right so that the left most pseudo function wrapper fires first, passing each function's return value down to the next, until + finally the original target function is executed. You can see what this looks like in the above example property send::foo:bar:zaz. +

+ +

+ There are separate guides for extensions and pseudos that talk about how to create and use your own, but for now just be aware that they are one of + the primary means the X-Tag library delivers its own features. +

+ + +

Create your own Extension:

+ + + +

Say Hello to Custom Attribute Accessors

+ +

+ Accessors are custom attributes linking to a corresponding pair of setters/getters, and X-Tag has a built-in extension that makes adding accessors to + + your custom element definition stupid simple. To use this extension, add an ::attr modifier to one of your class definition properties. + + This tells X-Tag to wire up a getter/setter to an HTML attribute of the same name. When attributes are linked to a getter/setter their gets, sets, and + + state changes will be synced without having to write any additional code. + +

+ +

+ In addition to binding attributes the ::attr extension also allow you to declare a specific data type. +

+ + +

+
+xtag.create('x-foo', class extends XTagElement {
+
+  set 'maxVolume::attr' (value){
+
+    // X-Tag automatically maps camel cased getter/setter names to their
+
+    // dashed attribute equivalents. In this example, the `maxVolume` 
+
+    // getter/setter pair maps to the `max-volume` attribute.
+
+  }
+
+});
+
+
+
+xtag.create('x-bar', class extends XTagElement {
+
+  '::template(true)' (){ return '<input />' }
+
+  set 'disabled::attr(boolean)' (value){
+
+    // The ::attr extended property links node.disabled to gets/sets of 
+
+    // the disabled="" attribute. Because it is declared as a boolean, 
+
+    // all values passed into its getter/setter will be a Boolean.
+
+    this.firstElementChild.disabled = value;
+
+  }
+
+});
+
+
+ + +
+ + +

Content is King

+ +

+ Many of the components you create will require child elements for structure and presentation. X-Tag includes a content templating + extension that makes this quick and easy. Simply add a ::template function to your component definition - and return a string or ES6 Template String. In the example below, notice the true parameter being passed to the extension. + + and return a string or ES6 Template String. In the example below, notice the true parameter being passed to the extension. + This tells the template extension to render the content immediately when an instance is created. If you don't want a template to render + automatically like this, don't pass anything to it. +

+

+ + The XTagElement's `render()` method is the work horse of the `template` `extension`and makes it possible to create feature rich application + + parts. For more information regarding this check out the section. + +

+ + +

+
 xtag.create('x-frankenstein', class extends XTagElement {
+
   '::template(true)' (){
+
     return `<h2>I am Frankenstein</h2>
+
             <span>I was created by a mad scientist</span>`
+
   }
+
 });
+
 
+ +

Manual Rendering of Templates

+ +

+ If you elect not to have your template automatically rendered when your component instances are created, you'll need to manually trigger render. +

+ +

+
 const Frank = xtag.create('x-frankenstein', class extends XTagElement {
+
   name (){ return 'Frankenstein'; }
+
   '::template' (){
+
     return `<h2>I am ${this.name()}</h2>
+
             <span>I was created by a mad scientist</span>`
-  }
-});
+
+  }});
+
+
 
 const FrankNode = new Frank();
+
 FrankNode.render();
+
 
+ +

Multiple Templates

+ +

+ The template extension can be used multiple times within the same class definition block, which allows you to specify different templates + for use in the same component. The templates are cached and reference based on the property name you put in front of the ::template extension + token. To render your templates, simply pass the name of the template you want to use to the render function, as in the following example: +

+ +

+
 const Frank = xtag.create('x-frankenstein', class extends XTagElement {
+
   'foo::template(true)' (){
+
     return `<h2>My name is Frankenstein</h2>
+
             <span>I work for a mad scientist</span>`
+
   }
+
   'bar::template' (){
+
     return `<h2>My friends call me Frank</h2>
+
             <span>I work for a mad scientist</span>`
+
   }
+
 });
 
+
+
 const FrankNode = new Frank();
+
 // Because the foo template indicated it was to be automatically rendered, its content is already present in your element instance.
+
 FrankNode.render('bar');
+
 // Calling the render function with the bar template name swaps out the current foo template content with the bar content.
+
 
-
-

Say Hello to Custom Attribute Accessors

-

- Accessors are custom attributes linking to a corresponding pair of setters/getters, and X-Tag has a built-in extension that makes adding accessors to - your custom element definition stupid simple. To use this extension, add an ::attr modifier to one of your class definition properties. - This tells X-Tag to wire up a getter/setter to an HTML attribute of the same name. When attributes are linked to a getter/setter their gets, sets, and - state changes will be synced without having to write any additional code. -

+

The Elements Render

+ +

+ + The XTagElement's render() method is the work horse of the template extension. It get's attached to every X-Tag element that you create and can be reused for your own extensions and pseudos. Below is an example of using an event to initiate a mode accessor. + +

+ -

- You can also tell the accessor extension that type of accessor you are creating, and it will help by sanitizing values and modifying the gets/sets to - match the behavior of the type you declare. I


-xtag.create('x-foo', class extends XTagElement {
-  set 'maxVolume::attr' (value){
-    // X-Tag automatically maps camel cased getter/setter names to their
-    // dashed attribute equivalents. In this example, the `maxVolume` 
-    // getter/setter pair maps to the `max-volume` attribute.
+
+var _rendered = xtag.create( "x-mode", class extends XTagElement {
+
+  set 'mode::attr'(_mode) {
+
+    this.render(_mode);
+
+    return _mode;
+
   }
-});
 
-xtag.create('x-bar', class extends XTagElement {
-  '::template(true)' (){ return '<input />' }
-  set 'disabled::attr(boolean)' (value){
-    // The ::attr extended property links node.disabled to gets/sets of 
-    // the disabled="" attribute. Because it is declared as a boolean, 
-    // all values passed into its getter/setter will be a Boolean.
-    this.firstElementChild.disabled = value;
+  get 'mode::attr'(){ 
+
+    return this.getAttribute("mode"); 
+
+  }
+
+  'myModeSnippet::template'() {
+
+    return "
My creation has come to be,

Rendered.

"; + } -}); -
+ + 'click::event'(e){ + + e.target.mode = e.target.mode; + + } + +} ); + +
+ +

The DL on Events

+

+ X-Tag provides a powerful event system you'll use often in developing your components. + We'll cover the basics here, and leave the more advanced features for a special tutorial dedicated to the topic. -

-

- To add event listeners to your component (either native or custom events), you'll be using the event extension. To do so, add a property to your - Custom Element definition that matches the name of the event you want to listen for, plus the ::event extension flag. When your class definition - is processed by X-Tag's create method, the event extension will remove the property, add a listener using the supplied property name with the - function you supplied as the handler.

-

-xtag.register('x-foo', {
-  'click::event': function(){
-    // attaches a click listener that calls this function when
-    // the user clicks an element inside the custom element
-  },
-  'focus::event': function(){
-    // attaches a focus listener that calls this function when
-    // something inside your custom element is focused.
-  }
-});
-
-
- -

Gettin' Jedi with Pseudos

- One advanced feature of X-Tag you should be aware of right off the bat is the delegate pseudo. - X-Tag features a function modifier system called pseudos which allows you to seamlessly wrap - functions anywhere in your custom element defintion object (lifecycle callbacks, methods, accessors, and events) - to extend their functionality. The delegate pseudo enables you to quickly add event delegation - (filtering of event targets based on CSS expressions) to any event function you add to your component. Here's an example:

-

-xtag.register('x-foo', {
-  content: '<input/>',
-  events: {
-    'tap:delegate(input)': function(){
-      // Perform an action only when the user taps on an
-      // <input/> element within your component.
-    }
-  }
-});
-
+ To add event listeners to your component (either native or custom events), you'll be using the event extension. To do so, add a property to your -

Create your own Pseudo:

+ Custom Element definition that matches the name of the event you want to listen for, plus the ::event extension flag. When your class definition + + is processed by X-Tag's create method, the event extension will remove the property, add a listener using the supplied property name with the + + function you supplied as the handler. -

- Once you create a pseudo and add it to the main xtag.pseudos object, as show below, - you can then use it on any key of your custom element definition objects that has a - function as its value.

+ +

-xtag.pseudos.foo = {
-  onParse: function(ctor, property, args, fn){
-    /*
-      Parse is called when the pseudos specified in a declaration are being 
-      compiled and wrapped around the function they are being applied to.
 
+xtag.register('x-foo', {
+
+  'click::event': function(){
+
+    // attaches a click listener that calls this function when
+
+    // the user clicks an element inside the custom element
 
-      ctor: the Custom Element Class definition
-      property: property the pseudo is being applied to (ex: ping:foo, property = ping)
-      args: arguments from the pseudo definition (ex: prop:foo(1, 2), args = [1, 2])
-      fn: the function the pseudo is wrapping in the pseud chain
-    */
   },
-  onInvoke: function(node, obj){
-    /*
-      Invoke is called any time the pseudo-wrapped function is called. This is where 
-      you perform whatever action you desire on the node or object the pseudo targets.
 
-      node: the element
-      obj: object composed of these properties: { fn: fn, args: args, detail: detail } 
-    */
-  }
-};
-
+ 'focus::event': function(){ -
+ // attaches a focus listener that calls this function when -

Inheritance

+ // something inside your custom element is focused. -

- X-Tag uses the standard Custom Elements mechanism for inheritance: ES6 class extension. The return value of the create method is an X-Tag compiled ES6 class, which - can be itself extended either via generic ES6 class declaration, or by again passing it into create, if you wanted to add additional features to your new extended class - using X-Tag APIs. -

+ } -

-const Foo = xtag.create('x-foo', class extends XTagElement {
-  set 'foo::attr' (){ /* Handle foo attribute change */ }
 });
 
-Bar extends Foo {
-  bar (){ }
-}
+


-const Zaz = xtag.create('x-zaz', class extends Bar { - 'click::event' (){ /* do something when clicked */ } -}); - -

API Reference

+ +

xtag.create(TAG_NAME, DEFINITION)

+ +

+ Create and (optionally) register a Custom Element definition for use as a new tag in HTML markup or via DOM APIS. +

+ + + + + + + + + + + + + + + + + +
ArgumentTypeDescription
TAG_NAME
(optional)
String + The tag name you want to use when using your Custom Element (must contain a dash). When + this argument is passed, the Custom Element definition is automatically added to the document's Custom Element registry. +
DEFINITIONClassThe class definition block for your Custom Element
+ +

+
 const Frank = xtag.create('x-frankenstein', class extends XTagElement {
+
   constructor (){
+
     alert("It's moving...it's alive!");
+
   }
+
 });
+
 
+ +
+ +

xtag.addEvent(ELEMENT, TYPE, HANDLER, CAPTURE)

+ +

+ Add a native, custom, or X-Tag library event listener to an element. The TYPE field also + accepts pseudo chains for even more powerful event handling. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
ArgumentTypeDescription
ELEMENTDOM element reference + The element you would like to attach an event listener to. +
TYPEString + The event name, with any event pseudos you may want to chain. +
HANDLERFunction + The event handler you want called when the event occurs. +
CAPTUREFunction + Boolean argument you can pass if you want the event to use capturing vs bubbling. +
+ +

+
 xtag.addEvent(myElement, 'tap:delegate(img)', function(event){
+
   alert('An image element within myElement was just tapped');
+
 });
+
 
+ +
+ +

xtag.addEvents(ELEMENT, OBJECT)

+ +

+ Add multiple native, custom, or X-Tag library event listeners to an element using one function. + Pseudo chains are avaliable for use in your event object keys. +

+ + + + + + + + + + + + + + + + + +
ArgumentTypeDescription
ELEMENTDOM element reference + The element you would like to attach the event listeners to. +
OBJECTObject + An object composed of multiple events - keys are event names, and values are the event handlers. +
+ +

+
 xtag.addEvents(myElement, {
+
   'tap': function(event){
+
     alert('myElement was just tapped');
+
   },
+
   'keypress:keypass(13)': function(event){
+
     alert('The enter key was pressed, all other keys are blocked');
+
   }
+
 });
+
 
+ +

xtag.fireEvent(ELEMENT, NAME, OPTIONS)

+ +

+ Add a native, custom, or X-Tag library event listener to an element. The TYPE field also + accepts pseudo chains for even more powerful event handling. +

+ + + + + + + + + + + + + + + + + + + + + + +
ArgumentTypeDescription
ELEMENTDOM element reference + The element you would like to attach an event listener to. +
NAMEString + The event name you wish to fire on the target element. +
OPTIONSObject + The event options you want to use in firing your event. These include: +
    +
  • detail allows passage of custom data via the detail property of the event
  • +
  • bubbles specify whether the event bubbles - defaults to true
  • +
  • cancelable specify whether the event is cancelable - defaults to true
  • +
+
+ +

+
 xtag.fireEvent(myElement, 'show', {
+
   detail: {
+
     x: 123,
+
     y: 456
+
   }
+
 });
+
 
+ +
+ +
+ + + + + + + + + + + - \ No newline at end of file + + From 8a8cf6cd708d65efe3af2c45a93a83f686fd0951 Mon Sep 17 00:00:00 2001 From: KIP Date: Sun, 8 Apr 2018 01:40:29 -0500 Subject: [PATCH 2/5] patch-2 added a line for `creating an extension` moved `creating an extension` up a section --- index.html | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/index.html b/index.html index 8b2b21f..f1da2c4 100644 --- a/index.html +++ b/index.html @@ -608,10 +608,16 @@

Create your own Pseudo:

-

To an Extended Voyage

+

Create your own Extension

+ Creating an extension and using them can be simple, but you can use them and create complex relationships and bindings using this simple method + to organize data and display it. +

+ +

To an Extended Voyage

+

X-Tag uses the standard Custom Elements mechanism for inheritance: ES6 class extension. The return value of the create method is an X-Tag compiled ES6 class, which can be itself extended either via generic ES6 class declaration, or by again passing it into create, if you wanted to add additional features to your new extended class @@ -728,10 +734,6 @@

To an Extended Voyage

-

Create your own Extension:

- - -

Say Hello to Custom Attribute Accessors

From 5eb57cd7d209dcc3db70028568720dfbc0c4d908 Mon Sep 17 00:00:00 2001 From: KIP Date: Sun, 8 Apr 2018 14:52:39 -0500 Subject: [PATCH 3/5] Example for extensions additional: changed two `h4` headings to `h3` headings => To an Extended Voyage and Say Hello to Custom Attribute Accessors. I was going to put an additional example that doesn't use the `type` and also an example with an event to show the versatility of the X-Tag. Let me know what issues their are --- index.html | 114 ++++++++++++++++++++++++++--------------------------- 1 file changed, 56 insertions(+), 58 deletions(-) diff --git a/index.html b/index.html index f1da2c4..c6b4e3b 100644 --- a/index.html +++ b/index.html @@ -186,23 +186,16 @@

X-Tag is a that gets you there fast, and stays in its own lane.

- -
- -