<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5453912577685101694</id><updated>2011-04-21T20:41:00.348-07:00</updated><category term='junit'/><category term='jmock'/><category term='test'/><category term='method'/><category term='java'/><title type='text'>Rate of Intelligence</title><subtitle type='html'>Blog about software development</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://intelrate.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5453912577685101694/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://intelrate.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Pavel</name><uri>http://www.blogger.com/profile/10052990641851592314</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_uX-JLRYgRwc/SM-CrBTJOnI/AAAAAAAAABc/TCwhs_jYxik/S220/intelrate_logo_90x90.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>2</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5453912577685101694.post-6975288644067540298</id><published>2009-05-19T21:49:00.000-07:00</published><updated>2009-05-19T23:36:16.844-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='method'/><category scheme='http://www.blogger.com/atom/ns#' term='test'/><category scheme='http://www.blogger.com/atom/ns#' term='junit'/><category scheme='http://www.blogger.com/atom/ns#' term='jmock'/><title type='text'>How to mock protected method in Java</title><content type='html'>It's a very common situation when we call &lt;b&gt;protected methods&lt;/b&gt; of a class from other methods in the same class. This article is about approach to testing such caller methods. We'll not discuss why a test is more robust and modular if it covers only functionality of &lt;b&gt;enclosing method&lt;/b&gt; with assumptions that &lt;b&gt;invoked methods&lt;/b&gt; satisfy their contracts. For more information about advantages of modular tests please refer to articles about &lt;a href="http://www.intelrate.com/articles/agile/mockmethod/"&gt;TDD&lt;/a&gt; and &lt;a href="http://www.intelrate.com/articles/java/testing/"&gt;JUnit testing in Java&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt; Let's first review some trivial example to be on the same page. There is &lt;i&gt;EinsteinFormula&lt;/i&gt; interface below:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;package&lt;/span&gt; com.intelrate.mockmethod;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;public interface&lt;/span&gt; EinsteinFormula {&lt;br /&gt; &lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;double&lt;/span&gt; kineticEnergy(&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;double&lt;/span&gt; restMass, &lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;double&lt;/span&gt; velocity);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt; This interface states that we can get kinetic energy of some moving body if its rest mass and velocity are provided. Here is physical law describing the formula:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_uX-JLRYgRwc/ShOkZC2qlEI/AAAAAAAAAD0/0JT7uiPx8ck/s1600-h/mock.bmp"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 212px; height: 58px;" src="http://4.bp.blogspot.com/_uX-JLRYgRwc/ShOkZC2qlEI/AAAAAAAAAD0/0JT7uiPx8ck/s320/mock.bmp" border="0" alt=""id="BLOGGER_PHOTO_ID_5337790733534008386" /&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Take a look at implimentation:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;package&lt;/span&gt; com.intelrate.mockmethod.impl;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;import&lt;/span&gt; com.intelrate.mockmethod.EinsteinFormula;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;public class&lt;/span&gt; EinsteinFormulaImpl &lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;implements&lt;/span&gt; EinsteinFormula {&lt;br /&gt; &lt;br /&gt; &lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;static final double&lt;/span&gt; SPEED_OF_LIGHT = 2.99792458E8;&lt;br /&gt;&lt;span style="color: green;"&gt;&lt;br /&gt; /**&lt;br /&gt;  * Calculates kinetic energy for the given object.&lt;br /&gt;  * &lt;br /&gt;  * @param restMass object's mass&lt;br /&gt;  * @param velocity object's velocity&lt;br /&gt;  * @return kinetic energy according to Einstein formula&lt;br /&gt;  */&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt; public double&lt;/span&gt; kineticEnergy(&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;final double &lt;/span&gt;restMass, &lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;final double &lt;/span&gt;velocity) {&lt;br /&gt;  &lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;final double&lt;/span&gt; restEnegry = energy(restMass);&lt;br /&gt;  &lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;return&lt;/span&gt; restEnegry * (1 / Math.sqrt(1 - &lt;br/&gt;    (velocity * velocity) / (SPEED_OF_LIGHT * SPEED_OF_LIGHT)) - 1);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; &lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;double&lt;/span&gt; energy(&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;final double&lt;/span&gt; mass) {&lt;br /&gt;  &lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;return&lt;/span&gt; mass * SPEED_OF_LIGHT * SPEED_OF_LIGHT;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt; As you can see, there are two &lt;b&gt;meaningful methods&lt;/b&gt; in this class. It's quite clear how to test each of them from contract point of view but technically we don't want &lt;i&gt;energy&lt;/i&gt; method to be called in a test for &lt;i&gt;kineticEnergy&lt;/i&gt; because it is better to assume that &lt;i&gt;energy&lt;/i&gt; works correctly when a test for &lt;i&gt;kineticEnergy&lt;/i&gt; runs.&lt;br /&gt;&lt;br /&gt; If &lt;i&gt;energy&lt;/i&gt; method was in interface we could easily mock it using nested class as it is described at the end of &lt;a href="http://www.intelrate.com/articles/agile/mockmethod/"&gt;article about TDD&lt;/a&gt; but problem here is that we cannot perform fake call of &lt;i&gt;energy&lt;/i&gt; itself. The next interface serves a technique of mocking protected methods in Java:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package com.intelrate.mockmethod.impl;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;public interface&lt;/span&gt; MockInterface {&lt;br /&gt; Object mockMethod(Object parameter);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt; It's time to see how we can use it to test &lt;i&gt;kineticEnergy&lt;/i&gt; calculation in JUnit + JMock:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;package&lt;/span&gt; com.intelrate.mockmethod.impl;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;import static&lt;/span&gt; org.junit.Assert.assertEquals;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;import&lt;/span&gt; org.jmock.Expectations;&lt;br /&gt;&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;import&lt;/span&gt; org.jmock.Mockery;&lt;br /&gt;&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;import&lt;/span&gt; org.jmock.integration.junit4.JMock;&lt;br /&gt;&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;import&lt;/span&gt; org.jmock.integration.junit4.JUnit4Mockery;&lt;br /&gt;&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;import&lt;/span&gt; org.junit.Before;&lt;br /&gt;&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;import&lt;/span&gt; org.junit.Test;&lt;br /&gt;&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;import&lt;/span&gt; org.junit.runner.RunWith;&lt;br /&gt;&lt;br /&gt;@RunWith(JMock.class)&lt;br /&gt;&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;public class&lt;/span&gt; EinsteinFormulaImplTest {&lt;br /&gt;&lt;br /&gt; &lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;private final&lt;/span&gt; Mockery context = &lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;new&lt;/span&gt; JUnit4Mockery();&lt;br /&gt; &lt;br /&gt; &lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;private&lt;/span&gt; MockInterface mockInterface;&lt;br /&gt;&lt;br /&gt; &lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;private final static double&lt;/span&gt; DELTA = 0.001;&lt;br /&gt;&lt;br /&gt; @Before&lt;br /&gt; &lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;public void&lt;/span&gt; setUp() {&lt;br /&gt;  mockInterface = context.mock(MockInterface.&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;class&lt;/span&gt;);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Test&lt;br /&gt; &lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;public void&lt;/span&gt; testKineticEnergy() {&lt;br /&gt;  EinsteinFormulaImpl einsteinFormula = &lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;new&lt;/span&gt; EinsteinFormulaImpl() {&lt;br /&gt;   &lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;double&lt;/span&gt; energy(&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;final double&lt;/span&gt; mass) {&lt;br /&gt;    &lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;return&lt;/span&gt; (Double) mockInterface.mockMethod(mass);&lt;br /&gt;   }&lt;br /&gt;  };&lt;br /&gt;  &lt;br /&gt;  &lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;final double&lt;/span&gt; restMass = 10.0;&lt;br /&gt;  &lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;final double&lt;/span&gt; velocity = 100000000.0;&lt;br /&gt;  &lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;final double&lt;/span&gt; expectedEnergy = 5.4601175017849928E16;&lt;br /&gt;  &lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;final double&lt;/span&gt; mockRestEnergy = 8.987551787368178E17;&lt;br /&gt;&lt;br /&gt;  context.checking(&lt;span style="color: rgb(128, 0, 128); font-weight: bold;"&gt;new&lt;/span&gt; Expectations() { {&lt;br /&gt;   one(mockInterface).mockMethod(restMass);&lt;br /&gt;   will(returnValue(mockRestEnergy));&lt;br /&gt;  } });&lt;br /&gt;&lt;br /&gt;  assertEquals(expectedEnergy, einsteinFormula.kineticEnergy(&lt;br /&gt;                    restMass, velocity), DELTA);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt; The idea behind this test is simple - we provide rest mass and velocity of some physical body and expect that its kinetic energy will be equal to predefined value. At the same time we use JMock to mock our helper interface which controls that &lt;i&gt;energy&lt;/i&gt; method was called with &lt;i&gt;mass&lt;/i&gt; parameter and returned &lt;i&gt;mockRestEnergy&lt;/i&gt; to the tested method.&lt;br /&gt;&lt;br /&gt; Summarizing this idea, we've got a clear code with optimal interface and really modular test at the same time.&lt;br /&gt;&lt;br /&gt;Cheers!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5453912577685101694-6975288644067540298?l=intelrate.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://intelrate.blogspot.com/feeds/6975288644067540298/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5453912577685101694&amp;postID=6975288644067540298' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5453912577685101694/posts/default/6975288644067540298'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5453912577685101694/posts/default/6975288644067540298'/><link rel='alternate' type='text/html' href='http://intelrate.blogspot.com/2009/05/how-to-mock-protected-method-in-java.html' title='How to mock protected method in Java'/><author><name>Pavel</name><uri>http://www.blogger.com/profile/10052990641851592314</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_uX-JLRYgRwc/SM-CrBTJOnI/AAAAAAAAABc/TCwhs_jYxik/S220/intelrate_logo_90x90.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_uX-JLRYgRwc/ShOkZC2qlEI/AAAAAAAAAD0/0JT7uiPx8ck/s72-c/mock.bmp' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5453912577685101694.post-6245596675045690915</id><published>2008-09-28T07:33:00.000-07:00</published><updated>2008-09-28T08:59:35.351-07:00</updated><title type='text'>AJAX and Select HTML element or how I underestimated Internet Explorer.</title><content type='html'>Working on widget for selecting &lt;a href="http://intelrate.com/books/"&gt;recommended books&lt;/a&gt; I used &lt;a href="http://www.w3schools.com/ajax/ajax_server.asp"&gt;article from w3cschools&lt;/a&gt;. Desired functionality was simple: user changes the category so the list of books is updated without necessity to reload the page completely. I never keep in mind all technical details, that's why I always prefer to refer to respected sources for an advice. And the advice was to use AJAX in the next way:&lt;br /&gt;&lt;br /&gt;1) Create the instance of XMLHttpRequest handling a type of browser.&lt;br /&gt;2) Initialize its onreadystatechange property: xmlHttp.onreadystatechange = callbackFunction;&lt;br /&gt;3) Initialize parameters of Http request: xmlHttp.open("GET", "handler.php", true);&lt;br /&gt;4) Perform the request: xmlHttp.send(null);&lt;br /&gt;&lt;br /&gt;So far so good! It seemed reasonable and I decided to apply it. Here I throw off all insignificant details. Bluntly speaking, HTML view looked like this (file ndex.html):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;html&gt;&lt;br /&gt;    &amp;lt;body&gt;&lt;br /&gt;        &amp;lt;div&gt;&lt;br /&gt;            &amp;lt;script type="text/javascript" src="/select.js"&gt;&amp;lt;/script&gt;&lt;br /&gt;            &amp;lt;select id="select" onchange="javascript:changed();"&gt;&lt;br /&gt;                &amp;lt;option value="1"&gt;Firstly&amp;lt;/option&gt;&lt;br /&gt;                &amp;lt;option value="2"&gt;Secondly&amp;lt;/option&gt;&lt;br /&gt;                &amp;lt;option value="3"&gt;Finally&amp;lt;/option&gt;&lt;br /&gt;            &amp;lt;/select&gt;&lt;br /&gt;        &amp;lt;/div&gt;&lt;br /&gt;        &amp;lt;div id="advice" /&gt;&lt;br /&gt;&amp;lt;/html&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;img src="http://2.bp.blogspot.com/_uX-JLRYgRwc/SN-iOtTWUnI/AAAAAAAAACA/3YLkiQBEYjY/s320/selectElement.PNG" border="0" alt="select element" id="BLOGGER_PHOTO_ID_5251094064099906162" /&gt;&lt;br /&gt;It is simple Select element with associated onchange event handler represented by JavaScript function "changed( )" defined in select.js file:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;var&lt;/span&gt; httpObject = createXMLHttpRequest();&lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;function&lt;/span&gt; changed() {&lt;br /&gt;    &lt;span style="color: blue;"&gt;var&lt;/span&gt; selected = document.getElementById('select');&lt;br /&gt;    httpObject.onreadystatechange = handleResponse;&lt;br /&gt;    httpObject.open('GET', '/handler.php?option='&lt;br /&gt;        + selected.options[selected.selectedIndex].value);&lt;br /&gt;    httpObject.send(&lt;span style="color: blue;"&gt;null&lt;/span&gt;);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;// Handles server responses.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;function&lt;/span&gt; handleResponse() {&lt;br /&gt;    &lt;span style="color: blue;"&gt;if&lt;/span&gt; (httpObject.readyState == 4) {&lt;br /&gt;        &lt;span style="color: blue;"&gt;var&lt;/span&gt; response = httpObject.responseText;&lt;br /&gt;        document.getElementById('advice').innerHTML = response;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: green;"&gt;// Creates new XMLHttpRequest&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue;"&gt;function&lt;/span&gt; createXMLHttpRequest() {&lt;br /&gt;    &lt;span style="color: blue;"&gt;var&lt;/span&gt; xmlHttp;&lt;br /&gt;    &lt;span style="color: blue;"&gt;try&lt;/span&gt; {&lt;br /&gt;        &lt;span style="color: green;"&gt;// create an XMLHttpRequest object&lt;/span&gt;&lt;br /&gt;        xmlHttp = &lt;span style="color: blue;"&gt;new&lt;/span&gt; XMLHttpRequest();&lt;br /&gt;    } &lt;span style="color: blue;"&gt;catch&lt;/span&gt;(e) {&lt;br /&gt;        &lt;span style="color: green;"&gt;// assume IE6 or older&lt;/span&gt;&lt;br /&gt;        &lt;span style="color: blue;"&gt;try&lt;/span&gt; {&lt;br /&gt;            xmlHttp = &lt;span style="color: blue;"&gt;new&lt;/span&gt; ActiveXObject("Microsoft.XMLHttp");&lt;br /&gt;        } &lt;span style="color: blue;"&gt;catch&lt;/span&gt;(e) {&lt;br /&gt;            alert("Error creating the XMLHttpRequest object.");&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: blue;"&gt;return&lt;/span&gt; xmlHttp;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Let's review two other functions. Firstly, createXMLHttpRequest( ) creates global instance of XMLHttpRequest depending on type of browser. Function handleResponse( ) is called every time when our server sends a response with updated status. We wait until operation is complete (httpObject.readyState is equal to 4) and immediately update the advice with message generated by the server. Here these messages are (file handler.php):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color: red;"&gt;&amp;lt;?php&lt;/span&gt;&lt;br /&gt;    &lt;span style="color: blue;"&gt;if&lt;/span&gt; ($_GET['option'] == '1') {&lt;br /&gt;        &lt;span style="color: blue;"&gt;echo&lt;/span&gt; 'Initialize parameters of Http request';&lt;br /&gt;    } &lt;span style="color: blue;"&gt;else if&lt;/span&gt; ($_GET['option'] == '2') {&lt;br /&gt;        &lt;span style="color: blue;"&gt;echo&lt;/span&gt; 'Initialize onreadystatechange property';&lt;br /&gt;    } &lt;span style="color: blue;"&gt;else if&lt;/span&gt; ($_GET['option'] == '3') {&lt;br /&gt;        &lt;span style="color: blue;"&gt;echo&lt;/span&gt; 'Perform the request';&lt;br /&gt;    } &lt;span style="color: blue;"&gt;else&lt;/span&gt; {&lt;br /&gt;        &lt;span style="color: blue;"&gt;echo&lt;/span&gt; 'Exception';&lt;br /&gt;    }&lt;br /&gt;&lt;span style="color: red;"&gt;?&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It simply takes the option set by httpObject.open(...) call and generate appropriate text by means of HTTPResponse. This text will be contained in httpObject.responseText when the response is complete.&lt;br /&gt;&lt;br /&gt;And... Tada! I decided that my widget is ready. I've verified it in Mozilla Firefox (the best browser for software developers ;) and Opera (cool browser too). And then... Oh! I found that it doesn't work in Internet Explorer. More precisely, it works but only once. So, you can try, when user selects option 'Secondly' from the list at first time, Internet Explorer gets the response and updates the text of 'advice' HTML element. But then user may reselect different options infinitely without any result. Only F5 refreshing the page will provide one more attempt.&lt;br /&gt;&lt;br /&gt;I was depressed. But listening to S.O.S. by ABBA brought me to life.&lt;br /&gt;&lt;br /&gt;I couldn't leave this issue as it was because people still use IE. Nevertheless, here I should present my apologies to Internet Explorer. Actually, it was my fault that I'd been disappointed by w3cschools' article. The mistake was in order of steps of preparing and sending XMLHttpRequest. So, the fix is:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    httpObject.open('GET', '/handler.php?option='&lt;br /&gt;        + selected.options[selected.selectedIndex].value);&lt;br /&gt;    httpObject.onreadystatechange = handleResponse;&lt;br /&gt;    httpObject.send(&lt;span style="color: blue;"&gt;null&lt;/span&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here I set onreadystatechange property &lt;b&gt;after&lt;/b&gt; initialization of HTTPRequest parameters. It is exactly what the script listed above shouts about.&lt;br /&gt;&lt;br /&gt;Currently this widget works in all browsers I know, including IE6 and IE7. You are welcome to use it in your web projects as well!&lt;br /&gt;&lt;br /&gt;Taking everything into consideration, listening to music is the best approach to bug fixing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5453912577685101694-6245596675045690915?l=intelrate.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://intelrate.blogspot.com/feeds/6245596675045690915/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5453912577685101694&amp;postID=6245596675045690915' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5453912577685101694/posts/default/6245596675045690915'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5453912577685101694/posts/default/6245596675045690915'/><link rel='alternate' type='text/html' href='http://intelrate.blogspot.com/2008/09/ajax-and-select-html-element-or-how-i.html' title='AJAX and Select HTML element or how I underestimated Internet Explorer.'/><author><name>Pavel</name><uri>http://www.blogger.com/profile/10052990641851592314</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_uX-JLRYgRwc/SM-CrBTJOnI/AAAAAAAAABc/TCwhs_jYxik/S220/intelrate_logo_90x90.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_uX-JLRYgRwc/SN-iOtTWUnI/AAAAAAAAACA/3YLkiQBEYjY/s72-c/selectElement.PNG' height='72' width='72'/><thr:total>0</thr:total></entry></feed>
