HTMLDecor
文件大小: unknow
源码售价: 5 个金币 积分规则     积分充值
资源说明:HTMLDecor means full separation of content from presentation. With CSS you can change the styling of a whole site with one stylesheet. With HTMLDecor you can change everything - banner, navbars, ads, page-layout and stylesheets. This facilitates API-first / HTML-payload sites which are simple, robust and low-bandwidth, plus "pushState assisted navigation" comes for free.
HTMLDecor
=========

> HTMLDecor means **full** separation of content from presentation.
> With CSS you can change the styling of a whole site with one stylesheet.
> With HTMLDecor you can change everything -
> banner, navbars, ads, page-layout and stylesheets.
> This facilitates API-first / HTML-payload sites which are
> simple, robust and low-bandwidth, 
> plus "pushState assisted navigation" comes for free.

HTMLDecor is a Javascript page decoration engine which runs in the browser.
It allows your site to deliver real page content first and fast
(think API-first with HTML-payloads).
Your site decor can be placed in its own page and merged in the browser instead of on the server.
Auxiliary content could also be conditionally loaded with AJAX
(think inside-out iframes).

A site decor page is similar to an external stylesheet in that it can be shared between several pages.
Originally it was even referenced with a resource link, just like stylesheets:

    

**(This referencing method has been superceded by external configuration, which is less limiting.)**

As a bonus, when your site uses HTMLDecor "pushState assisted navigation" requires no additional setup. 
When someone viewing your page clicks on a link to another page that uses the same decor
then AJAX updates the real content
and `history.pushState()` updates the browser URL. 

HTMLDecor.js is around 10kB when minified and gzipped.

To see it in action visit my [blog](http://meekostuff.net/blog/).
Make sure you view the page source and check that it is just raw content.
The navbar and contact popup are all in the [site-decor page](http://meekostuff.net/blog/decor.html). 

For more info on the concept of HTMLDecor and its affinity with pushState assisted navigation, read  

- [The HTML decor concept](http://meekostuff.net/blog/HTML-Decor-I/)
- [Introducing HTMLDecor.js](http://meekostuff.net/blog/HTML-Decor-II/)
- [pushState was made for HTMLDecor](http://meekostuff.net/blog/pushState-was-made-for-HTMLDecor/)

Also make sure you check the [wiki](https://github.com/meekostuff/HTMLDecor/wiki).


Installation
------------

1. Copy or clone the HTMLDecor project files to a directory on your server, say 
	
		/path/to/HTMLDecor/

2. Open a browser and navigate to the following page
	
		http://your.domain.com/path/to/HTMLDecor/test/normal.html
	
	Visually inspect the displayed page for the following possible failures:
	
	- boxes with **red** background or borders. 
	- boxes that claim to be styled with colored borders but just have the default border. 
	
3. Source the HTMLDecor boot-script into your pages with this line in the `` of each page 
	
		``
		
	The boot-script 
	- MUST be in the `` of the page
	- MUST NOT have `@async` or `@defer`
	- SHOULD be before any stylesheets - `` or `
	
	
		
This fallback content will be removed from the page
#mk_content in page
This content is styled by the decor stylesheet
This content is styled by the page stylesheet
This fallback content will be removed from the page
Create the decor document (decor.html). This is a normal page of HTML that, when viewed in the browser, will appear as the final page without the page specific content.
#header in decor
#mk_main in decor
#mk_content in decor: This will be replaced by #mk_content from the page
#footer in decor
When page.html is loaded into the browser, HTMLDecor will merge decor.html into it, following these steps: 1. Set the visibility of the page to "hidden". \* 2. Detect the first ``, fully resolve the @href and use as the decor URL. 3. Load the decor URL into an iframe. 4. Fully resolve URLs for all scripts, images and links in the decor page. 5. Insert `
#header in decor
#mk_main in decor
#mk_content in page
This content is styled by the decor stylesheet
This content is styled by the page stylesheet
#footer in decor
Fallbacks --------- Sometimes HTMLDecor will not be able to apply the decor document to the page. This can occur because - Javascript is disabled - the HTMLDecor script failed to download - HTMLDecor is configured to NOT autostart - the decor document failed to download In this scenario you would like the page to have some basic styling and auxiliary content - something that can be dispensed with when HTMLDecor runs. ### Stylesheets Any `` or ` **NOTE:** this is done in the default `config.js`. If you want to remove or modify this behavior then do so in your site-specific `config.js`. ### Auxiliary content Children of `` which have no `@id`, or which have `@id` that cannot be found in the decor document will be removed from the page before the decor is applied, e.g.
This irrelevant content will be DEFINITELY REMOVED from the page because it has no @id
This content will be REMOVED from the page assuming the decor has no element with matching @id
This content will be RETAINED in the page assuming the decor has an element with matching @id
PushState Assisted Navigation ----------------------------- If `history.pushState` is available then HTMLDecor will conditionally over-ride the default browser behavior when hyperlinks are clicked. If the @href of the hyperlink is a document that specifies the same decor as the current page then it can be merged into the current page in a _similar_ way to the startup merging of decor and document. Some hyperlinks are not appropriate for this and are ignored by HTMLDecor: - hyperlinks to pages on other sites - hyperlinks with a different protocol, e.g. `javascript:...`, `ftp:` - hyperlinks that target a different window or iframe, e.g. ... - anchor hyperlinks - `` That leaves hyperlinks to other pages within the same site. If a decor lookup function has been registered then HTMLDecor queries what the decor of the hyperlinked page would be. If it is the same as the current decor then the page is downloaded and used to replace the real content of the current page. Otherwise normal browser navigation to the next page is triggered. **Note** that the HTMLDecor `click` handling can always be prevented by calling `event.preventDefault()`. "PushState Assisted Navigation" (PAN) may sometimes be referred to as panning, as in [camera panning](http://en.wikipedia.org/Panning_\(camera\)). ### Page Transition Animation To enable author supplied animation of page transitions, HTMLDecor provides the `Meeko.panner.config()` method. You could use it by placing something like the following in your **decor document** Meeko.panner.config({ duration: 0, // minimum time (ms) between paging start and end. nodeRemoved: { before: hide, // handler for before a content node leaves the page. Called at start of transition. after: show // handler for after a content node leaves the page. Cannot be called before duration has expired. }, nodeInserted: { before: hide, // handler for before a node enters the page, after the new url has been downloaded. after: show // handler for after a node enters the page. Called after a delay to allow styles set by `before` to be applied. }, pageOut: { before: noop, after: noop }, pageIn: { before: noop, // indicates that the decor is ready for content to be placed. This would allow decor to be mutated in url dependent way after: noop // the equivalent of `window.onload` in non-pushstate enabled environments. } }); function hide(msg) { msg.node.setAttribute("hidden", "hidden"); } function show(msg) { msg.node.removeAttribute("hidden"); } function noop() {} These are actually the options set by the default `config.js`, so there's no need to repeat these settings. The method can be called at anytime. Key / value pairs in the passed options object overwrite the matching previous settings. **NOTE** There is not always a notification **after** `pageOut`. For instance, if the next page is ready before the transition duration has expired then the new nodes replace the old nodes directly, rather than transitioning through the decor placeholders. **Example:** A simple way to achieve a fade-out / fade-in effect on page transition is to use the following in the decor document: **Example:** If your pages rely on `@class` on the `` or `` elements, the following will install them in the view-document when the page is panned in: ### Waiting Indicators If a new page takes longer than one second to load, the user may wonder if the loading has stalled. In this case a waiting indicator is typically used to reassure the user that the page is still loading. HTMLDecor provides a simple way to do this - when the `duration` has expired (and the next page still hasn't loaded) the decor document is used as the waiting page. ### Manual handling You can stop HTMLDecor handling hyperlink clicks by calling `event.preventDefault()` in a click handler, e.g. document.onclick = function(event) { event.preventDefault(); } You can also request HTMLDecor to navigate manually to a new URL by the following: Meeko.panner.assign(newURL) or with `history.replaceState()` behavior: Meeko.panner.replace(newURL) `
` handling ----------------- HTMLDecor ONLY handles forms where `@method="GET"`. All other forms are NOT handled, which means the native browser behavior will apply unless external code prevents the default-action and implements a different behavior. You are encouraged to handle other forms in a site-specific manner. ### @method = GET The form's `@action` and input values are processed to generate a query URL which is then used to perform pushState assisted navigaion. This mimics standard browser behavior. `` This dynamic script insertion is referred to as **enabling** in the following rules. - Scripts in the `` of the decor are **enabled** AFTER all the content in the `` of the decor is MERGED WITH the page. - Scripts in the `` of the decor are **enabled** AFTER all the content in the `` of the decor is INSERTED INTO the page, but BEFORE the page content is MERGED WITH the decor. - When panning occurs, scripts in the `` of the next page are **enabled** AFTER all the content in the `` of the next page is MERGED WITH the page. Scripts in the `` of the next page are **enabled** AFTER the content in the `` of the next page is MERGED WITH the page. **RECOMMENDATION:** You do not need and SHOULD NOT have scripts in any page (other than the decor document). Capturing --------- The **capturing** [boot option](#boot-options) prevents normal browser parsing of the *landing page*. This allows HTMLDecor to manage parsing in the same way that AJAXed pages are handled. The main benefits of this would be: - normalizing landing-page content occurs before the content is rendered, and - because `` and `` resources aren't automatically downloaded they can be changed (or removed) with no penalty. The drawbacks are: - parsing and displaying of content doesn't begin until the landing-page has fully down-loaded. On long pages over slow networks this will have quite a noticeable delay before any content is viewable. The article "[Capturing - Improving Performance of the Adaptive Web](https://hacks.mozilla.org/2013/03/capturing-improving-performance-of-the-adaptive-web/)" provides a short description and discussion of this approach. ### Restrictions 1. The boot-script must be within - or before - ``. 2. The boot-script must be the first ` 5. Make sure to test the modifications. You could symlink to the test directory from the root directory ln -s path/to/HTMLDecor/test then navigate in the browser to http://your.domain.com/test/normal.html Now you have a simple setup allowing you to: - modify your options without affecting the HTMLDecor installation, and - update HTMLDecor without overwriting your options. When you want to: + modify options - edit your copy of `options.js` - repeat step 3 to rebuild your boot-script + update HTMLDecor - overwrite the HTMLDecor directory with the latest version - repeat step 3 + minify HTMLDecor.js - minify HTMLDecor.js to HTMLDecor.min.js in the /path/to/HTMLDecor directory - change `htmldecor_script` to `/path/to/HTMLDecor/HTMLDecor.min.js` in your copy of the `options.js` file - repeat step 3 + minify boot.js - minify boot.js to boot.min.js in the /path/to/HTMLDecor directory - repeat step 3 with `path/to/HTMLDecor/boot.min.js` ### Boot options These options aren't specifically related to the operation of HTMLDecor. The boot-script has the following options (default values in **bold**). - htmldecor_script: **"{bootscriptdir}HTMLDecor.js"** - log_level: "none", "error", **"warn"**, "info", "debug" - polling_interval: **50** (milliseconds) - autostart: false, **true** - capturing: **false**, true, "strict" - hidden_timeout: **3000** (milliseconds) - html5\_block\_elements: **"article aside figcaption figure footer header hgroup main nav section"** - html5\_inline\_elements: **"abbr mark output time audio video picture"** - config_script: **"{bootscriptdir}config.js"** Sources for options are detailed below. #### From `Meeko.options` **NOTE** this is how options are set in `options.js`. Options can be **preset** by script, like this: This tells HTMLDecor to - log 'info', 'warn' and 'error' messages - prevent automatic startup, and - when a manual start is requested to hide the page until all decor-resources are loaded *or* 1000 milliseconds (1 second) have elapsed, whichever comes *first*. If autostart is turned off, HTMLDecor can be manually started by calling `Meeko.decor.start()`. #### From localStorage and sessionStorage When debugging a page you probably don't want to modify the page source to change HTMLDecor options, especially as you may have to change them back after you've found the problem. For this reason HTMLDecor reads `sessionStorage` and `localStorage` at startup, looking for config options. `sessionStorage` options override those found in `localStorage`, which in turn override those in data-attributes. Config options are read from JSON stored in the `Meeko.options` key. Thus the following would prevent `autostart` and turn on `debug` logging. sessionStorage.setItem('Meeko.options', JSON.stringify({ autostart: false, log_level: "debug" }) ); _Note_ that the page would require a refresh after these settings were made. ### HTMLDecor configuration There are two aspects of HTMLDecor: 1. Decoration - the wrapping of the primary content of the page with site decor 2. Panning - replacing the primary content of the page while retaining the same decor These aspects are opposite in purpose, but similar in operation. In particular, they both involve: - downloading of external content - normalizing this content to prepare for HTMLDecor processing - notifications of content insertion / removal, etc ### Decorator engine Options for the decorator are stored in `Meeko.decor.options`, which can be accessed directly or by calling Meeko.decor.config(options); where `options` is an object containing key / value pairs that will overwrite current values. Configuration should be done before HTMLDecor starts. This can be achieved by editing the site-specific `config.js` created during [Preparation](#preparation). Usually you only want to configure how HTMLDecor determines the appropriate decor-document for a page. Do this by providing one of the following options: - **`detect(doc)`** MUST return the decor-URL by inspecting the current page when HTMLDecor starts (this doesn't allow panning) - **`lookup(url)`** MUST return the decor-URL for any URL in the site, either the current `document.URL`, or the URL of a different page that is to be panned in. `lookup(url)` is the recommended option. `detect(doc)` is mainly provided for backwards compatibility, as can be seen in the default `config.js` script. **TODO:** `request`, `normalize`, notifications ### Panner engine Options for the panner are stored in `Meeko.panner.options`, which can be accessed directly or by calling Meeko.panner.config(options); where `options` is an object containing key / value pairs that will overwrite current values. Typically you only want to configure panner animation options. These would be set in the decor-document, as dealt with in [Page Transition Animation](#page-transition-animation). All other configuration should be done before HTMLDecor starts. This can be achieved by editing the site-specific `config.js` created during [Preparation](#preparation). #### Pre-decorated pages Pages on your site may not be in the format that HTMLDecor and your decor-document are expecting. The most likely scenario for this is that your primary content containers are not direct children of the ``, or they do not have @id. In this case you need to provide a `normalize(doc)` function which will manipulate the DOM of `doc` into the appropriate format, e.g. Meeko.panner.config({ normalize: function(doc) { var content = doc.getElementsByTagName('main')[0]; content.id = 'mk_content'; doc.body.innerHTML = ''; doc.body.appendChild(content); } }); **NOTE:** configuring the `normalize` option prevents initial page decoration until the `DOMContentLoaded` event (or safest equivalent). #### Non-HTML payloads You can also make your landing-page download as HTML and thereafter request, say JSON, and build the primary-content HTML in the browser. Do this by providing a `request(url, data, details, callback)` function, where + **method** is the HTTP method for the request, which will be 'GET' or 'POST'. + **url** is the URL of the page to be panned in + **data** is any form data (**WARNING** not implemented yet) + **details** is an object containing at least the `URL` and `method` + **callback** is an object with `complete(result)` and `error(err)` callback-methods An example of configuration might be Meeko.panner.config({ request: function(method, url, data, details, callback) { // assumes 'GET' if (!/GET/i.test(method)) throw "Only supporting GET requests"; var rq = new XMLHttpRequest; rq.open(method, url, true); rq.setRequestHeader('Accept', 'application/json'); rq.onreadystatechange = onchange; rq.send(); function onchange() { if (rq.readyState != 4) return; if (rq.status != 200) { callback.error(rq.status); return; } onload(); } function onload() { var json = JSON.parse(rq.responseText); var doc = document.implementation.createHTMLDocument(json.title); doc.body.innerHTML = processJSON(json); // your json-to-html converter callback.complete(doc); } } }); ### Bonus APIs HTMLDecor defines various utility classes and functions for internal use. Many of these are also available for external use if appropriate. The most useful of these are in the `Meeko.DOM` namespace, and include + `Meeko.DOM.URL` This provides overlapping functionality with the [proposed URL API](http://url.spec.whatwg.org/#api). `Meeko.DOM.URL(absoluteURL)` will return a URL object with the following (read-only) fields: - `href`, `protocol`, `host`, `hostname`, `port`, `pathname`, `search`, `hash` **(Standard)** - `origin`, `basepath`, `base`, `nosearch`, `nohash` **(Extensions)** The URL object also has the `resolve(relativeURL)` method which performs a fast conversion of a relative URL to absolute, using itself for the `baseURL`. + `Meeko.DOM.$id` This is short-hand for `document.getElementById` (typically aliased to `$id` in a code block) + `Meeko.DOM.$$` This is short-hand for `document.getElementsByTagName` (typically aliased to `$$` in a code block) Notes and Warnings ------------------ - HTMLDecor may not be compatible with IE behaviors, eg [CSS3 PIE](http://css3pie.com/). - The decor document is loaded via XMLHttpRequest(), parsed to disable scripts, then written into an iframe using `document.write()`. - unlike CSS, decor pages should be in the same domain as the content page otherwise the browsers cross-site restrictions will apply. Detection for this hasn't been implemented yet. - any stylesheets in the content document and with a title of "nodecor" will be deleted at the start of merging of the decor page. This allows for a fallback styling option of decor-less pages. For example, the following stylesheets would be removed: `` AND `` - in most current browsers, elements from the content can be moved into the decor *while the element is still loading*. On IE6,7,8 this will throw an error, so for those browsers the decor is inserted and elements moved only after the DOM has fully loaded. - the configuration options and mechanism may change in future releases - URLs in `