Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Componentize all the things!

JSIST
September 28, 2014

Componentize all the things!

JSIST 2014
By : Pascal Precht
http://jsist.org

JSIST

September 28, 2014
Tweet

More Decks by JSIST

Other Decks in Programming

Transcript

  1. Four technologies HTML Templates - Inert chunks of clonable DOM

    Shadow DOM - Style & DOM encapsulation Custom Elements - Define and use new DOM elements HTML Imports - Include/Reuse other HTML documents
  2. Four technologies HTML Templates - Inert chunks of clonable DOM

    Shadow DOM - Style & DOM encapsulation Custom Elements - Define and use new DOM elements HTML Imports - Include/Reuse other HTML documents
  3. Offscreen DOM < d i v i d = "

    m y t e m p l a t e " h i d d e n > < i m g s r c = " l o g o . p n g " > < d i v c l a s s = " c o m m e n t " > < / d i v > < / d i v > We can clone the DOM Nothing is rendered Not inert, network request is made for the image Styling is painful, all styles must be prefixed with # m y t e m p l a t e
  4. Overloading script < s c r i p t i

    d = " m y t e m p l a t e " t y p e = " t e x t / x - h a n d l e b a r s - t e m p l a t e " > < / s c r i p t > < i m g s r c = " l o g o . p n g " > < d i v c l a s s = " c o m m e n t " > < / d i v > Nothing rendered, < s c r i p t > is d i s p l a y : n o n e ; by default It's inert (yay!), JS isn't parsed because of its type Security issues, run-time string of user-supplied data can easily lead to XSS vulnerabilities
  5. HTML Templates to the rescue! < t e m p

    l a t e i d = " m y t e m p l a t e " > < i m g s r c = " p a t h / t o / s o u r c e . p n g " a l t = " g r e a t i m a g e " > < d i v c l a s s = " c o m m e n t " > < / d i v > < / t e m p l a t e > Clonable DOM Parsed, not rendered Stylesheets/Images aren't loaded, media isn't played, scripts don't run
  6. Activating a template You can activate templates by cloning their

    c o n t e n t document fragment. v a r t = d o c u m e n t . q u e r y S e l e c t o r ( ' # m y t e m p l a t e ' ) ; t . c o n t e n t . q u e r y S e l e c t o r ( ' i m g ' ) . s r c = ' l o g o . p n g ' ; d o c u m e n t . b o d y . a p p e n d C h i l d ( t . c o n t e n t . c l o n e N o d e ( t r u e ) ) ; Demo
  7. No prerendering Templates can't be "precompiled" like you can with

    libs like handlebars Assets, images, JS processing can't be preloaded
  8. Nested templates behaviour Activating outer template will not activate inner

    templates. < t e m p l a t e > < u l > < t e m p l a t e > < l i > S t u f f < / l i > < / t e m p l a t e > < / u l > < / t e m p l a t e >
  9. Four technologies HTML Templates - Inert chunks of clonable DOM

    Shadow DOM - Style & DOM encapsulation Custom Elements - Define and use new DOM elements HTML Imports - Include/Reuse other HTML documents
  10. Four technologies Shadow DOM - Style & DOM encapsulation HTML

    Templates - Inert chunks of clonable DOM Custom Elements - Define and use new DOM elements HTML Imports - Include/Reuse other HTML documents
  11. The web platform offered only one built-in mechanism to isolate

    one chunk of code to another - < i f r a m e >
  12. < i n p u t t y p e

    = " t i m e " > - - : - -
  13. < d e t a i l s > C

    o n t e n t g o e s h e r e < / d e t a i l s > Details
  14. Shadow Trees shadow host shadow root child child child child

    Document Tree ... ... ... shadow boundary ... ...
  15. Creating Shadow DOM . c r e a t e

    S h a d o w R o o t ( ) creates a shadow root on a host element. < b u t t o n > H e l l o W o r l d ! < / b u t t o n > v a r h o s t = d o c u m e n t . q u e r y S e l e c t o r ( ' b u t t o n ' ) ; v a r s h a d o w R o o t = h o s t . c r e a t e S h a d o w R o o t ( ) ; s h a d o w R o o t . t e x t C o n t e n t = ' H e l l o J s i s t ! ' ; Demo
  16. It's just HTML Use typical JS APIs to put nodes

    into your Shadow DOM (. i n n e r H T M L , . a p p e n d C h i l d ( ) ...). v a r h o s t = d o c u m e n t . q u e r y S e l e c t o r ( ' # h o s t ' ) ; v a r s h a d o w R o o t = h o s t . c r e a t e S h a d o w R o o t ( ) ; v a r p = d o c u m e n t . c r e a t e E l e m e n t ( ' p ' ) ; p . i n n e r H T M L = ' T h i s i s H T M L c o d e ' ; / * * * B o t h w o r k * / s h a d o w R o o t . i n n e r H T M L = ' < p > T h i s i s H T M L c o d e < / p > ' ; s h a d o w R o o t . a p p e n d C h i l d ( p ) ;
  17. Shadow DOM <3 Templates Simply combine the things we just

    learned. < t e m p l a t e i d = " c u s t o m - t e m p l a t e " > < p > T h i s i s H T M L C o d e < / p > < / t e m p l a t e > v a r h o s t = d o c u m e n t . q u e r y S e l e c t o r ( ' # h o s t ' ) ; v a r s h a d o w R o o t = h o s t . c r e a t e S h a d o w R o o t ( ) ; v a r t = d o c u m e n t . q u e r y S e l e c t o r ( ' # c u s t o m - t e m p l a t e ' ) ; s h a d o w R o o t . a p p e n d C h i l d ( t . c o n t e n t . c l o n e N o d e ( t r u e ) ) ;
  18. Great! But is there also a way to separate the

    content from presentation? YES!
  19. Insertion Points < c o n t e n t

    > < / c o n t e n t > lets you create insertion points that cherry-pick content from the shadow host.
  20. Let's create a special button < t e m p

    l a t e i d = " s p e c i a l - b u t t o n - t e m p l a t e " > < s t y l e > < / s t y l e > < b u t t o n c l a s s = " s p e c i a l - b u t t o n " > S p e c i a l B u t t o n ! < / b u t t o n > < / t e m p l a t e > . s p e c i a l - b u t t o n { b a c k g r o u n d : # b a d a 5 5 ; c o l o r : r e d ; p a d d i n g : 1 e m ; b o r d e r - r a d i u s : 0 . 3 e m ; f o n t - s i z e : 1 e m ; }
  21. < s p a n i d = " s

    p e c i a l - b u t t o n " > < / s p a n > Special Button!
  22. < s p a n i d = " s

    p e c i a l - b u t t o n " > S p e c i a l B u t t o n ! < / s p a n > Special Button!
  23. < s p a n i d = " s

    p e c i a l - b u t t o n " > M e r h a b a ! < / s p a n > Merhaba!
  24. < t e m p l a t e i

    d = " s p e c i a l - b u t t o n - t e m p l a t e " > < s t y l e > < / s t y l e > < b u t t o n c l a s s = " s p e c i a l - b u t t o n " > S p e c i a l B u t t o n ! < / b u t t o n > < / t e m p l a t e > . s p e c i a l - b u t t o n { b a c k g r o u n d : # b a d a 5 5 ; c o l o r : r e d ; p a d d i n g : 1 e m ; b o r d e r - r a d i u s : 0 . 3 e m ; f o n t - s i z e : 1 e m ; }
  25. < t e m p l a t e i

    d = " s p e c i a l - b u t t o n - t e m p l a t e " > < s t y l e > < / s t y l e > < b u t t o n c l a s s = " s p e c i a l - b u t t o n " > < c o n t e n t > < / c o n t e n t > < / b u t t o n > < / t e m p l a t e > . s p e c i a l - b u t t o n { b a c k g r o u n d : # b a d a 5 5 ; c o l o r : r e d ; p a d d i n g : 1 e m ; b o r d e r - r a d i u s : 0 . 3 e m ; f o n t - s i z e : 1 e m ; } Demo
  26. Cherry-picking content projection s e l e c t attribute

    uses CSS selectors to specify where children are projected. < d i v i d = " h o s t " > < h 1 > M y T i t l e < / h 1 > < h 2 > M y S u b t i t l e < / h 2 > < d i v > . . . o t h e r c o n t e n t . . . < / d i v > < / d i v > < h g r o u p > < c o n t e n t s e l e c t = " h 2 " > < / c o n t e n t > < c o n t e n t s e l e c t = " h 1 : f i r s t - c h i l d " > < / c o n t e n t > < / h g r o u p >
  27. Wow! Can we even select descendents for projection like s

    e l e c t = " t a b l e t r " ? NO!
  28. Style Encapsulation Shadow DOM comes with a shadow boundary that

    enables style encapsulation for free. Styles are scoped to shadow root < d i v > < h 3 > L i g h t D O M < / h 3 > < / d i v > < s c r i p t > v a r h o s t = d o c u m e n t . q u e r y S e l e c t o r ( ' d i v ' ) . c r e a t e S h a d o w R o o t ( ) ; h o s t . i n n e r H T M L = ' < s t y l e > h 3 { c o l o r : r e d ; } < / s t y l e > ' + ' < h 3 > S h a d o w D O M < / h 3 > ' ; < / s c r i p t > Shadow DOM
  29. Styling the host element : h o s t allows

    us to style the element hosting a shadow tree. < b u t t o n > M y b u t t o n < / b u t t o n > < s c r i p t > v a r b u t t o n = d o c u m e n t . q u e r y S e l e c t o r ( ' b u t t o n ' ) ; v a r h o s t = b u t t o n . c r e a t e S h a d o w R o o t ( ) ; h o s t . i n n e r H T M L = ' < s t y l e > ' + ' : h o s t { t e x t - t r a n s f o r m : u p p e r c a s e ; } ' + ' < / s t y l e > ' + ' < c o n t e n t > < / c o n t e n t > ' ; < / s c r i p t > MY BUTTON
  30. Moar host selectors : h o s t ( s

    e l e c t o r ) - Matches if host itself s e l e c t o r : h o s t ( : h o v e r / : a c t i v e ) - Know pseudo selectors
  31. Context selectors : h o s t - c o

    n t e x t ( s e l e c t o r ) - Matches if host element or any of its ancestors match s e l e c t o r < d i v c l a s s = " t h e m e - n a m e " > < x - f o o > < / x - f o o > < / d i v > : h o s t - c o n t e x t ( . t h e m e - n a m e ) { / * s t y l e s * / }
  32. Styling Shadow DOM from outside We have two new selectors

    to cross the shadow boundaries and style Shadow DOM from the outside world. : : s h a d o w - matches the shadow root itself / d e e p / - Crosses into any number of shadow trees
  33. The : : s h a d o w pseudo-element

    < s t y l e > < / s t y l e > < d i v i d = " h o s t " > < s p a n > L i g h t D O M < / s p a n > < / d i v > # h o s t : : s h a d o w s p a n { c o l o r : r e d ; } v a r h o s t = d o c u m e n t . q u e r y S e l e c t o r ( ' d i v ' ) ; v a r r o o t = h o s t . c r e a t e S h a d o w R o o t ( ) ; r o o t . i n n e r H T M L = ' < s p a n > S h a d o w D O M < / s p a n > ' + ' < c o n t e n t > < / c o n t e n t > ' ; Shadow DOMLight DOM
  34. The / d e e p / combinator Useful when

    having multiple levels of Shadow DOM (very common when working with Custom Elements. x - t a b s / d e e p / x - p a n e l { / * s t y l e s * / } ^ Select all x - p a n e l elements that are descendents of x - t a b anywhere in the tree.
  35. Four technologies Shadow DOM - Style & DOM encapsulation HTML

    Templates - Inert chunks of clonable DOM Custom Elements - Define and use new DOM elements HTML Imports - Include/Reuse other HTML documents
  36. Four technologies Custom Elements - Define and use new DOM

    elements HTML Templates - Inert chunks of clonable DOM Shadow DOM - Style & DOM encapsulation HTML Imports - Include/Reuse other HTML documents
  37. Custom Elements Features Define new HTML/DOM Elements Extend existing elements

    Bundle together custom functionality into a single tag
  38. Registering new elements d o c u m e n

    t . r e g i s t e r E l e m e n t ( ) let's you create custom elements. v a r M y E l e m e n t = d o c u m e n t . r e g i s t e r E l e m e n t ( ' m y - e l e m e n t ' ) ; d o c u m e n t . b o d y . a p p e n d C h i l d ( n e w M y E l e m e n t ( ) ) ; Or with an optional prototype v a r M y E l e m e n t = d o c u m e n t . r e g i s t e r E l e m e n t ( ' m y - e l e m e n t ' , { p r o t o t y p e : O b j e c t . c r e a t e ( H T M L E l e m e n t . p r o t o t y p e ) } ) ;
  39. Extend native/custom elements Simply inherit prototype from H T M

    L [ t y p e ] E l e m e n t and add e x t e n d s property accordingly. v a r M e g a B u t t o n = d o c u m e n t . r e g i s t e r E l e m e n t ( ' m e g a - b u t t o n ' , { p r o t o t y p e : O b j e c t . c r e a t e ( H T M L B u t t o n E l e m e n t . p r o t o t y p e , { / * n e w A P I s * / } ) , e x t e n d s : ' b u t t o n ' } ) ; < b u t t o n i s = " m e g a - b u t t o n " > < / b u t t o n > Custom elements that inherit from native elements are called type extension custom elements.
  40. Instantiate Custom Elements Declarative: < m y - e l

    e m e n t > < / m y - e l e m e n t > Via DOM APIs: v a r m y E l e m e n t = d o c u m e n t . c r e a t e E l e m e n t ( ' m y - e l e m e n t ' ) ; Using n e w : v a r m y E l e m e n t = n e w M y E l e m e n t ( ) ; d o c u m e n t . b o d y . a p p e n d C h i l d ( m y E l e m e n t ) ;
  41. Lifecycle callback methods c r e a t e d

    C a l l b a c k - instance of the element is created a t t a c h e d C a l l b a c k - instance was inserted into the document d e t a c h e d C a l l b a c k - instance was removed into the document a t t r i b u t e C h a n g e d C a l l b a c k - attribute was added, removed or updated
  42. v a r p r o t o = O

    b j e c t . c r e a t e ( H T M L E l e m e n t . p r o t o t y p e ) ; p r o t o . c r e a t e d C a l l b a c k = f u n c t i o n ( ) { . . . } ; p r o t o . a t t a c h e d C a l l b a c k = f u n c t i o n ( ) { . . . } ; v a r X F o o = d o c u m e n t . r e g i s t e r E l e m e n t ( ' x - f o o ' , { p r o t o t y p e : p r o t o } ) ;
  43. v a r p r o t o = O

    b j e c t . c r e a t e ( H T M L E l e m e n t . p r o t o t y p e ) ; p r o t o . c r e a t e d C a l l b a c k = f u n c t i o n ( ) { t h i s . i n n e r H T M L = ' < p > H T M L g o e s h e r e < / p > ' ; } ; v a r X F o o = d o c u m e n t . r e g i s t e r E l e m e n t ( ' x - f o o ' , { p r o t o t y p e : p r o t o } ) ;
  44. v a r p r o t o = O

    b j e c t . c r e a t e ( H T M L E l e m e n t . p r o t o t y p e ) ; p r o t o . c r e a t e d C a l l b a c k = f u n c t i o n ( ) { v a r t = d o c u m e n t . q u e r y S e l e c t o r ( ' # s d t e m p l a t e ' ) ; v a r c l o n e = t . c o n t e n t . c l o n e N o d e ( t r u e ) ; t h i s . c r e a t e S h a d o w R o o t ( ) . a p p e n d C h i l d ( c l o n e ) ; } ; v a r X F o o = d o c u m e n t . r e g i s t e r E l e m e n t ( ' x - f o o ' , { p r o t o t y p e : p r o t o } ) ;
  45. Four technologies Custom Elements - Define and use new DOM

    elements HTML Templates - Inert chunks of clonable DOM Shadow DOM - Style & DOM encapsulation HTML Imports - Include/Reuse other HTML documents
  46. Four technologies HTML Imports - Include/Reuse other HTML documents HTML

    Templates - Inert chunks of clonable DOM Shadow DOM - Style & DOM encapsulation Custom Elements - Define and use new DOM elements
  47. Why Imports? Different types of the web that can be

    loaded: < s c r i p t s r c > - For JavaScript < l i n k r e l = " s t y l e s h e e t " > - For Stylesheets < i m g > , < v i d e o > , < a u d i o > ...
  48. Here are our options < i f r a m

    e > - super heavy, super restrictive, frustrating to script in/out A J A X - x h r . r e s p o n s e T y p e = " d o c u m e n t " , wtf? We need JS to load HTML? Hacks - embedded in strings, hidden as comments
  49. HTML Imports to the rescue! Use < l i n

    k r e l = " i m p o r t " > to import external HTML documents. < l i n k r e l = " i m p o r t " h r e f = " p a t h / t o / i m p o r t . h t m l " >
  50. Turns this... < l i n k r e l

    = " s t y l e s h e e t " h r e f = " b o o t s t r a p . c s s " > < l i n k r e l = " s t y l e s h e e t " h r e f = " f o n t s . c s s " > < s c r i p t s r c = " j q u e r y . j s " > < / s c r i p t > < s c r i p t s r c = " b o o t s t r a p . j s " > < / s c r i p t > < s c r i p t s r c = " b o o t s t r a p - t o o l t i p . j s " > < / s c r i p t > < s c r i p t s r c = " b o o t s t r a p - d r o p d o w n . j s " > < / s c r i p t >
  51. ...into this. < l i n k r e l

    = " i m p o r t " h r e f = " b o o t s t r a p . h t m l " >
  52. Getting the content v a r c o n t

    e n t = d o c u m e n t . q u e r y S e l e c t o r ( ' l i n k [ r e l = " i m p o r t " ] ' ) . i m p o r t
  53. Cloning contents into main document v a r l i

    n k = d o c u m e n t . q u e r y S e l e c t o r ( ' l i n k [ r e l = " i m p o r t " ] ' ) ; v a r c o n t e n t = l i n k . i m p o r t ; v a r e l = c o n t e n t . q u e r y S e l e c t o r ( ' . w i d g e t ' ) ; d o c u m e n t . b o d y . a p p e n d C h i l d ( e l ) ; Content is inert until cloned into the DOM!
  54. Declaring elements with Polymer < p o l y m

    e r - e l e m e n t n a m e = " f o o - e l e m e n t " c o n s t r u c t o r = " F o o E l e m e n t " > < t e m p l a t e > < ! - - s h a d o w D O M h e r e - - > < p > T h i s i s a f o o - e l e m e n t . < / p > < / t e m p l a t e > < s c r i p t > < / s c r i p t > < / p o l y m e r - e l e m e n t > P o l y m e r ( { / / p r o p e r t i e s a n d m e t h o d s h e r e } ) ;
  55. Declaring elements with X-Tag v a r f r a

    g = x t a g . c r e a t e F r a g m e n t ( ' < p > T h i s i s a f o o - e l e m e n t . < / p > ' ) ; x t a g . r e g i s t e r ( ' f o o - e l e m e n t ' , { l i f e c y c l e : { c r e a t e d : f u n c t i o n ( ) { t h i s . a p p e n d C h i l d ( f r a g . c l o n e N o d e ( t r u e ) ) ; } } } ) ;
  56. Shadow DOM is optional in X-Tag x t a g

    . r e g i s t e r ( ' m y - e l e m e n t ' , { l i f e c y c l e : { c r e a t e d : f u n c t i o n ( ) { v a r t p l = d o c u m e n t . q u e r y S e l e c t o r ( ' # m y - t e m p l a t e ' ) ; v a r s h a d o w = t h i s . c r e a t e S h a d o w R o o t ( ) s h a d o w . a p p e n d C h i l d ( t p l . c o n t e n t . c l o n e N o d e ( t r u e ) ) ; } } } ) ;
  57. Reads Polymer vs. X-Tag - Here's the difference Inheritance and

    Composition in Polymer Sharing styles across Web Components with Polymer and core-style