Semantic HTML, Web Components, and Javascript

Oh my!

Problem Domain

Angular Person Directive from RT-WAR

<span>
    <a style="cursor: pointer" onclick="SP.UI.ModalDialog.showModalDialog({url:'../_layouts/userdisp.aspx?ID={{ personInfo.ID || personInfo.Author.ID || personInfo.User.ID }}'});">
        {{ personInfo.Name || personInfo.Author.Name || personInfo.User.Name }}
    </a>
</span>    

Whoa, That looked Weird

Mustache Style Templates

<h1>{{title}}</h1>
<div>
    {{content}}
</div>
+
{
    "title": "Example",
    "content": "Here is some example content"
}

Template and POJO




<h1>Example</h1>
<div>
    Here is some example content
</div>


Semantic HTML


  • HTML that describes the content
  • Use of HTML to reinforce the meaning

  • Semantic tags
    • h1, form, table, img
  • Non-Semantic tags
    • div, span

Examples


 <button>Go!</button>
vs
 <div class="button">Go!</div>

- or -

 <div class="link" data-link-to="/about">About</div>
vs
 <a href="/about">About</a>

Why do I care?


  • Screen readers work better
  • Search engines can understand better
  • Easier as a dev to understand
  • Encourages better separation of concerns


Semantic HTML...

But...

HTML5!


  • Nothing new, boagworld has an article from 2005
  • HTML 5 just introduces additional tags
    • header, nav, section, article, aside, figure, figcaption, footer, details, summary, mark, time
  • Know when to use them

Improve what we had

<a style="cursor: pointer" onclick="SP.UI.ModalDialog.showModalDialog({url:'../_layouts/userdisp.aspx?ID={{ personInfo.ID || personInfo.Author.ID || personInfo.User.ID }}'});">
        {{ personInfo.Name || personInfo.Author.Name || personInfo.User.Name }}
</a>

  • Both span and anchor's are inline elements
  • span provides no value in this scenario

Wait a Minute!

  • What is that style doing there?
    • Well, lets partially fix now

<a onclick="SP.UI.ModalDialog.showModalDialog({url:'../_layouts/userdisp.aspx?ID={{ personInfo.ID || personInfo.Author.ID || personInfo.User.ID }}'});">
        {{ personInfo.Name || personInfo.Author.Name || personInfo.User.Name }}
</a>

Web Components


  • Allow web developers to define new HTML elements
    • Allows more semantic markup
  • Allows bundling of Javascript with an element

        <x-gas-products>
        </x-gas-products>
    

How Do I Use This?

  • Part of the HTML5 spec
    • wait for Microsoft to adopt (NOT part of IE11)
    • Chrome and Firefox support
  • Use a library or framework
    • Ember-Components
    • Angular Directives
    • Polymer

Improve What We Have

  • There is really nothing to do here
  • Already using an Angular Directive
    • We have been looking at the "internal" markup all along

<div data-person data-person-info="item.Author" />

Wait a minute!

  • Non-semantic div
  • Data prefixing
  • Self Closing

 <div data-person data-person-info="item.Author" />

Refactor

onclick="SP.UI.ModalDialog.showModalDialog({url:'../_layouts/userdisp.aspx?ID={{ personInfo.ID || personInfo.Author.ID || personInfo.User.ID }}'});"

By using ngClick
<a ng-click="showUserInfoSPModal()">{{ personObject.Name }}</a>
Directive Controller
// personObject is passed into the controller
...
var userDisplayUrl = '/_layouts/userdisp.aspx?ID=' + personObject.ID;
showUserInfoSPModal = function() {
    SP.UI.ModalDialog.showModalDialog({url: userDisplayUrl});
};
...


Refactor

onclick="SP.UI.ModalDialog.showModalDialog({url:'../_layouts/userdisp.aspx?ID={{ personInfo.ID || personInfo.Author.ID || personInfo.User.ID }}'});"

By using ngClick
ng-click="showUserInfoSPModal()"
Directive Controller
// personObject is passed into the controller
...
var userDisplayUrl = '/_layouts/userdisp.aspx?ID=' + personObject.ID;
showUserInfoSPModal = function() {
    SP.UI.ModalDialog.showModalDialog({url: userDisplayUrl});
};
...

Notable Changes

  • Proper separation of code
  • Remove complexity
  • Added readability
 var id = personInfo.ID || personInfo.Author.ID || personInfo.User.ID;
vs
var id = personObject.ID;

Complete Fix

Alluded to a partial fix previously regarding semantic markup
Whats wrong with this?
<a ng-click="showUserInfoSPModal()">{{ personObject.Name }}</a>

Right! Anchors have HREFs
<a href="{{ userDisplayUrl }}" ng-click="showUserInfoSPModal()">
    {{ personObject.Name }}
</a>

That ALl?

Well, by adding that href we handled the old bad inline style

And here are some more examples of components

Resources

Semantic HTML,

By Ryan Hirsch

Semantic HTML,

  • 915