tag:blogger.com,1999:blog-74209047439296018422024-03-05T12:31:12.318-08:00Unobtrusive Javascript ApplicationsOr how to fulfill a complete separation of structure, presentation and behaviorJuan Molina Urquizuhttp://www.blogger.com/profile/14577874265747648298noreply@blogger.comBlogger9125tag:blogger.com,1999:blog-7420904743929601842.post-33160675345185995252013-12-12T02:53:00.003-08:002013-12-12T03:20:27.576-08:00The CSS3 :target pseudo-class<p>Some years ago, in 2005, I attended a workshop about CSS. Andy clark told us about the near future and showed us an example of a completely CSS driven web page. We all thought that there was some kind of javascript there but Andy said that the secret was the CSS3 :target pseudo-class.
</p>
<p>
You can run this jsFiddle <a href="http://jsfiddle.net/jurquizu/Wtr4g/">http://jsfiddle.net/jurquizu/Wtr4g/</a> for a live example.
</p>
<p>
The idea behind the :target pseudoclass is that the target element of an anchor can have its CSS rules. For example the anchor link "#info" is targetting the paragraph with id "info". When we click this link, the CSS selector p#info:target is triggered and all its rules are applied.
</p>
<p>
<b>HTML</b>
<pre name="code" class="XML">
<p>Click on the link to show the hidden paragraph: <a href="#info">show me</a>.</p>
<p id="info">This is the hidden paragraph.</p>
</pre>
</p>
<p>
<b>CSS</b>
<pre name="code" class="XML">
/* here's pseudoclass-target in action */
p#info {
display:none;
}
p#info:target {
display:block;
border:2px solid red;
background-color:yellow;
width:250px;
text-align:center;
}
</pre>
</p>Juan Molina Urquizuhttp://www.blogger.com/profile/14577874265747648298noreply@blogger.com0tag:blogger.com,1999:blog-7420904743929601842.post-47359971415955267682011-08-05T01:26:00.000-07:002011-08-05T03:52:45.198-07:00Adding behavior to CSS?<img style="float:left; border:0px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdcyHn9DhKECaAfv_5hkuF1Q_HO51oNitUmskPVFT1eXSPdbgkB8-cN6jKC_zrekLs-lhie8iUP770pjuRDY3rdox8m-EEXgU0cvRaqZCFgPu2QwZB7crx3MrtCM2h-gKQbKAXsMH3Kcg/s200/blur.png" title="Blurred separation between presentation and behavior" alt="Blurred separation between presentation and behavior" id="BLOGGER_PHOTO_ID_5637321662076511570" />
<p>
It's been already stated that it is a good practice to separate Presentation (CSS), Structure (HTML) and Behavior (Javascript) when building a web site. But this concept has not been always clear.
</p>
<p>
Recently, CSS3 has been adding features to enhance its ability to add behavior by means of new properties like <a href="http://www.sitepoint.com/a-primer-on-css3-transforms/">transition</a> or the <a href="http://reference.sitepoint.com/css/pseudoclass-target">:target pseudo class</a>. Doesn't this break the forementioned separation concern? Even previous CSS versions had features that made it possible to mix behavior in the presentational layer. Do you remember the vendor specific <a href="http://reference.sitepoint.com/css/behavior">behavior property of IE</a> and the associated .htc files? What about the :active or :hover pseudo classes?
</p>
<p>
All these features try to add a visual change (rotation, scaling, changing color...) that is related to behavior (activating a link, targetting an element, hovering over anything...) and all this is done via CSS! Shouldn't this be done via Javascript? In fact JavaScript was designed to be the layer of interactivity.
</p>
<p>
Well, that is why there is a bit of controversy (<a href="http://snook.ca/archives/javascript/css_animations_in_safari/">http://snook.ca/archives/javascript/css_animations_in_safari/</a>). To smooth things out let me share with you some ideas.
</p>
<p>
<ul>
<li>Most browser vendors are accepting CSS3 standards. Then, why not accept the transition property?</li>
<li>Transitions and animations in CSS3 have blurred the distinction between presentation and behavior as separate layers, but they are easy to create and fun.</li>
<li>Some animated transitions are presentational and have nothing to do with behavior such as a flashing banner or a fading title.</li>
<li>
Sometimes there is no clear border between presentation and behavior.</li>
</ul>
</p>
<p>
All in all, as long as you have a clear understanding of the benefits resulting from the separation of concerns, I don't think it is a mistake to take advantage of the improvements in CSS3 even though these benefits blur the distinction between presentation and behavior.
</p>Juan Molina Urquizuhttp://www.blogger.com/profile/14577874265747648298noreply@blogger.com0tag:blogger.com,1999:blog-7420904743929601842.post-85528605871785359982011-06-29T01:49:00.000-07:002011-06-29T05:47:14.905-07:00jQuery Mobile<p>
Once decided that jQuery will be my choice to write javascript code, I faced the challenge to find an easy way to write mobile applications. To my surprise I came across <a href="http://jquerymobile.com/">jQuery Mobile</a>, a javascript framework for creating websites optimized for the most popular mobile devices. This framework adds a layer on top of jQuery and meets some needs that developers of mobile devices have.
</p><p>
Before the appearance of these javascript frameworks, developers had to program websites for each particular device. This caused a lot of work for the creation and maintenance of these mobile sites. However, jQuery Mobile abstracts the specific logic of each device, so programmers can focus on what really matters.
</p><p>
jQuery Mobile works. While this is a very new project, a few months of life, it is giving a lot of talk, consolidating itself increasingly as the framework for the creation of star websites for mobile phones and tablets.
</p>
<p>
<b>jQuery Mobile Features</b>
</p>
<ul>
<li>Ease of Use: eases the development of user interfaces for mobile devices.</li>
<li>HTML5 markup driven support: When using this framework, we will forget to type JavaScript code. By using HTML tags, the rendering time will be processed by jQuery Mobile.</li>
<li>Multiple platforms supported: jQuery supports many devices and technologies, such as: IOS, Android, Blackberry, Palm WebOS, Symbian, Windows Mobile, etc..</li>
<li>Small size: All compressed library weighs less than 12K.</li>
<li>Custom Themes: The framework presents some utilities for managing themes. You can also create custom themes.</li>
</ul>
<p>
You can find more info and an example at <a href="http://www.codeforest.net/jquery-mobile-tutorial-basics">http://www.codeforest.net/jquery-mobile-tutorial-basics</a>
</p>
There's a great book and online course you can purchase at <a href="http://www.sitepoint.com/books/mobile1">http://www.sitepoint.com/books/mobile1</a>
</p>Juan Molina Urquizuhttp://www.blogger.com/profile/14577874265747648298noreply@blogger.com0tag:blogger.com,1999:blog-7420904743929601842.post-73524085085190931972011-06-02T03:07:00.000-07:002011-06-02T05:15:04.034-07:00jQuery Tools v jQueryUI<p>There is a debate whether to choose one javascript library or the other in order to have richer interface widgets in your web applications. From my point of view, there is no reason to conclude that on is better than the other.
</p>
<p>
Each jQuery libray has its own advantages and drawbacks. For example, to date, jQuery Tools lacks drag & drop functionality and jQueryUI lacks tooltips. However, jQueryUI has great theming support while jQuery Tools has a more hancrafted system to create themes.
</p>
<p>
Future releases of jQueryUI will include tooltip support, and many other enhancement. It's a matter of preference. Both of them are very easy to integrate in your web applications and keep the principle of separation between HTML, CSS and behaviour.
</p>Juan Molina Urquizuhttp://www.blogger.com/profile/14577874265747648298noreply@blogger.com0tag:blogger.com,1999:blog-7420904743929601842.post-66432291439618943832011-03-31T04:01:00.000-07:002011-03-31T04:15:28.414-07:00What is best: Prototype or JQuery?<p>Over time, the evolution of Javascript Frameworks has changed dramatically. When I started this blog, prototype was my best choice at the moment. However, nowadays I've changed my mind and I prefer the use of JQuery. I just wanted to make you know that from now on, the JS examples used in this blog will use JQuery.
</p>
<p>
These are some of the reasons that made me change the javascript framework from Prototype to <span style="font-weight: bold;">JQuery</span>:
</p>
<ol>
<li>Available plugins</li>
<li>Shorter learning curve</li>
<li>It is lightweight</li>
<li>Consistency with CSS syntax</li>
<li>Very well documented</li>
</ol>Juan Molina Urquizuhttp://www.blogger.com/profile/14577874265747648298noreply@blogger.com0tag:blogger.com,1999:blog-7420904743929601842.post-8777526128202026412009-04-20T00:56:00.000-07:002009-04-20T01:23:43.169-07:00Unobtrusive js classes<span style="font-weight:bold;">jsPopup</span>
<p>
We'll use this class to open a popup centered both horizontally and vertically.
The URL of the popup is the href target of the html a tag.
</p>
<p>
Example:<br />
<pre name="code" class="XML">
<a class="jsPopup" href="www.google.es">Google</a>
</pre>
</p>
<p>
To stablish other values for the opened window other that the default we can add a new attribute to the html a tag called aPopup using a json syntax:
</p>
<p>
Example:<br />
<pre name="code" class="XML">
<a class="jsPopup" href="www.google.es" aPopup="( 'width':'500 ','height':'500')">Google</a>
</pre>
<p>
If you don't establish the size, a default value of 800x600 pixels will be assigned to the width and height respectively.
</p>
<span style="font-weight:bold;">jsHideShow</span>
<p>
For all element with class jsHideShow, clicking on one of these elements will toggle the maximize/minimize state of a certain div. Both elements have an id.
</p>
<p>
Example:<br />
<pre name="code" class="XML">
<img id="buttonXXX" class="jsHideShow" src ="..." aHideShow="('imgExpand:'...','ImgCollapse:'...') "/>
<div id="contentXXX">...</ div>
</pre>
<p>
Example:<br />
<pre name="code" class="XML">
<img id="buttonSearch" class="jsHideShow" src="expand.gif' aHideShow="{'imgExpand':'expand.gif','imgCollapse':'collapse.gif'}" />
<div id="contentSearch">...</ div>
</pre>
</p>
<p>
We can stablish an initial state for a block. Example of a block initially minimized:
</p>
<p>
<pre name="code" class="XML">
<img id ="buttonDocs" class="jsHideShow" src ="expand.gif" aHideShow="('imgExpand:expand.gif','imgCollapse:collapse.gif','start:min'}" />
<div id="contentDocs">...</div>
</pre>
</p>Juan Molina Urquizuhttp://www.blogger.com/profile/14577874265747648298noreply@blogger.com0tag:blogger.com,1999:blog-7420904743929601842.post-84028149245077979682009-01-27T05:45:00.000-08:002009-07-17T02:50:54.163-07:00Step by Step Separation<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMhHdFVU4maTx3LyFHPLYttyZxoQJAKiPyC8jZPLXW5ArS2_ibdTvHfDnwEcyHdGs1TuN59mxKcYojvCjYOCzmOgcuWizYetBUkTQHiTgkXtN4N7TUOakM9RlwIIfXwYciN3_9BWNgdyM/s1600-h/step-by-step.jpg"><img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 129px; height: 111px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMhHdFVU4maTx3LyFHPLYttyZxoQJAKiPyC8jZPLXW5ArS2_ibdTvHfDnwEcyHdGs1TuN59mxKcYojvCjYOCzmOgcuWizYetBUkTQHiTgkXtN4N7TUOakM9RlwIIfXwYciN3_9BWNgdyM/s200/step-by-step.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5303006250654082882" /></a>
It would be worth reading Chris Heilmann's article <a href="http://icant.co.uk/articles/seven-rules-of-unobtrusive-javascript/">"The seven rules of Unobtrusive JavaScript"</a>. We basically get the idea that even if javascript is not available the web page should work well. To do that, javascript must not interfere with HTML directly but by means of hooks or triggers. Let's see a simple example in which the structure, presentation and behaviour is mixed in the body of the web page. We'll try to separate each layer into three different blocks in the same page.
<pre name="code" class="XML">
<html>
<script>
function onClick(sUrl) {
window.open(sUrl)
}
</script>
<body>
<a href="javascript:void(null)" onclick="goToWeb('http://www.nbc.com')">
<span style="color:green;">NBC Official site</span>
</a>
</body>
</html>
</pre>
When the user clicks the green link "NBC Official site" a new page will open. But this code is extremely obtrusive. The href attribute has a value which require javascript enabled. Besides, there is an onclick attribute that will make possible the opening of a new window. Again, javascript is necessary.
First of all, we'll clean any behavioral attributes and values from the HTML. The result is this:
<pre name="code" class="XML">
<html>
<script>
function onClick(sUrl) {
window.open(sUrl)
}
</script>
<body>
<a href="http://www.nbc.com/">
<span style="color:green;">NBC Official site</span>
</a>
</body>
</html>
</pre>
Now, the behaviour of this page is not the one we wanted. We must find a way to open a new page when clicking on the link. Here is where the idea of javascript triggers comes in handy. Let's add a class attribute to the link tag:
<pre name="code" class="XML">
<html>
<script>
function onClick(sUrl) {
window.open(sUrl)
}
</script>
<body>
<a href="http://www.nbc.com/" class="externalLink">
<span style="color:green;">NBC Official site</span>
</a>
</body>
</html>
</pre>
And finaly let's write the necessary javascript code that will open a new page when the user clicks a link of class "externalLink". I've used prototype as the base library to simplify the javascript code.
<pre name="code" class="HTML">
<script type="text/javascript" src="prototype.js"></script>
<script>
document.observe("dom:loaded",function() {
$$('.externalLink').each(function(element) {
element.observe("click",function(event) {
window.open(element.href,'','top=10,left=10,width=800,resizable');
event.stop();
})
});
});
</script>
</pre>
There is only on final detail to take out presentation tags from the HTML code. We need to add a style block in the head of the document. This is the new proposal:
<pre name="code" class="HTML">
<html>
<head>
<style>
.externalLink { color:green; }
</style>
<script type="text/javascript" src="prototype.js"></script>
<script>
document.observe("dom:loaded",function() {
$$('.externalLink').each(function(element) {
element.observe("click",function(event) {
window.open(element.href,'','top=10,left=10,width=800,resizable');
event.stop();
})
});
});
</script>
</head>
<body>
<a href="http://www.nbc.com/" class="externalLink">NBC Official site</a>
</body>
</html>
</pre>
There's is a tricky thing about the way I used to separate presentation and behaviour from the structure of the page, the HTML. Not everybody will accept using the same class value "externalLink" to trigger javascript and CSS at the same time. It could be a bit confusing if we changed the name of the class thinking that the only consequence is that we must change only the name of the CSS rule. Doing so, we lose the behaviour of the page. It's easy to avoid the problem if CSS and javascript is in the same page, but be careful if those blocks are in separate files. We would have a coupling problem between the CSS file and the javascript file.
I prefer to adopt a solution that consists in using a naming convention for those values that are aimed to trigger javascript. We could use "jsExternalLink". The initial js states clearly that this value is a hook for javascript to play its role. However, values to trigger CSS rules will stay the same. Up till now it's been much more common to use class and id values to trigger CSS than javascript. That is why I only use this naming convention for javascript triggers.Juan Molina Urquizuhttp://www.blogger.com/profile/14577874265747648298noreply@blogger.com0tag:blogger.com,1999:blog-7420904743929601842.post-77023526288038367492009-01-27T05:41:00.001-08:002009-01-27T05:42:40.048-08:00Separating Behaviour and Structure<p>The main reasons for using Ajax are the user experience improvement, a quicker page load due to a smaller page size and an implicit need to separate content, normally delivered as <acronym title="Extended Hypertext Markup Language">XHTML</acronym>, presentation, by means of embedded <acronym title="Cascading StyleSheets">CSS</acronym>, and behavior. The latter is assumed to integrate Javascript accessing the <acronym title="DocumentObject Model">DOM</acronym>, the XMLHttpRequest object for a bidirectional communication with the server and a server-side language that receives requests and responds accordingly to the client. If your XHTML page is free from behavior tags and attributes your javascript code in the head of that page is said to be unobtrusive.
</p><p>This separation is the basis of a web design strategy labeled as progressive enhancement. In essence, a web page must work whether it has stylesheets (presentation) enabled or not, and whether it has javascript (behavior) enabled or not.</p><p>Let’s concentrate on the behavior layer as many drawbacks refrain developers from using this set of techniques called Ajax in their applications. One is reliability of Javascript in the present-day maremagnum of differents browsers and versions. However, this shortcoming is being solved through javascript libraries that are being gradually more cross-browser. In our examples you’ll see <a href="http://www.prototypejs.org/">Prototype 1.6</a> in action. Another big concern about using Ajax is accessibility. Is it possible to write only one version of a site that is accessible as well as Ajax?</p><p>There are several techniques to apply <a href="http://www.onlinetools.org/articles/unobtrusivejavascript/">unobtrusive javascript</a> to a site in order to acomplish the “one version site only” target and I'll try to explain them in different posts.</p><p>Let’s state some of the conditions of our document structure to assure that we can have an unobtrusive ajax application.</p><h3 class="post-title entry-title">Javascript triggers</h3>It is assumed that using the class and id attributes is a standard practice to separate presentation and structure in an HTML page. We say that CSS triggers the presentation of a website. By doing so, we can forget about inline presentation tags such as <span style="font-"> because the stylesheet file deploys the presentation attached to the class and id attributes.<p>The behavior layer of a web page should work in a similar way. Instead of the inline event handlers mixed with HTML, such as <<i>html_tag</i> onclick=<i>"javascript_function</i>()" />, we can add <a href="http://www.alistapart.com/articles/scripttriggers">JavaScript triggers</a> to the HTML. This triggers tell the script where to deploy the behavior from.</p><p>There are basically two methods to trigger javascript:</p><ul><li>adding custom attributes</li><li>using class and id attributes (<a href="http://www.blogger.com/post-edit.g?blogID=7420904743929601842&postID=4199228075371057375#other-valid-attributes">or other valid attributes</a>)
</li></ul><p>Both methods have their advantages and drawbacks. <acronym title="In my humble opinion">IMHO</acronym>, whether you prefer one or the other, is a matter of conscience or a phylosophical issue. Depending on the situation I prefer one to the other, or a mixture of both. I'll tell you more about that in a moment.
</p><p>To introduce an example, imagine we want to attach a behavior to an input field to avoid sending an empty string to the server. </p><p>Using the first technique, we could add a custom attribute to the input field called "required" with a value of "true". This will be the hook to the behavior in the js file. </p><p><input type="text" name="email" required="true" /> </p><p>Using the second technique, we add a valid class attribute to the input field with a value of required.
</p><p><input type="text" name="email" class="required" /></p>
<h3 id="other-valid-attributes" class="post-title entry-title">Other valid attributes to trigger javascript</h3>
There is another alternative to hook javascript to the HTML structure. Why not use the <code>rel</code> attribute instead of the <code>class</code> or <code>id </code>attributes to attach the JavaScript behavior?<p></p><p>We normally use the <code>class/id</code> attributes as a hook to the presentation layer (CSS). Mixing presentation and behavior in the same HTML attribute seems to be against the idea of separating presentation and behavior. But there is an alternative. We can use the <code>rel</code> attribute for the behavior (JavaScript). Here's an example of the markup required:</p><p> <a href="destination_url" rel="<a href="http://www.accessify.com/features/tutorials/the-perfect-popup/">popup</a>"></p><p>Is it acceptable to use the HTML <code>rel</code> attribute to accomplish our goal? What is the meaning of <code>rel</code> in HTML?</p><p><code>Rel</code> stands for "relationship". When used in the <code>a</code> tag, the <a href="http://reference.sitepoint.com/html/a/rel"><code>rel</code> attribute</a> is used to provide information about the relationship between the target url page and the actual page. This attribute can take any value, even a series of space separated values. The same happens with the <code>class</code> attribute but not the <code>id</code> which must have a unique value. Browsers don't use this attribute for any rendering effect or behavior change. It's pure semantic markup.
</p><p>The real value of the <code>rel</code> attribute is mainly to add behavior via Javascript. However, it can only be used correctly in the <code>a</code> and <code>link</code> tags and that's a big difference from <code>class</code> and <code>id</code> which ara core attributes and thus can be used in any HTML tag.</p>
<h3 class="post-title entry-title">Reasonable names for behavior triggers</h3>
Many XHTML coders understand that it is not correct to have a class with value red to format a text in order to emphasize its content: <strong><span class="red">Error: the address field is required</span></strong>. The reason is obvious. This class value carries presentation information, not semantic. Presentation information should be in the CSS file, not in the XHTML code. One solution is to find a name that carries information about the reason why that text is presented in a different way (now red, but perhaps the CSS designer could change it into a dark red and bold text some day. Then, the value red in the class attribute would become obsolete). The reason is that the user forgot to fill a field in a form. There is an error. That's the meaning, the semantic information. Thus, the value for that class could be "error" or "required". None of them carries information about the presentation of those classes. The responsible for the presentation is the CSS file.<p></p>
<p>In a similar way, names attached to class/id attributes in the XHTML code to trigger javascript should have a semantic value, not behavioral meaning. It's very subtle, but you are warned to think a bit when you have to find a name for a behavior trigger. For example, you may think that the previous <strong><a href="destination_url" rel="popup"></strong> has a correct value in the rel attribute. But that's not true as the "popup" is carrying a very clear behavioral meaning. It suggests that when you click this link a new popup window will open. But we could change this behavior and display the content of the target link into a div in the same page, or open a new tab, or whatever other behavior we can think of. What would be a proper name, then? Well, I can think of names like "externalLink", "outLink", ... The js file will trigger some behavior for those links in the XHTML page with a value of "outLink" in its rel attribute. In the end, we have accomplished what is called <a href="http://www.alistapart.com/articles/behavioralseparation">behavioral separation</a>.</p>Juan Molina Urquizuhttp://www.blogger.com/profile/14577874265747648298noreply@blogger.com0tag:blogger.com,1999:blog-7420904743929601842.post-49613892132845946322009-01-27T05:39:00.001-08:002009-01-27T05:40:44.454-08:00Unobtrusive Javascript Examples with Prototype<p>There is a well known design pattern when developing a web application known as MVC (Model-View-Controller). We can find an analogy of this design pattern with web applications that run in the client browser. We know the advantages of this separation. We can find an equivalence between the HTML structure and the Model, the CSS presentation and the View, and the JavaScript behavior and the Controller. Now it should be easier to understand why it is a sensible decision to remove style attributes and tags and JavaScript code mixed in the HTML file (<a href="http://www.juixe.com/techknow/index.php/2007/05/02/unobtrusive-javascript-with-prototype-and-behavior/">MVC analogy article</a>).
</p>
<p>The following example shows a way to make this separation effective. The example uses three files: an HTML file (the model or structure), a CSS file (the view or presentation) and a Javascript file (the controller or behavior). We use prototype in order to change the behavior of input fields with class value "required". When the page is fully loaded, javascript will change the default action of the onSubmit event to trigger a new behavior that will validate the form. When the user submits the form, an alert will show up indicating a list of the empty fields that are required. If javascript is disabled or the browser does not accept javascript, the page will still be fully functional.
</p>
<p>The basic document structure of our HTML tag will include the <strong>prototype.js</strong> library and our own set of functions that will be packed into a file named <strong>startup.js</strong>. In our examples these two files will be stored in folder <strong>js/</strong>.</p>
<p><strong>startup.js:</strong></p>
<pre>document.observe(<span style=' color: Maroon;'>"dom:loaded"</span>, <span style=' color: Blue;'>function</span>() {
<span style=' color: Green;'>// javascript code to be executed when the dom is loaded </span>
}); </pre>
<p><strong>example-01.html:</strong></p>
<pre><span style=' color: Blue;'><</span><span style=' color: Maroon;'>html</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>head</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>link</span> <span style=' color: Red;'>type</span>="<span style=' color: Blue;'>text/css</span>" <span style=' color: Red;'>rel</span>="<span style=' color: Blue;'>stylesheet</span>" <span style=' color: Red;'>href</span>="<span style=' color: Blue;'>css/style.css</span>"<span style=' color: Blue;'>></span><span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>link</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>script</span> <span style=' color: Red;'>type</span>="<span style=' color: Blue;'>text/javascript</span>" <span style=' color: Red;'>src</span>="<span style=' color: Blue;'>js/prototype.js</span>"<span style=' color: Blue;'>></span><span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>script</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>script</span> <span style=' color: Red;'>type</span>="<span style=' color: Blue;'>text/javascript</span>" <span style=' color: Red;'>src</span>="<span style=' color: Blue;'>js/startup.js</span>"<span style=' color: Blue;'>></span><span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>script</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>head</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>body</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>h1</span><span style=' color: Blue;'>></span>Request information form<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>h1</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>form</span> <span style=' color: Red;'>name</span>="<span style=' color: Blue;'>info_rq</span>" <span style=' color: Red;'>method</span>="<span style=' color: Blue;'>post</span>" <span style=' color: Red;'>action</span>="<span style=' color: Blue;'>info_request.php</span>" <span style=' color: Red;'>id</span>="<span style=' color: Blue;'>info_request</span>"<span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span>p<span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>label</span> <span style=' color: Red;'>for</span>="<span style=' color: Blue;'>e-mail</span>"<span style=' color: Blue;'>></span>e-mail<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>label</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>input</span> <span style=' color: Red;'>name</span>="<span style=' color: Blue;'>e-mail</span>" <span style=' color: Red;'>value</span>="<span style=' color: Blue;'></span>" <span style=' color: Red;'>class</span>="<span style=' color: Blue;'>required</span>" /<span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>span</span> <span style=' color: Red;'>id</span>="<span style=' color: Blue;'>error-e-mail</span>"<span style=' color: Blue;'>></span>*<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>span</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>p</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span>p<span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>label</span> <span style=' color: Red;'>for</span>="<span style=' color: Blue;'>comment</span>"<span style=' color: Blue;'>></span>your comment<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>label</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>textarea</span> <span style=' color: Red;'>name</span>="<span style=' color: Blue;'>comment</span>" <span style=' color: Red;'>value</span>="<span style=' color: Blue;'></span>" <span style=' color: Red;'>cols</span>="<span style=' color: Blue;'>80</span>" <span style=' color: Red;'>rows</span>="<span style=' color: Blue;'>5</span>" <span style=' color: Red;'>class</span>="<span style=' color: Blue;'>required</span>"<span style=' color: Blue;'>></span><span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>textarea</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>span</span> <span style=' color: Red;'>id</span>="<span style=' color: Blue;'>error-comment</span>"<span style=' color: Blue;'>></span>*<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>span</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>p</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>input</span> <span style=' color: Red;'>type</span>="<span style=' color: Blue;'>submit</span>" <span style=' color: Red;'>value</span>="<span style=' color: Blue;'>Send comment</span>" /<span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>form</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span>p<span style=' color: Blue;'>></span>The * indicates a required field<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>p</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>body</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>html</span><span style=' color: Blue;'>></span></pre><p>Now it's time to start designing the code to be executed when the dom is loaded. These are the steps we'll follow to accomplish our goals:
<ol>
<li>Design the function to be attached to the onSubmit event</li>
<li>Capture the onSubmit event and attach the previously designed function</li>
</ol>
</p>
<p><strong>startup.js:</strong></p>
<pre>document.observe(<span style=' color: Maroon;'>"dom:loaded"</span>, <span style=' color: Blue;'>function</span>() {
<span style=' color: Green;'>// javascript code to be executed when the dom is loaded</span>
$(<span style=' color: Maroon;'>'info_request'</span>).onsubmit = <span style=' color: Blue;'>function</span>() {
<span style=' color: Blue;'>var</span> sError = <span style=' color: Maroon;'>'The following fields cannot be empty:\n'</span>;
<span style=' color: Blue;'>var</span> sField = <span style=' color: Maroon;'>''</span>;
$$(<span style=' color: Maroon;'>'.required'</span>).each(<span style=' color: Blue;'>function</span>(element) {
<span style=' color: Blue;'>if</span> (!element.present()) {
sField+= element.name+<span style=' color: Maroon;'>'\n'</span>;
}
});
<span style=' color: Blue;'>if</span> (sField!=<span style=' color: Maroon;'>''</span>) {
alert(sError+sField);
<span style=' color: Blue;'>return</span> <span style=' color: Maroon;'>false</span>;
}
<span style=' color: Blue;'>else</span> {
<span style=' color: Blue;'>return</span> <span style=' color: Maroon;'>true</span>;
}
}
});</pre>
<p>
Now, as you can see, the HTML code is free from any inline behavior attributes, or script tags, with one exception. All the necessary javascript files are described in the head of the document. We have achieved the behavior separation goal.
</p>
<p>One of the advantages of this separation is that we can device a completely different behavior for the onSubmit event without changing the HTML file at all. In this second example, when the user submits the form, every empty input field of class required will display a red text next to it indicating the error. Let's see how to do it.
</p>
<p><strong>startup.js:</strong></p>
<pre>document.observe(<span style=' color: Maroon;'>"dom:loaded"</span>, <span style=' color: Blue;'>function</span>() {
<span style=' color: Green;'>// javascript code to be executed when the dom is loaded</span>
$(<span style=' color: Maroon;'>'info_request'</span>).onsubmit = <span style=' color: Blue;'>function</span>() {
<span style=' color: Blue;'>var</span> sError_field = <span style=' color: Maroon;'>''</span>;
<span style=' color: Blue;'>var</span> bError = <span style=' color: Maroon;'>false</span>;
$$(<span style=' color: Maroon;'>'.required'</span>).each(<span style=' color: Blue;'>function</span>(element) {
sError_field = <span style=' color: Maroon;'>'error-'</span>+element.name;
<span style=' color: Blue;'>if</span> (!element.present()) {
bError = <span style=' color: Maroon;'>true</span>;
$(sError_field).update(<span style=' color: Maroon;'>'* EMPTY'</span>).addClassName(<span style=' color: Maroon;'>'empty'</span>);
}
<span style=' color: Blue;'>else</span> {
$(sError_field).update(<span style=' color: Maroon;'>'*'</span>).removeClassName(<span style=' color: Maroon;'>'empty'</span>);
}
});
<span style=' color: Blue;'>if</span> (bError) {
<span style=' color: Blue;'>return</span> <span style=' color: Maroon;'>false</span>;
}
<span style=' color: Blue;'>else</span> {
<span style=' color: Blue;'>return</span> <span style=' color: Maroon;'>true</span>;
}
}
});</pre>
<p>The style.css file has only one rule that presents all elements of class "empty" in the HTML file in red color. That is why we call the .addClassName('empty') or .removeClassName('empty') in the startup.js file.</>
<p><strong>style.css:</strong></p>
<pre>
.empty {
color:red;
}
</pre>
In the third example you'll see how to show a confirmation popup when you click a link that targets a deletion action. This is the HTML code:
<pre><span style=' color: Blue;'><</span><span style=' color: Maroon;'>html</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>head</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>link</span> <span style=' color: Red;'>type</span>="<span style=' color: Blue;'>text/css</span>" <span style=' color: Red;'>rel</span>="<span style=' color: Blue;'>stylesheet</span>" <span style=' color: Red;'>href</span>="<span style=' color: Blue;'>css/style.css</span>"<span style=' color: Blue;'>></span><span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>link</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>script</span> <span style=' color: Red;'>type</span>="<span style=' color: Blue;'>text/javascript</span>" <span style=' color: Red;'>src</span>="<span style=' color: Blue;'>js/prototype.js</span>"<span style=' color: Blue;'>></span><span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>script</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>script</span> <span style=' color: Red;'>type</span>="<span style=' color: Blue;'>text/javascript</span>" <span style=' color: Red;'>src</span>="<span style=' color: Blue;'>js/startup-03.js</span>"<span style=' color: Blue;'>></span><span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>script</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>head</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>body</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>h1</span><span style=' color: Blue;'>></span>List of newspapers<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>h1</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span>p<span style=' color: Blue;'>></span>Click on the 'X' to delete a register. Confirmation will be requested.<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>p</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>ul</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>li</span><span style=' color: Blue;'>></span><span style=' color: Blue;'><</span>a <span style=' color: Red;'>href="remove_newspaper.php?id</span>=1" <span style=' color: Red;'>class</span>="<span style=' color: Blue;'>confirm</span>"<span style=' color: Blue;'>></span>X<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>a</span><span style=' color: Blue;'>></span> La Vanguardia<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>li</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>li</span><span style=' color: Blue;'>></span><span style=' color: Blue;'><</span>a <span style=' color: Red;'>href="remove_newspaper.php?id</span>=2" <span style=' color: Red;'>class</span>="<span style=' color: Blue;'>confirm</span>"<span style=' color: Blue;'>></span>X<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>a</span><span style=' color: Blue;'>></span> El Mundo<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>li</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>li</span><span style=' color: Blue;'>></span><span style=' color: Blue;'><</span>a <span style=' color: Red;'>href="remove_newspaper.php?id</span>=3" <span style=' color: Red;'>class</span>="<span style=' color: Blue;'>confirm</span>"<span style=' color: Blue;'>></span>X<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>a</span><span style=' color: Blue;'>></span> El Pa&iacute;s<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>li</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>li</span><span style=' color: Blue;'>></span><span style=' color: Blue;'><</span>a <span style=' color: Red;'>href="remove_newspaper.php?id</span>=4" <span style=' color: Red;'>class</span>="<span style=' color: Blue;'>confirm</span>"<span style=' color: Blue;'>></span>X<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>a</span><span style=' color: Blue;'>></span> El Peri&oacute;dico<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>li</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>ul</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>h2</span><span style=' color: Blue;'>></span>Remove register<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>h2</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>form</span> <span style=' color: Red;'>method</span>="<span style=' color: Blue;'>post</span>" <span style=' color: Red;'>action="remove_newspaper.php?id</span>=5"<span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>label</span><span style=' color: Blue;'>></span>Newspaper<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>label</span><span style=' color: Blue;'>></span> <span style=' color: Blue;'><</span><span style=' color: Maroon;'>input</span> <span style=' color: Red;'>type</span>="<span style=' color: Blue;'>text</span>" <span style=' color: Red;'>name</span>="<span style=' color: Blue;'>newspaper</span>" <span style=' color: Red;'>value</span>="<span style=' color: Blue;'>El Marca</span>" /<span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span><span style=' color: Maroon;'>input</span> <span style=' color: Red;'>type</span>="<span style=' color: Blue;'>submit</span>" <span style=' color: Red;'>value</span>="<span style=' color: Blue;'>Delete</span>" <span style=' color: Red;'>class</span>="<span style=' color: Blue;'>confirm</span>" /<span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>form</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>body</span><span style=' color: Blue;'>></span>
<span style=' color: Blue;'><</span>/<span style=' color: Maroon;'>html</span><span style=' color: Blue;'>></span>
</pre>
The correspondig javascript file captures the onClick event
<p><strong>startup-03.html:</strong></p>
<pre>document.observe(<span style=' color: Maroon;'>"dom:loaded"</span>,<span style=' color: Blue;'>function</span>() {
$$(<span style=' color: Maroon;'>'.confirm'</span>).each(<span style=' color: Blue;'>function</span>(element) {
element.observe(<span style=' color: Maroon;'>"click"</span>,<span style=' color: Blue;'>function</span>(<span style=' color: Blue;'>event</span>) {
<span style=' color: Blue;'>if</span> (!confirm(<span style=' color: Maroon;'>'Are you sure to perform this action?'</span>)) {
<span style=' color: Blue;'>event</span>.stop();
}
})
});
});</pre>Juan Molina Urquizuhttp://www.blogger.com/profile/14577874265747648298noreply@blogger.com0