As JavaScript developers, we regularly forget that not everybody has a similar data as USA. It’s referred to as the curse of knowledge: once we’re associate expert on one thing, we have a tendency to cannot keep in mind however confused we have a tendency to felt as newbies. we have a tendency to overestimate what folks can notice simple. Therefore, we predict that requiring a bunch of JavaScript to initialize or piece the libraries we have a tendency to write is OK. Meanwhile, a number of our users struggle to use them, frantically repetition and pasting examples from the documentation, tweaking them indiscriminately till they work.
One in 2 folks that write hypertext mark-up language and CSS isn't comfy with JavaScript. One in two. Let that sink certain an instant.
As associate example, check out the subsequent code to initialize a jQuery UI autocomplete, taken from its documentation:
<div class="ui-widget">
<label for="tags">Tags: </label>
<input id="tags">
</div>
$( function() {
var availableTags = [
"ActionScript",
"AppleScript",
"Asp",
"BASIC",
"C"
];
$( "#tags" ).autocomplete({
source: availableTags
});
} );
This is straightforward, even for people that don’t recognize any JavaScript, right? Wrong. A non-programmer would have all forms of queries looking their head once seeing this instance within the documentation. “Where do I place this code?” “What area unit these braces, colons associated brackets?” “Do i want them?” “What do I do if my part doesn't have an ID?” and then on. Even this small snip of code needs individuals to grasp object literals, arrays, variables, strings, a way to get a relation to a DOM part, events, once the DOM is prepared and far a lot of. Things that appear trivial to programmers may be associate uphill battle to HTML authors with no JavaScript information.
Now take into account the equivalent declarative code from HTML5:
<div class="ui-widget">
<label for="tags">Tags: </label>
<input id="tags" list="languages">
<datalist id="languages">
<option>ActionScript</option>
<option>AppleScript</option>
<option>Asp</option>
<option>BASIC</option>
<option>C</option>
</datalist>
</div>
Not solely is that this abundant clearer to anyone World Health Organization will write hypertext mark-up language, it's even easier for programmers. we have a tendency to see that everything is about in one place, no have to be compelled to care concerning once to initialize, a way to get a respect to the component and the way to line stuff thereon. No have to be compelled to grasp that perform to decision to initialize or that arguments it accepts. And for a lot of advanced use cases, there's additionally a JavaScript API in situ that enables all of those attributes and components to be created dynamically. It follows one among the foremost basic API style principles: It makes straightforward} easy and therefore the advanced doable.
This brings U.S.A. to a crucial lesson concerning hypertext mark-up language APIs: they might profit not solely individuals with restricted JavaScript ability. For common tasks, even we, programmers, square measure usually wanting to sacrifice the flexibleness of programming for the convenience of declarative markup. However, we have a tendency to somehow forget this once writing a library of our own.
So, what's Associate in Nursing hypertext mark-up language API? in line with Wikipedia, Associate in Nursing API (or application programming interface) is “is a group of software definitions, protocols, and tools for building application computer code.” In Associate in Nursing hypertext mark-up language API, the definitions and protocols square measure within the hypertext mark-up language itself, and therefore the tools look in hypertext mark-up language for the configuration. hypertext mark-up language Apis typically accommodates bound category and attribute patterns that may be used on existing hypertext mark-up language. With net elements, even custom component names square measure game, and with the Shadow DOM, those will even have a whole internal structure that's hidden from the remainder of the page’s JavaScript or CSS. however this is often not a piece of writing concerning net elements; net Components provide a lot of power and choices to hypertext mark-up language API styleers; however the principles of excellent (HTML) API design square measure an equivalent.
HTML Apis improve collaboration between designers and developers, carry some work from the shoulders of the latter, and change designers to make abundant higher-fidelity mockups. as well as Associate in Nursing hypertext mark-up language API in your library doesn't simply build the community a lot of inclusive , it additionally ultimately comes back to profit you, the engineer.
Not each library desires Associate in Nursing hypertext mark-up language API. hypertext mark-up language Apis square measure largely helpful in libraries that change UI components like galleries, drag-and-drop, accordions, tabs, carousels, etc. As a rule of thumb, if a non-programmer cannot perceive what your library will, then your library doesn’t would like Associate in Nursing hypertext mark-up language API. as an example, libraries that modify or facilitate to prepare code don't would like Associate in Nursing hypertext mark-up language API. What quite hypertext mark-up language API would Associate in Nursing MVC framework or a DOM helper library even have?
So far, we've mentioned what Associate in Nursing hypertext mark-up language API is, why it's helpful and once it's required. the remainder of this text is concerning a way to style an honest one.
Init Selector
With a JavaScript API, formatting is strictly controlled by the library’s user: as a result of they need to manually decision a operate or produce Associate in Nursing object, they management exactly once it runs and on what. With Associate in Nursing hypertext markup language API, we've got to create that alternative for them, and make certain to not get within the method of the facility users World Health Organization can still use JavaScript and need full management.
The common thanks to resolve the stress between these 2 use cases is to solely auto-initialize components that match a given selector, sometimes a particular category. Awesomplete follows this approach, solely finding out input components with class="awesomplete".
In some cases, creating auto-initialization straightforward is additional vital than creating opt-in specific. this can be common once your library must run on plenty of components, and once avoiding having to manually add a category to each single one is additional vital than creating opt-in specific. for instance, Prism mechanically highlights any <code> part that contains a language-xxx category (which is what the HTML5 specification recommends for specifying the language of a code snippet) or that's within a component that will. this can be as a result of it may be enclosed during a web log with plenty of code snippets, and having to travel back and add a category to each single one in every of them would be an enormous problem.
In cases wherever the init selector is employed terribly munificently, a decent follow is permit|to permit} customization of it or allow opting-out of auto-initialization altogether. for instance, elastic autosizes each <input>, <select> and <textarea> by default, however permits customization of its init selector to one thing additional specific via a data-stretchy-filter attribute. Prism supports a data-manual attribute on its <script> part to utterly disable automatic formatting. a decent follow is to permit this feature to be set via either hypertext markup language or JavaScript, to accommodate each kinds of library users.
Minimize Init Markup
So, for each component the init selector matches, your library wants a wrapper around it, 3 buttons within it and 2 adjacent divs? No downside, however generate them yourself. this type of grunt work is healthier suited to machines, not humans. don't expect that everybody exploitation your library is additionally exploitation some variety of templating system: many of us area unit still hand-crafting markup and realize build systems too sophisticated. build their lives easier.
This additionally minimizes error conditions: What if a user includes the category that you simply expect for initialisation however not all of the markup you need? once there's no further markup to feature, no such errors area unit potential.
There is one exception to the present rule: swish degradation and progressive sweetening. for instance, embedding a tweet involves lots of markup, despite the fact that one component with data-* attributes for all the choices would answer. this can be done in order that the tweet is legible even before the JavaScript hundreds or runs. a decent rule of thumb is to raise yourself, will the additional markup provide a profit to the tip user even while not JavaScript? If thus, then requiring it's OK. If not, then generate it together with your library.
There is additionally the classic tension between easy use and customization: Generating all of the markup for the library’s user is less complicated for them, however exploit them to put in writing it offers them additional flexibility. Flexibility is nice after you want it, however annoying after you don’t, and you continue to ought to set everything manually. To balance these 2 wants, you'll generate the markup you would like if it doesn’t exist already. for instance, suppose you wrap all .foo parts with a .foo-container element? 1st, check whether or not the parent — or, better yet, any ascendant, via component.closest(".foo-container") — of your .foo component already has the foo-container category, and if so, use that rather than making a brand new component.
Settings
Typically, settings ought to be provided via data-* attributes on the relevant part. If your library adds plenty of attributes, then you may wish to namespace them to stop collisions with alternative libraries, like data-foo-* (where foo could be a one-to-three letter prefix supported your library’s name). If that’s too long, you'll use foo-*, however bear in mind that this may break hypertext markup language validation and may place a number of the a lot of diligent hypertext markup language authors off your library owing to it. Ideally, you ought to support each, if it won’t bloat your code an excessive amount of. None of the choices here area unit ideal, thus there's associate current discussion within the WHATWG concerning whether or not to decriminalise such prefixes for custom attributes.
Follow the conventions of hypertext markup language the maximum amount as potential. for instance, if you employ associate attribute for a Boolean setting, its presence means that true despite the worth, and its absence means that false. don't expect things like data-foo="true" or data-foo="false" instead. Sure, ARIA will that, however if ARIA jumped off a formation, would you are doing it, too?
When the setting could be a Boolean, you'll additionally use categories. Typically, their linguistics area unit almost like Boolean attributes: The presence of the category means that true, and also the absence means that false. If you wish the alternative, you'll be able to use a no- prefix (for example, no-line-numbers). confine mind that category names area unit used quite data-* attributes, thus there's a larger chance of collision with the user’s existing category names. you'll think about prefixing your categories with a prefix like foo- to stop that. Another danger with category names is that a future supporter may notice that they're not utilized in the CSS and take away them.
When you have a gaggle of connected Boolean settings, victimisation one space-separated attribute may be higher than victimisation several separate attributes or categories. for instance, <div data-permissions="read add edit delete save logout>" is healthier than <div data-read data-add data-edit data-delete data-save data-logout">, and <div class="read add edit delete save logout"> would doubtless cause plenty of collisions. you'll be able to then target individual ones via the ~= attribute selector. for instance, element.matches("[data-permissions~=read]") checks whether or not part has the scan permission.
If the sort of a setting is associate array or object, then you'll be able to use a data-* attribute that links to a different part. for instance, scrutinize however HTML5 will autocomplete: as a result of autocomplete needs an inventory of suggestions, you employ associate attribute to link to a <datalist> part containing these suggestions via its ID.
This is a degree once following hypertext markup language conventions becomes painful: In hypertext markup language, linking {to associateother|to a different} part in an attribute is often done by referencing its ID (think of <label for="…">). However, this is often rather limiting: It’s such a lot a lot of convenient to permit selectors or perhaps nesting if it is sensible. What you accompany can for the most part rely on your use case. simply confine mind that, whereas consistency is very important, usability is our goal here.
It’s OK if not each single setting is out there via hypertext markup language. Settings whose values area unit functions will keep in JavaScript and be thought-about “advanced customization.” think about Awesomplete: All numerical, boolean, string and object settings area unit accessible as data-* attributes (list, minChars, maxItems, autoFirst). All perform settings area unit solely accessible in JavaScript (filter, sort, item, replace, data). If somebody is ready to write down a JavaScript perform to assemble your library, then they will use the JavaScript API.
Regular expressions (regex) area unit alittle of a grey area: usually, solely programmers recognize regular expressions (and even programmers have bother with them!); thus, initially look there doesn’t appear to be any purpose in together with settings with regex values in your hypertext markup language API. However, HTML5 did embody such a setting (<input pattern="regex">), and that i believe it absolutely was quite winning, as a result of non-programmers will research their use case during a regex directory and replica and paste.
Inheritance
If your UI library goes to be used once or doubly on every page, then inheritance won’t matter a lot of. However, if it may well be applied to multiple parts, then configuring constant settings on every one of them via categories or attributes would be painful. bear in mind that not everybody uses a build system, particularly non-developers. In these cases, it would be helpful to outline that settings is inheritable from relative parts, in order that multiple instances is mass-configured.
Take Prism, a well-liked syntax-highlighting library, used here on Smashing Magazine yet. The highlight language is designed via a category of the shape language-xxx. Yes, this goes against the rules we tend to mentioned within the previous section, however this was a acutely aware call as a result of the HTML5 specification recommends this for specifying the language of a code piece. On a page with multiple code snippets (think of however usually a journal post concerning code uses inline <code> elements!), specifying the cryptography language on every <code> part would become extraordinarily tedious. To mitigate this pain, Prism supports inheritance of those categoryes: If a <code> part doesn't have a language-xxx class of its own, then the one in every of its nearest relative that will is employed. this permits users to line the cryptography language globally (by putt the category on the <body> or <html> elements) or by section, and override it solely on parts or sections with a special language.
Now that CSS variables square measure supported by each browser, they're a decent candidate for such settings: they're inheritable by default and may be set inline via the design attribute, via CSS or via JavaScript. In your code, you get them via getComputedStyle(element).getPropertyValue("--variablename"). Besides browser support, their main draw back is that developers don't seem to be nonetheless accustomed them, however that's ever-changing. Also, you can't monitor changes to them via MutationObserver, such as you will for parts and attributes.
Global Settings
Most UI libraries have 2 teams of settings: settings that customise however every instance of the device behaves, and international settings that customise however the library behaves. So far, we've got in the main mentioned the previous, therefore you would possibly be curious what's a decent place for these international settings.
One candidate is that the <script> component that has your library. you'll get this via document.currentScript, and it's excellent browser support. The advantage of this can be that it’s unambiguous what these settings area unit for, therefore their names are often shorter (for example, data-filter, rather than data-stretchy-filter).
However, the <script> component mustn't be the sole place you choose up these settings from, as a result of some users could also be mistreatment your library during a CMS that doesn't permit them to customise <script> parts. you may conjointly search for the setting on the <html> and <body> parts or maybe anyplace, as long as you have got a clearly declared policy concerning that price wins once there area unit duplicates. (The 1st one? The last one? one thing else?)
Documentation
So, you’ve taken care to style a pleasant declarative API for your library. Well done! but, if all of your documentation is written as if the user understands JavaScript, few are able to use it. I bear in mind seeing a cool library for toggling the show of parts supported the computer address, via hypertext markup language attributes on the weather to be toggled. However, its nice hypertext markup language API couldn't be utilized by the individuals it targeted as a result of the whole documentation was tormented by JavaScript references. The terribly initial example started with, “This is resembling location.href.match(/foo/).” What likelihood will a non-programmer got to perceive this?
Also, bear in mind that a lot of of those individuals don't speak any programing language, not simply JavaScript. don't refer models, views, controllers or alternative software system engineering ideas in text that you just expect them to browse and perceive. All you may bring home the bacon is confusing them and turning them away.
Of course, you must document the JavaScript components of your API furthermore. you may do this in associate “Advanced usage” section. However, if you begin your documentation with references to JavaScript objects and functions or software system engineering ideas, then you’re primarily telling non-programmers that this library isn't for them, thereby excluding an oversized portion of your potential users. Sadly, most documentation for libraries with hypertext markup language arthropod genus suffers from these problems, as a result of hypertext markup language arthropod genus area unit usually seen as a cutoff for programmers, not as the way for non-programmers to use these libraries. Hopefully, this may modification within the future.
What About Web Components?
In the close to future, the net elements quartet of specifications can revolutionize hypertext mark-up language Apis. The <template> part can change authors to supply scripts with partial inert markup. Custom components can change way more elegant init markup that resembles native hypertext mark-up language. hypertext mark-up language imports can change authors to incorporate only 1 file, rather than 3 vogue sheets, 5 scripts and 10 templates (if Mozilla gets its act along and stops thinking that ES6 modules area unit a competitive technology). The Shadow DOM can change your library to own advanced DOM structures that area unit properly encapsulated which don't interfere with the user’s own markup.
However,
<template>
aside, browser support for the other three is currently limited.. So, they need giant polyfills, that makes them less engaging for library use. However, it’s one thing to stay on your radiolocation for the close to future.MarkApp: A List Of Libraries With HTML APIs
If you’ve followed the recommendation during this article, then congratulations on creating the net a more robust, a lot of comprehensive area to be inventive in! I try and maintain an inventory of all libraries that have HTML Apis on MarkApp. Send a pull request and add yours, too!