Skip to content

Instantly share code, notes, and snippets.

@timshadel
Last active August 25, 2019 20:15
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timshadel/5818243af126c2ca3dd4 to your computer and use it in GitHub Desktop.
Save timshadel/5818243af126c2ca3dd4 to your computer and use it in GitHub Desktop.
A Facebook post in HTML and hyper+json.

Compare & Contrast

HTML, Hyper+JSON, and Data as JSON

OK. Everyone's got LOTS of questions and emotions around how to use hyper. I want to answer them, but first I want to walk you through a comparison exercise.

  1. Take a look at the screenshot below of a typical Facebook post.

    Think about the ways you could navigate or interact with this FB post, based only on what you see. Any kind of interaction you take either moves the view to another object, or it alters the data of this object.

  2. Look through 4 different ways to represent this screen

    With each one, notice what's similar and what's different.

  3. Read through the Q&A at the bottom & actually answer the questions

    Try to keep the answers hidden, then see if you come up with any surprises.

<div class="userContentWrapper _5pcr _3ccb"
data-gt="{&quot;type&quot;:&quot;click2canvas&quot;,&quot;fbsource&quot;:703,&quot;ref&quot;:&quot;nf_generic&quot;}">
<div class="_4r_y">
<div class="_6a uiPopover _5pbi _5puc _5v56 _b1e" id="u_jsonp_4_10">
<a class="_5pbj _p" aria-label="Story options" href="#"
aria-haspopup="true" aria-expanded="false" rel="toggle"
role="button" id="u_jsonp_4_11"></a>
</div>
</div>
<div class="clearfix _5x46">
<a class="_5pb8 _5v9u _29h _303"
href="https://www.facebook.com/brittiny.jones?fref=nf" aria-hidden="true" tabindex="-1"
data-ft="{&quot;tn&quot;:&quot;m&quot;}" data-hovercard="/ajax/hovercard/user.php?id=7066216">
<img class="_s0 _5xib _5sq7 _rw img" src="https://fbcdn-profile-a.akamaihd.net/hp....">
<!--
Yup. A ton of UI-aware html.
-->
<!--
NOTE: I've simplified the FB 'like, comment, share' line here.
JS heavily alters the actual requests.
I've made the semantic HTML reflect the actual FB requests.
-->
<form method="post" action="/ajax/ufi/modify.php" rel="async">
<input type=​"hidden" autocomplete=​"off" name=​"data_only_response" value=​"1">​
<input type=​"hidden" autocomplete=​"off" name=​"feedback_params" value=​"{"actor":​"7066216","target_fbid":​"10126303101029766","check_hash":​"AQBlv4okzAMN_-oj"}​">​
<div>
<span>
<a href="#">Like</a>
</span>
<label>
<input name=​"add_comment_text" type="text">​
<input type=​"button" value=​"Comment">​
</label>
<span>
<a href="/ajax/sharer/?s=22&appid=98234602" rel="dialog">Share</a>
</span>
</div>
</form>
<div class="post">
<div class="header">
<a href="/brittiny-jones?fref=nf">
<img src="/brittiny-jones/picture" alt="Profile photo of Brittiny Jones" />
</a>
<h5 class="name">
<a href="/brittiny-jones?fref=nf">
Brittiny Emerson Jones
</a>
</h5>
<div class="post-metadata">
<a href="/brittiny-jones/posts/10126303101029766">
<abbr data-utime="1415916614">2 hrs</abbr>
</a>
<div title="Shared with: Brittiny's friends">
<i class="icon-shared-with-friends"></i>
</div>
</div>
</div>
<div class="body">
<div>
<p>Well, we finally had that classic parent experience:</p>
<p>Me: Why are you crying?<br/>
Kid: Because something's up my nose and I can't get it out!</p>
<p>Yes, yes, it was a lego.</p>
</div>
<div class="controls">
<span>
<form method="post" action="/ajax/ufi/like.php">
<input type=​"hidden" autocomplete=​"off" name=​"like_action" value=​"1">​
<input type=​"hidden" autocomplete=​"off" name=​"actor" value=​"7066216">​
<input type=​"hidden" autocomplete=​"off" name=​"ft_ent_identifier" value=​"10126303101029766">​
<input type=​"button" value=​"Like">​
</form>
</span>
<span>
<form method="post" action="/ajax/ufi/add_comment.php">
<input type=​"hidden" autocomplete=​"off" name=​"actor" value=​"7066216">​
<input type=​"hidden" autocomplete=​"off" name=​"ft_ent_identifier" value=​"10126303101029766">​
<input type=​"text" autocomplete=​"off" name=​"comment_text" placeholder=​"Write a comment...">​
<input type=​"button" value=​"Comment">​
</form>
</span>
<span>
<a href="/ajax/sharer/?s=22&appid=98234602" rel="dialog">Share</a>
</span>
</div>
<div class="LikeSentence">
<a class=​"profileLink" href=​"/​jennifer.smith" data-hovercard=​"/​ajax/​hovercard/​hovercard.php?​id=272414071">​Jennifer Zuckerman Smith</a>​,
<a class=​"profileLink" href=​"/kara.jensen" data-hovercard=​"/​ajax/​hovercard/​hovercard.php?​id=140272471">​Kara Smith Johnson</a>​,
<a class=​"profileLink" href=​"/jenny.jacobs" data-hovercard=​"/​ajax/​hovercard/​hovercard.php?​id=471140272">​Jenny Jacobs</a>​, and
<a class=​"profileLink" href=​"/browse/likes?id=10126303101029766&actor=7066216" role="button">​32 others</a>​like this.
</div>
</div>
{
"href": "/brittiny-jones/posts/10126303101029766",
"author": {
"href": "/brittiny-jones?fref=nf",
"picture": {
"src": "/brittiny-jones/picture",
"type": "image/jpeg",
"title": "Profile photo of Brittiny Jones"
},
"name": "Brittiny Emerson Jones"
},
"meta_details": {
"time": {
"utime": 1415916614,
"text": "2 hrs"
},
"audience": {
"type": "friends_of",
"users": [ "brittiny-jones" ],
"text": "Shared with: Brittiny's friends"
}
},
"paragraphs": [
"Well, we finally had that classic parent experience:",
"Me: Why are you crying?
Kid: Because something's up my nose and I can't get it out!",
"Yes, yes, it was a lego."
],
"likes": {
"href": ​"/browse/likes?id=10126303101029766&actor=7066216",
"count": 35,
"collection": [
{
"href": ​"/​jennifer.smith",
"class": "profileLink",
"hovercard": { "href": "/​ajax/​hovercard/​hovercard.php?​id=272414071" },
"name": "​Jennifer Zuckerman Smith"
},
{
"href": ​"/kara.jensen",
"class": "profileLink",
"hovercard": { "href": "/​ajax/​hovercard/​hovercard.php?​id=140272471" },
"name": "​Kara Smith Johnson"
},
{
"href": ​"/jenny.jacobs",
"class": "profileLink",
"hovercard": { "href": "/​ajax/​hovercard/​hovercard.php?​id=471140272" },
"name": "Jenny Jacobs"
}
]
},
"like": {
"action": "/ajax/ufi/like.php",
"method": "POST",
"input": {
"like_action": {
"type": "hidden",
"value": true
},
"actor": {
"type": "hidden",
"value": ​"7066216"
},
"ft_ent_identifier": {
"type": "hidden",
"value": ​"10126303101029766"
}
}
},
"comment": {
"action": "/ajax/ufi/add_comment.php",
"method": "POST",
"input": {
"actor": {
"type": "hidden",
"value": ​"7066216"
},
"ft_ent_identifier": {
"type": "hidden",
"value": ​"10126303101029766"
},
"comment_text": {
"type": "text",
"placeholder": "Write a comment..."
}
}
},
"share": {
"href": "/ajax/sharer/?s=22&appid=98234602",
"prompt": "Share"
}
}
{
"id": "10126303101029766",
"author": {
"id": "brittiny-jones",
"name": "Brittiny Emerson Jones"
},
"meta_details": {
"time": {
"utime": 1415916614,
"text": "2 hrs"
},
"audience": {
"type": "friends_of",
"users": [ "brittiny-jones" ],
"text": "Shared with: Brittiny's friends"
}
},
"paragraphs": [
"Well, we finally had that classic parent experience:",
"Me: Why are you crying?
Kid: Because something's up my nose and I can't get it out!",
"Yes, yes, it was a lego."
],
"likes_count": 35,
"likes": [
{
"id": ​"​jennifer.smith",
"name": "​Jennifer Zuckerman Smith"
},
{
"id": ​"kara.jensen",
"name": "​Kara Smith Johnson"
},
{
"id": ​"jenny.jacobs",
"name": "Jenny Jacobs"
}
]
}

Discussion

OK. With parallel examples, let's go through and compare and contrast them.

Regular HTML: 39,453 bytes

Semantic HTML: 2,602 bytes

hyper+JSON: 2,347 bytes

data as JSON: 838 bytes

Ultimately I hope you'll see that hyper+json's closest cousin is actually semantic HTML, and if you like semantic HTML then you should really love hyper.

Media Type Q&A

  1. Which code knows how to draw the UI in each case?

    Regular HTML: app server + CSS

    The HTML document contains lots of presentation details for browser code. The server must know about presentation details to serve it up. The browser must know an immense amount about how to render any valid HTML document.

    Semantic HTML: CSS

    The HTML document contains no presentation detail—everything is in separate CSS files. The server only needs to know how to arrange the data when making this document, and how to render links to related data and forms. The document only includes the basic instructions for navigation and form submission.

    hyper+JSON: client app

    The server only needs to know how to arrange the data when making this document, and how to render links to related data and forms. The document also includes the basic instructions for finding related data, and altering this data.

    data as JSON: client app

    The server only needs to know how to arrange the data when making this document.

  2. Which code knows the URL for profile images?

    Regular HTML: app server

    The HTML document has <img> tags, with URLs created by the server.

    Semantic HTML: app server

    The HTML document has <img> tags, with URLs created by the server.

    hyper+JSON: app server

    The hyper document has src properties, with URLs created by the server.

    data as JSON: client app + app server to serve the image

    Custom client app code must turn the author's id into a URL.

  3. Which code knows how to issue a like command?

    Regular HTML: app server

    The HTML document has <form> tags, with URLs and hidden inputs created by the server.

    Generic browser code knows how to turn form tags into a valid HTTP request (without having a clue what the request means) when the user triggers that action.

    Semantic HTML: app server

    The HTML document has <form> tags, with URLs and hidden inputs created by the server.

    Ditto on the generic browser.

    hyper+JSON: app server

    The HTML document has action objects, with URLs and hidden inputs created by the server.

    Generic hyper code knows how to turn action objects into a valid HTTP request (without having a clue what the request means) when the client app triggers that action.

    Generic HTTP libraries properly encode the request as a application/x-www-form-urlencoded document.

    data as JSON: client app + app server to process the request

    Custom client app code must issue a request to the correct URL, and include all the relevant hidden inputs when that action is triggered.

    Generic HTTP libraries properly encode the request as a application/x-www-form-urlencoded document.

  4. Which code knows how to issue a comment command? What's different from like?

    Regular HTML: app server + browser for comment text

    The HTML document has <form> tags, with URLs and hidden inputs created by the server.

    Generic browser code provides a user control, asking the user to provide the text. It knows to update the parameter of a form because its <input> is nested within the <form>.

    Generic browser code knows how to turn form tags into a valid HTTP request (without having a clue what the request means) when the user triggers that action.

    Semantic HTML: app server + browser for comment text

    The HTML document has <form> tags, with URLs and hidden inputs created by the server.

    Ditto on the browser.

    hyper+JSON: app server + client app for comment text

    The hyper document has action objects, with URLs and hidden inputs created by the server.

    Custom client app code provides a user control, asking the user to provide the text. It knows to that control is bound to update the input parameter inside the action object.

    Generic hyper code knows how to turn action objects into a valid HTTP request (without having a clue what the request means) when the client app triggers that action.

    Generic HTTP libraries properly encode the request as a application/x-www-form-urlencoded document.

    data as JSON: client app + app server to process the request

    Custom client app code provides a user control, asking the user to provide the text.

    Custom client app code must issue a request to the correct URL, and include all the relevant hidden inputs, and place the user comment text in the right parameter when that action is triggered.

    Generic HTTP libraries properly encode the request as a application/x-www-form-urlencoded document.

Recap

  1. Regular HTML

    Server takes responsibility for UI and data. Client expected to render dynamic UI per request from HTML/CSS.

  2. Semantic HTML

    Server takes responsibility for UI nav, forms, and data. Client expected to render dynamic UI per request from HTML/CSS.

  3. hyper+JSON

    Server takes responsibility for data nav, forms, and data. Client expected to render static UI from custom code, and handle UI nav appropriate for the data links from hyper. The client app is bound to data paths in the hyper+JSON, but not to the detail of how to construct valid requests.

  4. data as JSON

    Server takes responsibility for data only. Custom client code expected to do UI, data nav, UI nav, and form submission. The client app is bound to BOTH the data paths in the data as JSON, AND the detail of how to construct valid requests. Strongly typed mappings are often bound to the entire and exact object structure, breaking more easily when things change in ways that don't break loosely coupled mappings.

I hope you'll see the parallels between hyper+json and Semantic HTML. Both focus on:

  1. Raw Data
  2. Structured semantically
  3. Have basic navigation links to related data
  4. Provide forms to alter current data

Both rely on:

  1. Generic code to follow links
  2. Generic code to submit forms
  3. Custom client code to render the UI (CSS, JS, or native)

A few ways they differ:

  1. Semantic HTML assumes generic browser code will render basic UI

    Hyper assumes custom client code will map UI to a named form parameter, and map data paths from the object into UI elements.

  2. Semantic HTML assumes that following a link will give the browser a new UI with embedded data

    Hyper assumes that generic hyper code will request the data, and then custom client code will transition to a UI appropriate for that data

In general, semantic HTML relies more on assumptions about UI, and hyper expects a custom UI nav to trigger data links.

@mndvns
Copy link

mndvns commented Nov 14, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment