BreizhBeans - Web components


Published on

A talk on web components

Published in: Technology, Design
  • Be the first to comment

  • Be the first to like this

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

BreizhBeans - Web components

  1. 1. By @LostInBrittany Web Components today
  2. 2. Horacio Gonzalez Spaniard lost in Brittany, Java developer, dreamer and all-around geek • Senior Software Engineer at Crédit Mutuel Arkea o Currently... • Leader of the FinistJUG and the BreizhBeans community +Horacio.Gonzalez @LostInBrittany
  3. 3. BreizhBeans Developer community at the far end of French Brittany @BreizhBeans
  4. 4. Introduction Because I love to tell old stories
  5. 5. At the beginning we had the thick client • Widget : basic building blocks of your UI o Encapsultation o Reutilisation In thick client you create your UI by widget assembling Image : Wikipedia
  6. 6. Web development was unlike thick-client • HTML/CSS/JS didn't support widgets o Page where the building blocks Web apps were page oriented Image : IBM
  7. 7. GWT gave back widgets to web devs • GWT uses a thick-client-like development paradigm o Widgets, properties, events GWT web apps are widget oriented : Single-page apps Image : GWT Mail sample app
  8. 8. Single-page apps are a current trend • From UX POV single-page apps are richer o But making them without widgets is painful HTML/CSS/JS needed a widget standard Image : Ken Schultz comedy juggler
  9. 9. Web Components Reinventing the wheel... and this time making it round
  10. 10. Web Components : a W3C standard • Web Components standard is being worked at W3C o We all know what this means o Clue : HTML5 They will work for years, bickering and fighting Browsers and devs will use the WiP document
  11. 11. Example : the Google+ button • If you want to place a Google+ button in your page <!-- Place this tag where you want the +1 button to render. --> <div class="g-plusone" data-annotation="inline" data-width="300"></div> <!-- Place this tag after the last +1 button tag. --> <script type="text/javascript"> (function() { var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true; po.src = ''; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s); })(); </script>
  12. 12. Example : the Google+ button • And what I would like is simple <g:plusone></g:plusone>
  13. 13. Example : the Google+ button • To be fair, Google already makes it simpler <script type="text/javascript" src=""> </script> ... <g:plusone></g:plusone> • They create directives with JS to emulate components o AngularJS approach o Respecting the spirit of the future standard o Working in current browsers
  14. 14. Another example : the RIB • If you're French, you know what a RIB is o A banking account identification number • To show a RIB in HTML: o All styling, all surface control must be done elsewhere by CSS and JS • What I would like o A semantic tag o With encapsulated styling and surface controlling <div class="rib">58496 87451 00014500269 74</div> <x-rib banque=58496 guichet=87451 compte=00014500269 cle=74> </x-rib>
  15. 15. But we already can do that! • In most modern frameworks we can already do components, in a way or another o And all those ways are different! o Using different JavaScript libraries o Almost no component sharing between frameworks • W3C's works aim to make a standard way o Supported natively by all browsers o Allowing for component reuse
  16. 16. The 5 pillars of the Web Components • Templates • Shadow DOM • Custom Elements • Decorators • Imports
  17. 17. Templates The clone wars
  18. 18. Templates • A reusable model o Contains markup intended to be used later <template id="commentTemplate"> <div> <img src=""> <div class="comment-text"></div> </div> </template>
  19. 19. Templates before <template> • How did we do templating before o Using display:none or hidden o Putting it inside a script o Type unknown to browser, it isn't interpretated o Markup easily recovered via .innerHTML and reused o Approach used by many template engines <div id="commentTemplate" class="comment" hidden> <img src=""> <div class="comment-text"></div> </div> <script id="commentTemplate" type="text/template"> <div class="comment"> <img src=""> <div class="comment-text"></div> </div> </script>
  20. 20. • Uniformising those approach with a new tag <template id="commentTemplate"> <div> <img src=""> <div class="comment-text"></div> </div> </template> • Content inside the tag is parsed but not interpreted o HTML not shown o Resources are not loaded o Scripts not executed The <template> tag
  21. 21. Template instantiation • Using JavaScript <template id="commentTemplate"> <div> <img src=""> <div class="comment-text"></div> </div> </template> <script> function addComment(imageUrl, text) { var t = document.querySelector("#commentTemplate"); var comment = t.content.cloneNode(true); // Populate content. comment.querySelector('img').src = imageUrl; comment.querySelector('.comment-text').textContent = text; document.body.appendChild(comment); } </script>
  22. 22. Shadow DOM Join the shadowy side, young padawan Image: Springfield Punx
  23. 23. Encapsulation • Each component should have o Public interface o Private inner code • When using a component o You manipulate the interface only o You don't need to know anything about inner code o No conflict between inner code and outside code
  24. 24. Encapsulation before Shadow DOM • Only a way : <innerFrame> Image : Star Trek the Next Generation
  25. 25. Browsers already use encapsulation • Considerer this simple slider o How is is done inside? o With HTML, CSS and JS! o It has a movable element, I can recover it's position o Why cannot see it in DOM tree? • Browsers hide DOM sub-trees for standard components o They have a public interface and hidden inner code • That's Shadow DOM! <input id="foo" type="range"> <video width="320" height="240" controls> <source src="movie.mp4" type="video/mp4"> </video> Image: Springfield Punx
  26. 26. My name is DOM, Shadow DOM • Shadow DOM: ability of the browser to o Include a DOM subtree into the rendering o But not into the main document DOM tree • In Chome you can see the Shadow DOM o By activating the option in Inspector
  27. 27. Looking into the Shadow • For the slider :
  28. 28. Shadow DOM is already here • Browser use it everyday... o For their inner needs o Not exposed to developers • Web Components makes Shadow DOM available o You can use it for your own components Image: Springfield Punx
  29. 29. Using Shadow DOM • There is a host element o A normal element in DOM tree • A shadow root is associated to the host o Using the createShadowRoot method o The shadow root is the root of the hidden DOM tree Image: W3C
  30. 30. Using Shadow DOM • Quick and dirty Shadow DOM o DOM tree only shows <div id="emptyHost"></div> o Rendered HTML shows Not empty anymore! o Markup in innerHTML is ugly <div id="emptyHost"></div> <script> var host = document.querySelector('#emptyHost'); var root = host.createShadowRoot(); root.innerHTML = "<h1>Not empty anymore!</h4>"; </script>
  31. 31. Using Shadow DOM • Shadow DOM with templates <template id="commentTemplate"> <div> <img src=""> <div class="comment-text"></div> </div> </template> <script> function addComment(imageUrl, text) { ... } </script> <div id="emptyHost"></div> <script> var host = document.querySelector('#emptyHost'); var root = host.createShadowRoot(); root.appendChild = addComment("", "This is a nice comment made by a nice guy"); </script>
  32. 32. • HTML elements are compositional o You can put a button inside a table • Shadow DOM elements need to be compositional o Insertion points in the Shadow DOM Separate content from presentation <template id="commentTemplate"> <div class="comment"> <img src=""> <div class="comment-text"> <content></content> </div> </div> <style> ... </style> </template> ... <div id="aComment"> <h1>Ceci est un commentaire</h1> </div> Result : <div id="aComment"> #documentFragment <div class="comment"> <img src=""> <div class="comment-text"> <h1>Ceci est un commentaire</h1> </div> </div> <style> ... </style> </div>
  33. 33. • More granularity can be added : Separate content from presentation <template id="commentTemplate"> <div class="comment"> <div class="comment-img"> <content select="img"></content> </div> <div class="comment-author"> <content select="div"></content> </div> <div class="comment-text"> <content select="text"></content> </div> </div> <style> ... </style> </template> ... <div id="aComment"> <div class="author">Horacio</div> <img src=""/> <div class="text">Ceci est un commentaire</div> </div> Result : <div id="aComment"> #documentFragment <div class="comment"> <div class="comment-img"> <img src=""> </div> <div class="comment-author"> Horacio </div> <div class="comment-text"> Ceci est un commentaire </div> </div> <style> ... </style> </div> Why does it work for author? Invitation model, first match
  34. 34. Shadow DOM et CSS • CSS defined in the Shadow DOM remains there • Outside styles don't affect Shadowed content <h1>This is a title</h1> <div id="widget"> #document-fragment <style> div {border: solid 1px red;} h1 {color: blue;} </style> <h1>And this is widget title</h1> <div>Widget content here</div> </div> This is a title And this is widget title Widget content here
  35. 35. Shadow DOM et CSS • Styling the host element : @host <template id="template"> <style> @host { button { border-radius: 5px; } } </style> <content></content> </template> <button id="host">My Button</button> <script> var host = document.querySelector('#host'); var root = host.createShadowRoot(); var shadowContent = document.querySelector("#template").content.cloneNode(true); root.appendChild = shadowContent; </script> My Button
  36. 36. Shadow DOM et CSS • Inheriting and resetting styles in Shadow DOM content o .resetStyleInheritance  false (default) : properties are inherited  true : inheritable properties are reset to initial o .applyAuthorStyles  false (default) : author styles aren't applied  true: author styles bleed into the content • widget theming
  37. 37. Shadow DOM et CSS • Inheritance Cheat Sheet Image : HTML5 Rocks' Web Components 201
  38. 38. Custom Elements Elemental mayhem !
  39. 39. Custom elements : the <element> tag • An element encloses template, lifecycle and behaviour o Templates done with <template> tag <element name="tick-tock-clock"> <template> <style> // Here the nice style of our nice clock </style> <span id="hh"></span> <span id="sep">:</span> <span id="mm"></span> </template> </element>
  40. 40. • Livecycle defined with 3 callbacks o readyCallback: called after the element is created o insertedCallback: called after the element is inserted into a document o removedCallback: called after the element is removed Custom elements : the <element> tag <element name="tick-tock-clock"> <template> ... </template> <script> function aFunctionToStartTheClock() { ... } function aFunctionToStopTheClock() { ... } ({ readyCallback: function () { this._root = this.createShadowRoot(); this._root.appendChild(template.content.cloneNode()); if (this.parentElement) {; } }, insertedCallback: aFunctionToStartTheClock(), removedCallback: aFunctionToStopTheClock() }); </script> </element>
  41. 41. • If an element extends another, instantiation with is keyword Custom elements : instantiation <element extends="button" name="fancy-button"> ... </element> <button is="fancy-button">Do something fancy</button> • If an element doesn't extends, its name becomes a custom tag <element name="myShinyElement"> ... </element> <myShinyElement>Do something fancy</myShinyElement>
  42. 42. Imports Because you hate long files
  43. 43. • Custom elements can be loaded from external files o Using the link tag: o Only <decorator> and <element> are interpreted o The DOM of this document is available to script o Documents are retrieved according to cross-origin policies Polymer <link rel="import" href="goodies.html">
  44. 44. Other interesting bits Even if outside Web Components
  45. 45. • Provide developers a way to react to changes in DOM Mutation Observers // select the target node var target = document.querySelector('#some-id'); // create an observer instance var observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { console.log(mutation.type); }); }); // configuration of the observer: var config = { attributes: true, childList: true, characterData: true }; // pass in the target node, as well as the observer options observer.observe(target, config); // later, you can stop observing observer.disconnect(); • Replace MutationEvents o Increased performance
  46. 46. • Observe and notify of mutations to JavaScript objects o Properties added, updated, deleted or reconfigurated Object.observe function log( change ) { console.log( "What Changed? ", ); console.log( "How did it change? ", change.type ); console.log( "What is the present value? ", change.object[ ] ); } var o = {}; // Specify |o| as an observable object Object.observe(o, function( changes ) { changes.forEach( log ); }); o.who = "Rick"; /* What Changed? who How did it change? new What is the present value? Rick */ • Part of ECMA 6
  47. 47. Can I use? If not, why are you telling us all this sh*t?
  48. 48. Are we componetized yet
  49. 49. • New Google project o Introduced in Google I/O 2013 o New type of library for the web o Built on top of Web Components o Designed to leverage the evolving web platform • What does it means ? o Polymer is comprised of two efforts : o A core platform to give Web Component capabilities to modern browsers  Shims for all modern browsers  Shared with Mozilla x-tag project o A next-generation web framework built upon this core platform  Called the Polymer. Polymer
  50. 50. Polymer
  51. 51. • Principes: o Everything is a component  Encapsulation is needed for a component oriented application o Extreme pragmatism  Boilerplate is bad  Anything repetitive should be re-factored into a component • Handled by Polymer itself or • Added into the browser platform itself o Salt to taste  Use as much or as little of the framework as you wish. • You want polyfills only : load polymer-all/platform/platform.js • You want extra bits : load polymer-all/polymer/polymer.js o Polymer elements Polymer
  52. 52. • Platform technologies are already functional o You can use it to add templates, shadow DOM, custom elements and imports to your app • Lots of examples in the site Polymer
  53. 53. • X-Tag is a small JavaScript library o created and supported by Mozilla o that brings Web Components capabilities o to all modern browsers. • Polymer vs X-tags ? o Different features and approaches o Mozilla and Google are collaborating o building the shared polyfills platform X-Tags
  54. 54. • AngularJS directives allow to create custom elements o Similar but different to Web Components AngularJS angular.module('ng').directive('testElem', function () { return { restrict: 'A', template: '<div class="mydirectiveclass"><h1>hello...</h1><p ng-repeat="obj in arr">{{obj}}</p></div>', //templateUrl: '/partials/template.html', link: function (scope, iterStartElement, attr) { $(".mydirectiveclass").css({'background-color' : 'yellow'}); scope.arr = ["mikhail", "is", "the", "best"]; } }; }); o First line declares the directive testElem o The element name will be test-elem
  55. 55. • AngularJS directives allow to create custom elements o Similar but different to Web Components AngularJS angular.module('ng').directive('testElem', function () { return { restrict: 'A', template: '<div class="mydirectiveclass"><h1>hello...</h1><p ng-repeat="obj in arr">{{obj}}</p></div>', //templateUrl: '/partials/template.html', link: function (scope, iterStartElement, attr) { $(".mydirectiveclass").css({'background-color' : 'yellow'}); scope.arr = ["mikhail", "is", "the", "best"]; } }; }); o Restrict defines the element scope : o E: a DOM element with a custom name, <my-directive> o A: a DOM element with custom attribute, <div my-directive="exp"> o C: invocation via a class, <div class="my-directive: exp"> o M: invocation via a comment, o <!-- directive: my-directive exp -->
  56. 56. • AngularJS directives allow to create custom elements o Similar but different to Web Components AngularJS angular.module('ng').directive('testElem', function () { return { restrict: 'A', template: '<div class="mydirectiveclass"><h1>hello...</h1><p ng-repeat="obj in arr">{{obj}}</p></div>', //templateUrl: '/partials/template.html', link: function (scope, iterStartElement, attr) { $(".mydirectiveclass").css({'background-color' : 'yellow'}); scope.arr = ["mikhail", "is", "the", "best"]; } }; }); o template: HTML string of that the element will be replaced by o templateUrl: (optional) the template HTML inside another file o link: the linking function o After the template has been loaded, this function is called  to establish the AngularJS scope  any last-minute effects • jQuery animation or other logic.
  57. 57. • Using the custom elements AngularJS <!doctype html> <html> <head> <title>Directive Test</title> <script type="text/javascript" src="jquery.min.js" ></script> <script type="text/javascript" src="angular.min.js"></script> <script type="text/javascript" src="mydirectives.js"></script> </head> <body ng-app> <div test-elem></div> </body> </html>
  58. 58. Conclusion That's all folks!
  59. 59. You want to know more? • W3C's Introduction to Web Components • HTML5 Rocks' Shadow Dom 101 • HTML5 Rocks' Shadow Dom 201: CSS • Polymer & X-Tags • MutationObserver & Object.observe
  60. 60. Thank you !