This article needs to be updated.(January 2020) |
Unobtrusive JavaScript is a general approach to the use of JavaScript in web pages. Though the term is not formally defined, its basic principles are generally understood to include separation of functionality (the "behavior layer") from a Web page's structure/content and presentation,[1] and progressive enhancement to support user agents that may not support certain JavaScript functionality and users that have disabled JavaScript.[2]
The emergence of standards-compliant browsers, JavaScript frameworks, and high-quality debugging tools made organized, scalable JavaScript code possible, and the emergence of Ajax interfaces made it desirable. Whereas JavaScript was once reserved for relatively simple and non-critical tasks such as form validation and decorative novelties, it is now used to write large, complex codebases that are often part of a site's core functionality.
The concept of "unobtrusiveness" in relation to JavaScript programming was coined in 2002 by Stuart Langridge[3] in the article "Unobtrusive DHTML, and the power of unordered lists".[4] In the article Langridge argued for a way to keep all JavaScript code, including event handlers, outside of the HTML. Stuart Langridge has since expanded upon this thought in book[5] and article format.[6]
Other authors have tried to refine and define the essential elements of unobtrusiveness. David Flanagan's book JavaScript: The Definitive Guide said that while there is no specific formula, there are three main goals:
The Web Standards Project described four benefits of unobtrusive DOM scripting in their JavaScript Manifesto.
For the Paris Web Conference in 2007, Christian Heilmann identified seven rules of Unobtrusive JavaScript.[9]
Event
object that is passed to most event handlers.Traditionally, JavaScript was often placed inline together with an HTML document's markup. For example, the following is a typical way to register a JavaScript event handler in HTML:
<input type="text" name="date" onchange="validateDate()" />
The purpose of HTML markup is to describe a document's structure, not its programmatic behavior. Combining the two can negatively impact a site's maintainability, like combining content and presentation.[10] JavaScript behavior created and referenced in the HTML can be harder to use and maintain, for example when setting handlers for several events on a single element, when setting the same event handler on several elements, or when using event delegation.
The unobtrusive solution is to register the necessary event handlers programmatically, rather than inline. Rather than adding an onchange
attribute explicitly as above, the relevant element(s) are simply identified, for example by class
, id
or some other means in the markup:
<input type="text" name="date" id="date" />
A script that runs when the page is first loaded into the browser can then look for each relevant element and set it up accordingly:
window.addEventListener("DOMContentLoaded", function(event) {
document.getElementById('date').addEventListener("change", validateDate);
});
Unobtrusive JavaScript should add as little as possible to the global object or global namespace of the environment in which it runs. Other scripts may override any variable or function that is created in the global namespace, and this can lead to unexpected failures that are difficult to debug. JavaScript does not have a built-in explicit namespace mechanism, but the desired effects are easy to produce using the language's facilities. Flanagan suggests the use of the developer's own domain name, dotted segments reversed, as a single global name to publish that is very likely to be unique, in the style developed in the Java language.[11]
var org = org || {};
if (typeof org !== 'object') {
throw new Error("org already defined as non-object");
}
org.example = org.example || {};
if (typeof org.example !== 'object') {
throw new Error("org.example already defined as non-object");
}
While variables, functions and objects of all kinds can be further defined within such namespace objects, it is usually recommended to use closures within the namespace to further isolate what will become private variables and functions, as well as to export what will be the public interface of each module of functionality. The code above could be followed directly by the following, which uses an IIFE to establish its closure:[9]
org.example.Highlight = (function() {
// Define private data and functions
var highlightId = 'x';
function setHighlight(color) {
document.getElementById(highlightId).style.color = color;
}
// Return public pointers to functions or properties
// that are to be public.
return {
goGreen: function() { setHighlight('green'); },
goBlue: function() { setHighlight('blue'); }
}
}()); // End of closure
From any other module, these public methods could be invoked in either way as follows
org.example.Highlight.goBlue();
var h = org.example.Highlight;
h.goGreen();
In this way, each module-writer's code is contained in private or in a unique namespace and cannot interfere with or intrude upon any other code at any time.
Writing an event listener that detects the loading of the HTML page and then adds relevant listeners to other events on the page, as well as other behaviors as required, can solve the problem of separating JavaScript functionality from HTML markup. The use of client-side JavaScript libraries such as jQuery, MooTools or Prototype can simplify this process and help ensure that individual browser and browser version implementation details are hidden and catered for. Keeping most of the JavaScript out of the default namespace helps ensure that it is as unobtrusive as possible in that sense. A further criterion of unobtrusive JavaScript that is often cited is to ensure that added behavior degrades gracefully on those browsers with unexpected configurations, and those on which the user may have disabled JavaScript altogether.[7]
This requirement is a basic tenet of web accessibility, to ensure that JavaScript-enhanced websites are not only usable by people of all abilities and disabilities but that all users—whatever their computing platform—get equal access to all the site's information and functionality. Sometimes there is extra work involved in achieving this, but web accessibility is not an optional extra in many countries. For example, in the UK, the Equality Act 2010, while it does not refer explicitly to website accessibility, makes it illegal to discriminate against people with disabilities and applies to anyone providing any service in the public, private and voluntary sectors.[12] While a lot of effort may be put into designing and implementing a slick client-side user interface in unobtrusive JavaScript, it will not remain unobtrusive to a user without client-side scripting if they find that they cannot access published information. To meet this goal, it is often necessary to implement equivalent, albeit clunkier, server-side functionality that will be available without the use of JavaScript at all.
Take, for example, a webpage where thumbnail images need JavaScript behaviours so that full-size images will appear in front of the page when the mouse is rolled over them or they are clicked. First, server-side markup should ensure that the relevant full-size image is served to users without JavaScript who click on a thumbnail. In this case the basic HTML markup may look like the following, for each thumbnail:
<a href="fullsize-image-001.png" class="manual-link" title="Click for full-size image">
<img src="image-001-thumb.png" class="thumb" width="50" height="50" alt="Image 1 shows... etc">
</a>
This will work as it is without JavaScript. Unobtrusive JavaScript, in this case, during page-load, could find all the a
elements that have a class of manual-link
and remove them from the page DOM. It could then find all the images of class thumb
and attach an onmouseover
or an onclick
event handler that is specified in-line to provide the slick behaviour. For example, when invoked the event handler may send an Ajax request to the server for the full-size image, then add a div
to the page DOM invoking existing CSS so it appears in front of existing content, which itself may become partially greyed out. The div
will need a close button, perhaps a visual 'spinner' to show that data is loading, etc. Finally, when the Ajax data arrives, the handler hides the spinner and inserts the full-size image into the new div
for display.
This way, all the client-side functionality depends on the same JavaScript function. If that function succeeds, it begins by removing the basic, manual behavior, and goes on to add the client-side scripted behavior. If the script fails for whatever reason, the manual behavior remains in place and remains functional.
Though the essence of unobtrusive JavaScript is the concept of an added separate behavior layer, its advocates generally have subscribed to a number of related principles, such as:
By: Wikipedia.org
Edited: 2021-06-18 12:36:35
Source: Wikipedia.org