unobtrusive JavaScript is a design concept that removes JavaScript from the HTML structure, avoiding the inclusion of a bunch of onchange, onclick in HTML tags ... And so on, to Mount JavaScript events, to separate HTML from JavaScript, and to differentiate the functions and responsibilities according to the MVC principle, so that the HTML becomes structured and easy to read.
unobtrusive JavaScript is a common way to use JavaScript in Web pages. The name is not formally defined and its basic principles include:
- The behavior layer and the performance layer are separated from each other;
- is the best practice to solve traditional JavaScript programming problems (inconsistent browser rendering, lack of extensibility);
- Provides incremental support for user agents (usually browsers) that may not support JavaScript advanced features
--------------------------------------------------------
Seven guidelines for non-intrusive javascript
English Original: The Seven rules of unobtrusive JavaScript
Original Chris Heilmann
After years of development, teaching, and writing unobtrusive JavaScript, I found some of the following guidelines. I hope they can help you understand why it's better to design and execute JavaScript this way. These rules have helped me deliver products faster, and the quality of the products is higher and easier to maintain.
1. Don't make any assumptions
(JavaScript is an unreliable assistant)
One of the most important features of a potentially unobtrusive JavaScript is that you want to stop any assumptions:
* Don't assume that JavaScript is available, you'd better think it's very likely to be unavailable, rather than rely on it directly.
* Do not assume that the browser supports them until you have tested and verified that some methods and properties can be used.
* Don't assume that the HTML code is as correct as you think, check it every time, and don't do anything when it's not available.
* Make JavaScript function independent of the input device
* Remember that other scripts may affect the functionality of your JavaScript, so make sure that your scripts are scoped as securely as possible.
The first thing to consider before you start designing your script is to check the HTML code you want to script and see what you can do to help you achieve your goals.
2. Identify hooks and node relationships
(HTML is the cornerstone of the script)
Before you start writing scripts, take a look at the HTML you want to write JavaScript for. If HTML is not organized or unknown, then you can hardly have a good scripting scenario--it's likely that you'll either create too many tags with javascript, or your app will be too dependent on JavaScript.
There are some things to consider in HTML, which are hooks and node relationships.
<1>. HTML Hooks
The first and most important hooks of HTML are the IDs, and the IDs can be accessed--getelementbyid by the fastest Dom method. If all the IDs in a valid HTML document are unique (there is a bug in IE about name and ID, but some good class libraries solve the problem), using IDs is safe and easy to test.
Other hooks are HTML elements and CSS classes, HTML elements can be accessed through the getElementsByTagName method, and in most browsers, CSS classes are not accessible through native DOM methods. However, there are many external class libraries that provide access to CSS class names (similar to getelementsbyclassname).
<2>. HTML node Relationships
Another interesting thing about HTML is the relationship between tags, and consider the following questions:
* What is the easiest way to reach the target node with minimal DOM traversal?
* By modifying what tags, you can access as much as possible to the child nodes that need to be modified?
* What properties or information can be used to reach another element for a given element?
Traversing the DOM is resource-intensive and slow, which is why you should try to do this with the technology already in use in your browser.
3. Turn the traversal over to the experts
(CSS, faster traversal of the DOM)
It's interesting that the DOM script and the use of methods or properties (getElementsByTagName, nextSibling, PreviousSibling, ParentNode, and others) to traverse the DOM seem to confuse a lot of people. And interestingly, we've already done it through another kind of technology--css--.
CSS is a technique that uses CSS selectors to iterate through the DOM to access the target elements and change their visual properties. A complex JavaScript that uses the DOM can be replaced with a CSS selector:
Java code
- var n = document.getElementById (' nav ');
- if (n) {
- var as = N.getelementsbytagname (' a ');
- if (As.length > 0) {
- for (var i=0;as[i];i++) {
- As[i].style.color = ' #369′;
- As[i].style.textdecoration = ' None ';
- }
- }
- }
- /* The following code is the same as the above function */
- #nav a{
- color:#369;
- Text-decoration:none;
- }
This is a very powerful technique to take advantage of. You can do this by dynamically adding a class to the upper-level elements of the DOM or changing the element ID. If you add a CSS class to the body of the document using the DOM, it is easy for designers to define both static and dynamic versions of the document.
Java code
- Javascript:
- var dynamicclass = ' js ';
- var B = document.body;
- B.classname = B.classname? B.classname + ' js ': ' JS ';
- Css:
- /* Static version */
- #nav {
- ....
- }
- /* Dynamic version */
- Body.js #nav {
- ....
- }
4. Understanding Browsers and Users
(Create what you need in an existing usage pattern)
An important part of the unobtrusive JavaScript is to understand how the browser works (especially how the browser crashes) and what the user expects. You can easily use JavaScript to create a completely different interface, regardless of the browser. Drag-and-drop interfaces, folding areas, scrollbars, and sliders can all be created using JavaScript, but this is not a simple technical question, you need to think about the following questions:
* Can this new interface be independent of the input device? If not, then what can you rely on?
* Does the new interface I create follow the guidelines for browsers or other rich interfaces (can you switch directly from the multi-level menu with the mouse?). Or do you need to use the TAB key? )
* What functions do I need to provide but this feature is dependent on javascript?
The last question is not a problem, because you can use the DOM to create HTML in thin air if you need it. An example of this is the "print" link, because the browser does not provide a non-JavaScript print document feature, so you need to use the DOM to create such links. Similarly, a clickable title bar that implements the expansion and contraction of the content module also belongs to this case. The title bar cannot be activated by the keyboard, but the link can. So in order to create a clickable title bar you need to use JavaScript to add the link, and then all users using the keyboard can shrink and expand the content module.
An excellent resource for solving this kind of problem is the design pattern library. As for knowing what is in the browser independent of the input device, it depends on the accumulation of experience. The first thing you need to understand is the event handling mechanism.
5. Understanding Events
(Event handling can cause changes)
Event handling is the second step toward a non-intrusive javascript. The point is not to let everything become draggable, clickable, or inline, but to understand that event handling is something that can be completely detached. We have separated html,css from JavaScript, but we have not gone very far in the separation of event processing.
The event handler listens for changes in the elements that occur in the document, and if an event occurs, the processor finds a wonderful object (typically a parameter called E) that tells the element what is happening and what it can do with it.
The real interesting thing about most event handling is that it happens not only on the element you want to access, but also on all elements at a higher level in the DOM (but not all events are the exception of the focus and Blur events). For example, with this feature you can add only one event handler for a navigation list and use the event handler's method to get the element that really triggered the event. This technique is called event delegation, and it has several benefits:
* You just need to check if an element exists, without checking each element
* You can dynamically add or remove child nodes without deleting the appropriate event handlers
* You can respond to the same events on different elements
Another thing to keep in mind is that you can stop the event when it propagates to the parent element and you can override the default behavior of HTML elements (such as links). However, sometimes this is not a good idea, because browsers give HTML elements that behave for a reason. For example, a link might point to a target within a page and not modify it to ensure that the user can bookmark the current script state of the page.
6. For the sake of others
(namespaces, scopes, and schemas)
Your code is almost never the only script code in the document. So it is important to ensure that there are no global functions or global variables that can be overridden by other scripts in your code. There are some available modes to avoid this problem, the most basic thing is to use the VAR keyword to initialize all the variables. Let's say we've written the following script:
Java code
- var nav = document.getElementById (' nav ');
- function init () {
- Do stuff
- }
- Function Show () {
- Do stuff
- }
- function Reset () {
- Do stuff
- }
The above code contains a global variable called NAV and three functions named Init,show and reset respectively. These functions all have access to the NAV variable and can be accessed from each other by the function name:
Java code
- var nav = document.getElementById (' nav ');
- function init () {
- Show ();
- if (nav.classname = = = ' show ') {
- Reset ();
- }
- Do stuff
- }
- Function Show () {
- var c = nav.classname;
- Do stuff
- }
- function Reset () {
- Do stuff
- }
You can encapsulate the code in an object to avoid the type of global encoding above, so that you can turn the function into a method in the object and change the global variable into an attribute in the object. You need to use the name + Colon method to define methods and properties, and you need to add a comma after each property or method as a separator.
Java code
- var myScript = {
- Nav:document.getElementById (' nav '),
- Init:function () {
- Do stuff
- },
- Show:function () {
- Do stuff
- },
- Reset:function () {
- Do stuff
- }
- }
All methods and properties can be accessed externally and internally by using the class name + dot operator.
Java code
- var myscript = {
- nav:document.getElementById ( ' Nav '),
- init:function () {
- myscript.show ();
- if ( Myscript.nav.classname === ' show ') {
- Myscript.reset ();
- }
- // do stuff
- },
- show:function () {
- var c = myscript.nav.classname;
- //&NBSP;DO&NBSP;STUFF&NBSP;&NBSP;
- },
- reset:function () {
- // do stuff
- }
- }
The downside of this pattern is that every time you access another method or property from one method, you must precede the object's name, and everything in the object can be accessed externally. If you just want some of the code to be accessed by other scripts in the document, consider the following module mode:
Java code
- var myScript = function () {
- These are private methods and properties
- var nav = document.getElementById (' nav ');
- function init () {
- Do stuff
- }
- Function Show () {
- Do stuff
- }
- function Reset () {
- Do stuff
- }
- Public methods and properties are wrapped in a return statement using object syntax
- return {
- Public:function () {
- },
- Foo:' bar '
- }
- }();
You can access the returned public properties and methods in the same way as the previous code, which you can access in this example: Myscript.public () and Myscript.foo. But here's one more uncomfortable: when you want to access public methods from outside or from inside a private method, write a lengthy name (the name of the object can be very long). To avoid this, you need to define them as private and return only one alias in the return statement:
Java code
- var myscript = function () {
- // these are private methods and property
- Var nav = document.getelementbyid,
- Function init () {
- //&NBSP;DO&NBSP;STUFF&NBSP;&NBSP;
- }
- function show () {
- // do stuff
- // do stuff
- }
- Function reset () {
- // do stuff
- }
- var foo = ' bar ';
- function public () {
-
- }
Only returns pointers to the private methods and properties that you want to access
Java code
- return {
- Public: Public,
- Foo:foo
- }
- }();
This guarantees code style consistency, and you can use a shorter alias to access its methods or properties.
If you do not want to expose any methods or properties to the outside, you can encapsulate all the code in an anonymous method and execute it immediately after its definition:
Java code
- (function () {
- // these are all private methods and properties
- var nav = document.getelementbyid (
- function init () {
- // do stuff
- Show (); // here does not require the class name prefix
- }
- function show () {
- // do stuff
- }
- Function reset () {
- //&NBSP;DO&NBSP;STUFF&NBSP;&NBSP;
- }
- }) ();
This pattern is good for code modules that execute only once and are not dependent on other functions.
By following the rules above, your code works better for the user, and it also allows your code to run better on the machine and live in harmony with the code of other developers. However, there is another group that needs to be taken into account.
7. Consider for the developer who took over
(Make maintenance easier)
The final step in making your script truly unobtrusive is to examine it carefully after writing the code, and take care of the developer who takes over your code once the script is online. Consider the following question:
* Are all variables and function names reasonable and easy to understand?
* Has the code been properly organized? Is it smooth from beginning to end?
* All the dependencies are obvious?
* Have you added comments in places that might be confusing?
The most important thing to realize is that the HTML and CSS code in the document is more likely to be changed than JavaScript (because they are responsible for visual effects). So don't include any class and ID in the script code that you can see for the end user, but rather separate them into an object that holds the configuration information.
Java code
- MyScript = function () {
- var config = {
- Navigationid:' nav ',
- Visibleclass:' show '
- };
- var nav = document.getElementById (Config.navigationid);
- function init () {
- Show ();
- if (nav.classname = = = Config.visibleclass) {
- Reset ();
- };
- Do stuff
- };
- Function Show () {
- var c = nav.classname;
- Do stuff
- };
- function Reset () {
- Do stuff
- };
- }();
This allows the maintainer to know where to modify these properties without having to change other code.
More Information
These are the seven guidelines I've found. If you want to learn more about the topics discussed above, you can look at the following links:
* Yahoo! Design Pattern Library
* Event Delegation
* Event driven JavaScript application Design
* JavaScript Programming Patterns
* Show love to the Object Literal
* A JavaScript Module Pattern
Seven guidelines for unobtrusive JavaScript's unobtrusive javascript