|
BPO Services
Our Products
FAQ
|
Should I consider AJAX?
Does AJAX work with Java?
Won't my framework provide me with AJAX?
Where should I start?
What do I need to know to create my own AJAX functionality?
Do I really need to learn JavaScript?
What JavaScript Libraries and Frameworks are out there to assist a Java developer?
Should I use XML or text, JavaScript, or HTML as a return type?
Are there usability issues with AJAX?
How do I debug JavaScript?
Should I use an HTTP GET or POST for my AJAX calls?
How do I provide internationalized AJAX interactions?
How do I handle concurrent AJAX requests?
What do I do on the server to interact with an AJAX client?
Where do I store state with an AJAX client?
How do I submit a form or a part of a form without a page refresh?
Is the server or the client in control?
Are there any security issues with AJAX?
When do I use a synchronous versus a asynchronous request?
What about applets and plugins?
How do I handle the back and forward buttons?
How do I send an image using AJAX?
How do I create a thread to do AJAX polling?
When should I use an Java applet instead of AJAX?
How do I access data from other domains to create a mashup with Java?
Does Java have support for Comet style server-side push?
Should
I consider AJAX? AJAX definitely has the buzz right now,
but it might not be the right thing for you. AJAX is limited
to the latest browsers, exposes browser compatibility issues,
and requires new skill-sets for many. There is a good blog
entry by Alex Bosworth on
AJAX
Mistakes which is a good read before you jump full force
into AJAX.
On the other hand you can achieve highly interactive rich
web applications that are responsive and appear
really
fast.
While it is debatable as to whether an AJAX based
application is really faster, the user feels a sense of immediacy
because they are given active feedback while data is exchanged
in the background. If you are an early adopter and can handle
the browser compatibility issues, and are willing to learn
some more skills, then AJAX is for you. It may be prudent
to start off AJAX-ifying a small portion or component of your
application first. We all love technology, but just remember
the purpose of AJAX is to enhance your user's experience and
not hinder it.
Does AJAX work with Java?
Absolutely. Java is a great fit for AJAX! You can use Java Enterprise
Edition servers to generate AJAX client pages and to serve
incoming AJAX requests, manage server side state for AJAX
clients, and connect AJAX clients to your enterprise resources.
The
JavaServer
Faces
component model is a great fit for defining and using AJAX components.
Won't my server-side framework provide me with AJAX?
You may be benefiting from AJAX already. Many existing Java
based frameworks already have some level of AJAX interactions
and new frameworks and component libraries are being developed
to provide better AJAX support. I won't list all the Java frameworks
that use AJAX here, out of fear of missing someone, but you
can find a good list at
www.ajaxpatterns.org/Java_Ajax_Frameworks.
If you have not chosen a framework yet it is recommended
you consider using
JavaServer
Faces or a JavaServer Faces based framework. JavaServer
Faces components can be created and used to abstract many
of the details of generating JavaScript, AJAX interactions,
and
DHTML
processing and thus enable simple AJAX used by JSF application
developer and as plug-ins in JSF compatible IDE's, such as
Sun
Java Studio Creator.
Where should I start?
Assuming the framework you are using does not suffice your
use cases and you would like to develop your own AJAX components
or functionality I suggest you start with the article Asynchronous
JavaScript Technology and XML (AJAX) With Java 2 Platform,
Enterprise Edition.
If you would like to see a very basic example that includes
source code you can check out the tech tip Using
AJAX with Java Technology. For a more complete list of
AJAX resources the Blueprints AJAX
Home page.
Next, I would recommend spending some time investigating
AJAX
libraries and frameworks. If you choose to write your
own AJAX clients-side script you are much better off not re-inventing
the wheel.
What do I need to know to create my own AJAX functionality?
If you plan not to reuse and existing AJAX component here
are some of the things you will need to know.
Plan to learn
Dynamic HTML (DHTML), the technology
that is the foundation for AJAX. DHTML enables browser-base
realtime interaction between a user and a web page. DHTML
is the combination of JavaScript, the Document Object Model
(DOM) and Cascading Style Sheets (CSS).
JavaScript
- JavaScript is a loosely typed object based scripting language
supported by all major browsers and essential for AJAX interactions.
JavaScript in a page is called when an event in a page occurs
such as a page load, a mouse click, or a key press in a
form element.
DOM
- An API for accessing and manipulating structured documents.
In most cases DOM represent the structure of XML and HTML
documents.
CSS
- Allows you to define the presentation of a page such as
fonts, colors, sizes, and positioning. CSS allow for a clear
separation of the presentation from the content and may
be changed programmatically by JavaScript.
Understanding the basic request/response nature of HTTP is also important.
Many subtle bugs can result if you ignore the differences
between the GET and OIst methods when configuring an XMLHttpRequest
and HTTP response codes when processing callbacks.
JavaScript is the client-side glue, in a sense. JavaScript
is used to create the XMLHttpRequest Object and trigger the
asynchronous call. JavaScript is used to parse the returned
content. JavaScript is used to analyze the returned data and
process returned messages. JavaScript is used to inject the
new content into the HTML using the DOM API and to modify
the CSS.
>Do I really need to learn JavaScript?
Basically yes if you plan to develop new AJAX functionality
for your web application.
On the other hand, JSF
components and component libraries can abstract the details
of JavaScript, DOM and CSS. These components can generate
the necessary artifacts to make AJAX interactions possible.
Visual tools such as Java Studio Creator may also use AJAX
enabled JSF components to create applications, shielding the
tool developer from many of the details of AJAX. If you plan
to develop your own JSF components or wire the events of components
together in a tool it is important that you have a basic understanding
of JavaScript. There are client-side JavaScript
libraries (discussed below) that you can call from your
in page JavaScript that abstract browser differences. Object
Hierarchy and Inheritance in JavaScript is a great resource
for a Java developer to learn about JavaScript objects.
What JavaScript libraries
and frameworks are available?
There are many libraries/frameworks out there (and many more
emerging) that will help abstract such things as all the nasty
browser differences. Three good libraries are The Dojo Toolkit,
Prototype, and DWR.
The Dojo Toolkit contains APIs and widgets
to support the development of rich web applications. Dojo
contains an intelligent packaging system, UI effects, drag
and drop APIs, widget APIs, event abstraction, client storage
APIs, and AJAX interaction APIs. Dojo solves common usability
issues such as support for dealing with the navigation such
as the ability to detect the browser back button, the ability
to support changes to the URL in the URL bar for bookmarking,
and the ability to gracefully degrade when AJAX/JavaScript
is not fully support on the client. Dojo is the Swiss Army
Knife of JavaScript libraries. It provides the widest range
of options in a single library and it does a very good job
supporting new and older browsers.
Prototype focuses on AJAX interactions
including a JavaScript AJAX object that contains a few objects
to do basic tasks such as make a request, update a portion
of a document, insert content into a document, and update
a portion of a document periodically. Prototype JavaScript
library contains a set of JavaScript objects for representing
AJAX requests and contains utility functions for accessing
in page components and DOM manipulations. Script.aculo.us
and Rico are built on top of Prototype and provide UI effects,
support for drag and drop, and include common JavaScript
centric widgets. If you are just looking to support AJAX
interactions and a few basic tasks Prototype is great. If
you are looking for UI effects Rico and Script.aculo.us
are good options.
Yahoo UI Library is a utility library
and set of widgets using the APIs to support rich clients.
The utility library includes support for cross-browser AJAX
interactions, animation, DOM scriptging support, drag and
drop, and cross browser event support. The Yahoo UI Library
is well documnented and contains many examples.
DWR (Dynamic Web Remoting) is a client-side
and server-side framework that focuses on allowing a developer
to do RPC calls from client-side JavaScript to plain old
Java objects in a Java Enterprise Edition web container.
On the server side DWR uses a Servlet to interact with the
Java objects and returns object representations of the Java
objects or XML documents. DWR will be easy to get up and
running and plays well with other Java technologies. If
you are looking for a client-side and server-side framework
that integrates well use DWR.
Google
Web Toolkit (GWT) is client/server framework provided
by Google that allows a developer to write an AJAX application
in pure Java. The GWT takes care of the details of generating
all the client-side code using a Java-to-JavaScript compiler.
One of the key benefits of the GWT Software Developer Kit
(SDK) is that it allows you to debug your applications in
what is known as GWT hosted mode using an embedded browser
(IE on Windows and Mozilla/Gecko on Linux) that is tied
to the toolkit. In GWT hosted mode you setup through the
code and debug it as it is running on both the client and
server. The GWT contains a default set of widgets and widget
containers. An application is built by coding a set of widgets
and containers together much like would be done in a Swing
application. The GWT Software Developer Kit (SDK) is limited
to Linux and Windows XP/2000 though the web applications
it generates are compatible with the latest generation of
the mainstream browsers.
There are many new and emerging libraries for JavaScript
and this list only reviews some of the more common libraries.
When making a choice choose the library which suites your
needs the best. While it might be better to choose one, there
is nothing stopping you from using more than one framework.
For a more extensive list of client-side frameworks see: Survey
of AJAX/JavaScript Libraries.
Should I use XML or text,
JavaScript, or HTML as a return type?
It depends. Clearly the 'X' in AJAX stands for XML, but several
AJAX proponents are quick to point out that nothing in AJAX,
per se, precludes using other types of payload, such as, JavaScript,
HTML, or plain text.
XML - Web Services and AJAX seem made for one another.
You can use client-side API's for downloading and parsing
the XML content from RESTful Web Services.
(However be mindful with some SOAP
based Web Services architectures the payloads can get quite
large and complex, and therefore may be inappropriate with
AJAX techniqes.)
Plain Text - In this case server-generated text may be
injected into a document or evaluated by client-side logic.
JavaScript - This is an extension to the plain text case
with the exception that a server-side component passes a
fragment of JavaScript including JavaScript object declarations.
Using the JavaScript eval() function you can
then create the objects on the client. JavaScript Object
Notation (JSON),
which is a JavaScript object based data exchange specification,
relies on this technique.
HTML - Injecting server-generated HTML fragments directly
into a document is generally a very effective AJAX technique.
However, it can be complicated keeping the server-side component
in sync with what is displayed on the client.
Mashup is a popular term for creating a completely new web
application by combining the content from disparate Web Services
and other online API's. A good example of a mashup is housingmaps.com
which graphically combines housing want-ads from craiglist.org
and maps from maps.google.com.
Are there Usability Issues
with AJAX?
The nature of updating a page dynamically using data retrieved
via AJAX interactions and DHTML may result in drastically
changing the appearance and state of a page. A user might
choose to use the browser's back or forward buttons, bookmark
a page, copy the URL from the URL bar and share it with a
friend via an email or chat client, or print a page at any
given time. When designing an AJAX based application you need
to consider what the expected behavior would be in the case
of navigation, bookmarking, printing, and browser support
as described below.
Navigation - What would be the expected behavior of the
back, forward, refresh, and bookmark browser buttons in
your application design. While you could implement history
manipulation manually it may be easer to use a JavaScript
frameworks such as Dojo that provides API's history manipulation
and navigation control.
Bookmarking and URL sharing - Many users want to bookmark
or cut and paste the URL from the browser bar. Dojo provides
client-side for bookmarking and URL manipulation.
Printing - In some cases printing dynamically rendered
pages can be problematic.
Other considerations as a developer when using AJAX are:
Browser Support - Not all AJAX/DHTML features are supported
on all browsers or all versions of a browser. See quirksmode.org for a list
of browser support and possible workarounds.
JavaScript disabled - You should also consider what happens
if the user disables JavaScript. Additionally, there are
several legitimate reasons why JavaScript and CSS support
may be unavailable on a user's web browser.
Latency - Keep in mind latency in your design. A running
application will be much more responsive than when it is
deployed. Also keep in mind that when making multiple requests
the return order is not guaranteed. For a more detailed
discussion on latency see AJAX
Latency problems: myth or reality?
Accessibility - Guaranteeing your site is accessible to
people with disabilities is not only a noble goal, it is
also requited by law in many markets. Some marvelous enabling
technology is available to help people use the Web in spite
of disabilities including visual, auditory, physical, speech,
cognitive, and neurological disabilities. With a little
forethought, and comprehension of some well documented best
practices, you can assure that your application is compatible
with that enabling technology.
Degradability is the term used to describe techniques used
by web applications to adapt to the wide range of web browser
capabilities. Many AJAX libraries have automatic degradability
built in. But if you are coding your own custom AJAX functionality,
simply taking some care to follow the best practices promoted
by standards bodies like the World Wide Web Consortium (W3C), and grass root movements like
the Web Standards community and many others,
your application can run usefully on browsers that are incapable
of AJAX behaviors. Granted, your application may loose some
of the "wow factor" on these less capable browsers, but your
application will still be usable.
Remember to not design with AJAX just for the sake of coolness.
The reason you built your application is so people will use
it. And people will not use your application if your application
is not compatible with their web browser.
How do I debug JavaScript?
There are not that many tools out there that will support
both client-side and server-side debugging. I am certain this
will change as AJAX applications proliferate. I currently
do my client-side and server-side debugging separately. Below
is some information on the client-side debuggers on some of
the commonly used browsers.
Firefox/Mozilla/Netscape - Have a built in debugger Venkman which
can be helpful but there is a Firefox add on known as FireBug which
provides all the information and AJAX developer would ever
need including the ability to inspect the browser DOM, console
access to the JavaScript runtime in the browser, and the
ability to see the HTTP requests and responses (including
those made by an XMLHttpRequest). I tend to develop my applications
initially on Firefox using Firebug then venture out to the
other browsers.
Safari - Has a debugger which needs to be enabled. See
the Safari
FAQ for details.
Internet Explorer - There is MSDN
Documentation on debugging JavaScript. A developer
toolbar for Internet Explorer may also be helpful.
While debuggers help a common technique knowing as "Alert
Debugging" may be used. In this case you place "alert()" function
calls inline much like you would a System.out.println. While
a little primitive it works for most basic cases. Some frameworks
such as Dojo provide APIs for tracking
debug statements.
Should I use an HTTP GET
or POST for my AJAX calls?
AJAX requests should use an HTTP GET request when retrieving
data where the data will not change for a given request URL.
An HTTP POST should be used when state is updated on the server.
This is in line with HTTP
idempotency recommendations and is highly recommended
for a consistent web application architecture.
How do I provide internationalized
AJAX interactions?
Just because you are using XML does not mean you can properly
send and receive localized content using AJAX requests. To
provide internationalized AJAX components you need to do the
following:
Set the charset of the page to an encoding that is supported
by your target languages. I tend to use UTF-8 because it
covers the most languages. The following meta declaration
in a HTML/JSP page will set the content type:
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
In the page JavaScript make sure to encode any parameters
sent to the server. JavaScript provides the escape()
function which returns Unicode escape strings in which localized
text will appear in hexadecimal format. For more details
on JavaScript encoding see Comparing
escape(), encodeURI(), and encodeURIComponent().
On the server-side component set the character encoding
using the HttpServletRequest.setCharacterEncoding() method.
Before you access the localized parameter using the HttpServletRequest.getParameter()
call. In the case of UTF this would be request.setCharactherEncoding("UTF-8");.
A server-side component returning AJAX responses needs to
set the encoding of the response to the same encoding used
in the page.
response.setContentType("text/xml;charset=;UTF-8");
response.getWriter().write("<response>invalid</response>");
For more information on using
AJAX with Java Enterprise Edition technologies see
AJAX
and Internationalization and for developing multi-lingual
applications see Developing
Multilingual Web Applications Using JavaServer Pages Technology.
How do I handle
concurrent AJAX requests?
With JavaScript you can have more than one AJAX request processing
at a single time. In order to insure the proper post processing
of code it is recommended that you use JavaScript
Closures. The example below shows an XMLHttpRequest object
abstracted by a JavaScript object called AJAXInteraction.
As arguments you pass in the URL to call and the function
to call when the processing is done.
function AJAXInteraction(url, callback) {
var req = init();
req.onreadystatechange = processRequest;
function init() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else if (window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}
function processRequest () {
if (req.readyState == 4) {
if (req.status == 200) {
if (callback) callback(req.responseXML);
}
}
}
this.doGet = function() {
req.open("GET", url, true);
req.send(null);
}
this.doPost = function(body) {
req.open("POST", url, true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.send(body);
}
}
function makeRequest() {
var ai = new AJAXInteraction("processme", function() {
alert("Doing Post Process");});
ai.doGet();
}
The function makeRequest()
in the example above creates an AJAXInteraction
with a URL to of "processme" and an inline function that will
show an alert dialog with the message "Doing Post Process".
When ai.doGet() is called the AJAX interaction
is initiated and when server-side component mapped to the
URL "processme" returns a document which is passed to the
callback function that was specified when the AJAXInteraction
was created.
Using this closures insures that the proper callback function
associated with a specific AJAX interaction is called. Caution
should still be taken when creating multiple closure objects
in that make XmlHttpRequests as to there is a limited number
of sockets that are used to make requests at any given time.
Because there are limited number of requests that can be made
concurrently. Internet Explorer for example only allows for
two concurrent AJAX
requests at any given time. Other browsers may allow more
but it is generally between three and five requests. You may
choose to use pool
of AJAXInteraction objects.
One thing to note when making multiple AJAX calls from the
client is that the calls are not guaranteed to return in any
given order. Having closures within the callback of a closure
object can be used to ensure dependencies are processed correctly.
There is a discussion titled Ajaxian
Fire and Forget Pattern that is helpful.
What do I do on
the server to interact with an AJAX client?
The "Content-Type" header needs to be set to"text/xml". In
servlets this may be done using the HttpServletResponse.setContentType()should
be set to "text/xml" when the return type is XML. Many XMLHttpRequest
implementations will result in an error if the "Content-Type"
header is set The code below shows how to set the "Content-Type".
response.setContentType("text/xml");
response.getWriter().write("<response>invalid</response>");
You may also want to set
whether or not to set the caches header for cases such as
autocomplete where you may want to notify proxy servers/and
browsers not to cache the results.
response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
response.getWriter().write("<response>invalid</response>");
Note to the developer: Internet Explorer will automatically
use a cached result of any AJAX response from a HTTP GET if
this header is not set which can make things difficult for a
developer. During development mode you may want set this header.
Where do I store state with
an AJAX client
As with other browser based web applications you have a few
options which include:
On the client in cookies - The size is limited (generally
around 4KB X 20 cookies per domain so a total of 80KB) and
the content may not be secure unless encrypted which is
difficult but not impossible using JavaScript.
On the client in the page - This can be done securely
but can be problematic and difficult to work with. See my
blog entry on Storing
State on the Client for more details on this topic.
On the client file system - This can be done if the client
grants access to the browser to write to the local file
system. Depending on your uses cases this may be necessary
but caution is advised.
On the Server - This is closer to the traditional model
where the client view is of the state on the server. Keeping
the data in sync can be a bit problematic and thus we have
a solution Refreshing
Data on this. As more information processing and control
moves to the client where state is stored will need to be
re-evaluated.
How do I submit a form
or a part of a form without a page refresh?
When creating a form make sure that the "form" element "onSubmit"
attribute is set to a JavaScript function that returns false.
<form onSubmit="doAJAXSubmit();return false;" >
<input type="text" id="tf1" />
<input type="submit" id="submit1" value="Update"/>
</>
You can also submit data by associating a function with a form
button in a similar way.
<form onSubmit="doAJAXSubmit();return false;" >
<input type="text" id="tf1" />
<input type="button" id="button1" onClick="doAJAXSubmit()" value="Update"/>
</>
Note that the form "onSubmit" attribute is still set. If the user
hits the enter key in the text field the form will be submitted
so you still need to handle that case.
When updating the page it is recommend you wait to make sure
that the AJAX update of the form data was successful before
updating the data in the page. Otherwise, the data may not
properly update and the user may not know. I like to provide
an informative message when doing a partial update and upon
a successful AJAX interaction I will then update the page.
Is the server or the client
in control?
It depends. With AJAX the answer is more in between. Control
can be more centralized in a server-side component or as a
mix of client-side and server-side controllers.
Centralized server-side controller - When having a more
centralized controller the key is to make sure the data
in client-side page is in sync with that of the server.
Some applications may keep all the state on the server and
push all updates to client DOM via a simple JavaScript controller.
Client and server-side controllers - This architecture
would use JavaScript to do all presentation related control,
event processing, page manipulation, and rendering of model
data on the client. The server-side would be responsible
for things such as business logic and pushing updated model
data to the client. In this case the server would not have
intimate knowledge of the presentation short of the initial
page that would be sent to the client page request.
There are some use cases where an entire AJAX application
can be written in a single page. Keep in mind if you choose
this type of architecture that navigation and bookmarking
should be considered.
Both methods are viable depending on what you are trying
to accomplish. I tend to prefer spreading the control across
the client and server.
Are there any security issues
with AJAX?
JavaScript is in plain view to the user with by selecting
view source of the page. JavaScript can not access the local
filesystem without the user's permission. An AJAX interaction
can only be made with the servers-side component from which
the page was loaded. A proxy pattern could be used for AJAX
interactions with external services.
You need to be careful not to expose your application model
in such as way that your server-side components are at risk
if a nefarious user to reverse engineer your application.
As with any other web application, consider using HTTPS to
secure the connection when confidential information is being
exchanged.
When do I use a synchronous
versus a asynchronous request?
Good question. They don't call it AJAX for nothing! A synchronous
request would block in page event processing and I don't see
many use cases where a synchronous request is preferable.
What about applets and plugins?
Don't be too quick to dump your plugin or applet based portions
of your application. While AJAX and DHTML can do drag and
drop and other advanced user interfaces there still limitations
especially when it comes to browser support. Plugins and applets
have been around for a while and have been able to make AJAX
like requests for years. Applets provide a great set of UI
components and APIs that provide developers literally anything.
Many people disregard applets or plugins because there is
a startup time to initialize the plugin and there is no guarantee
that the needed version of a plugin of JVM is installed. Plugins
and applets may not be as capable of manipulating the page
DOM. If you are in a uniform environment or can depend on
a specific JVM or plugin version being available (such as
in a corporate environment) a plugin or applet solution is
great.
One thing to consider is a mix of AJAX and applets or plugins.
Flickr uses a combination of
AJAX interactions/DHTML for labeling pictures and user interaction
and a plugin for manipulating photos and photo sets to provide
a great user experience. If you design your server-side components
well they can talk to both types of clients.
How do I handle the back
and forward buttons?
While you could go out and create a custom solution that
tracks the current state on your application I recommend you
leave this to the experts. Dojo addresses the navigation in a browser neutral way as can
be seen in the JavaScript example below.
function updateOnServer(oldId, oldValue, itemId, itemValue) {
var bindArgs = {
url: "faces/ajax-dlabel-update",
method: "post",
content: {"component-id": itemId, "component-value": itemValue},
mimetype: "text/xml",
load: function(type, data) {
processUpdateResponse(data);
},
backButton: function() {
alert("old itemid was " + oldId);
},
forwardButton: function(){
alert("forward we must go!");
}
};
dojo.io.bind(bindArgs);
}
The example above will update a
value on the server using dojo.io.bind() with a function as
a property that is responsible for dealing with the browser
back button event. As a developer you are capable of restoring
the value to the oldValue or taking any other action that
you see fit. The underlying details of how the how the browser
button event are detected are hidden from the developer by
Dojo.
AJAX:
How to Handle Bookmarks and Back Buttons details this
problem and provides a JavaScript library Really Simple History
framework (RSH) that focuses just on the back and forward
issue.
How do I send an image using
AJAX?
While it may appear that images are being sent when using
AJAX with an application like Google
Maps what is really happening is that the URLs of images
are being send as the response of an AJAX request and those
URLs are being set using DHTML.
In this example an XML document is returned from an AJAX
interaction and the category bar is populated.
<categories>
<category>
<cat-id>1</cat-id>
<name>Books</name>
<description>Fun to read</description>
<image-url>books_icon.gif</image-url>
</category>
<category>
<cat-id>2</cat-id>
<name>Electronics</name>
<description>Must have gadgets</description>
<image-url>electronics.gif</image-url>
</category>
</categories>
Notice that the image-url element contains the
location of the URL for the image representing a category.
The callback method of an AJAX interaction will parse the
response XML document and call the addCategory
function for each category included in the response XML document.
The addCategory function looks up a table row
element "categoryTable" in body of the page and adds a row
to the element which contains the image.
<scrip type="text/javascript" >
...
function addCategory(id, name, imageSrc) {
var categoryTable = document.getElementById("categoryTable");
var row = document.createElement("tr");
var catCell = document.createElement("td");
var img = document.createElement("img");
img.src = ("images\\" + imageSrc);
var link = document.createElement("a");
link.className ="category";
link.appendChild(document.createTextNode(name));
link.setAttribute("onclick", "catalog?command=category&catid=" + id);
catCell.appendChild(img);
catCell.appendChild(link);
row.appendChild(catCell);
categoryTable.appendChild(row);
}
</script>
...
<table>
<tr>
<td width="300" bgoclor="lightGray">
<table id="categoryTable" border="0" cellpadding="0"></table>
</td>
<td id="body" width="100%">Body Here</td>
</tr>
</table>
Note that the source of the image is set to the image source.
The image is loaded by a subsequent HTTP request for the image
at the URL "images/books_icon.gif" or "images/electronic_icon.gif"
that occurs when the img element is added to the categoryTable.
How do I create a thread
to do AJAX polling?
JavaScript does not have threads. JavaScript functions are
called when an event happens in a page such as the page is
loaded, a mouse click, or a form element gains focus. You
can create a timer using the setTimeout which
takes a function name and time in milliseconds as arguments.
You can then loop by calling the same function as can be seen
in the JavaScript example below.
function checkForMessage() {
// start AJAX interaction with processCallback as the callback function
}
// callback for the request
function processCallback() {
// do post processing
setTimeout("checkForMessage()", 10000);
}
Notice that the checkForMessage will continue
to loop indefinitely. You may want to vary the increment the
interval based on activity in the page or your use cases.
You may also choose to have logic that would break out of
the loop based on some AJAX response processing condition.
When should I use an Java
applet instead of AJAX?
Applets provide a rich experience on the client side and
there are many things they can do that an AJAX application
cannot do, such as custom data streaming, graphic manipulation,
threading, and advanced GUIs. While DHTML with the use of
AJAX has been able to push the boundaries on what you can
do on the client, there are some things that it just cannot
do. The reason AJAX is so popular is that it only requires
functionality built into the browser (namely DHTML and AJAX
capabilities). The user does not need to download and/or configure
plugins. It is easy to incrementally update functionality
and know that that functionality will readily available, and
there are not any complicated deployment issues. That said,
AJAX-based functionality does need to take browser differences
into consideration. This is why we recommend using a JavaScript
library such as Dojo which abstracts browser differences.
So the "bottom line" is: If you are creating advanced UIs
where you need more advanced features on the client where
you want UI accuracy down to the pixel, to do complex computations
on the client, use specialized networking techniques, and
where you know that the applet plugin is available for your
target audience, applets are the way to go. AJAX/DHTML works
well for applications where you know the users are using the
latest generation of browsers, where DHTML/AJAX "good enough"
for you, and where your developers have JavaScript/DHTML/AJAX
skills. Many amazing things can be done with AJAX/DHTML but
there are limitations. AJAX and applets can be used together
in the same UIs with AJAX providing the basic structure and
applets providing more advanced functionality. The Java can
communicate to JavaScript using the Live-Connect
APIs. The question should not be should framed as do I
use AJAX or applets, but rather which technology makes the
best sense for what you are doing. AJAX and applets do not
have to be mutually exclusive.
How do I access data
from other domains to create a mashup with Java?
From your JavaScript clients you can access data in other
domains if the return data is provide in JSON format. In essence
you can create a JavaScript client that runs operates using
data from a different server. This technique is know as JSON
with Padding or JSONP. There are questions as to whether
this method is secure as you are retrieving data from outside
your domain and allowing it to be excuted in the context of
your domain. Not all data from third parties is accessible
as JSON and in some cases you may want an extra level of protection.
With Java you can provide a proxy to third party services
using a web component such as a servlet. This proxy can manage
the communication with a third party service and provide the
data to your clients in a format of your choosing. You can
also cache data at your proxy and reduce trips to service.
For more on using a Java proxy to create mashups see
The
XmlHttpProxy Client for Java.
Does Java have support for Comet
style server-side push?
Current AJAX applications use polling to communicate changes
data between the server and client. Some applications, such
as chat applications, stock tickers, or score boards require
more immediate notifications of updates to the client.
Comet
is an event based low latency server side push for AJAX applications.
Comet communication keeps one of the two connections available
to the browser open to continously communicate events from the
server to the client. A Java based solution for Comet is being
developed for Glassfish on top of the Grizzly HTTP connector.
|
What releases of Java technology are currently available? What do they contain?
What platforms is the JDK software available
on?
Should I use the Production Release or Reference
Implementation of the Solaris JDK software and JRE?
What about a version for my favorite platform? When can I get it?
How do I download Java technology and/or
JDK software? How do I install it?
Where can I find information about HotJava?
How can I get started with programming in
Java?
Do I need special server software to use
applets?
Who is licensing Java technology?
Is JavaScript available? How do I find
out more about it?
What are the security problems I've heard
about JavaScript scripts?
I can't find the API documentation on
any classes in the sun.* packages.
Why developers should not write programs that call 'sun' packages
Where can I get the Java programming language
source code?
What releases of Java technology are currently available?
What do they contain?
The Java programming language is currently shipping from Sun Microsystems, Inc. as the Java 2 SDK and Java 2 Runtime
Environment. (http://java.sun.com/j2se/).
Each release of the Java 2 SDK, Standard Edition contains:
Java Compiler
Java Virtual Machine*
Java Class Libraries
Java AppletViewer
Java Debugger and other tools
Documentation (in a separate download bundle)
To run Java 1.0 applets, use Netscape Navigator
3.x or other browsers that support Java applets. To run Java
1.1.x applets, use HotJava 1.x or Netscape Navigator 4.x or
other browsers that support the newest version of the Java API.
What platforms is the
Java-technology software available on?
Sun provides ports of the Java 2 Platform for Windows 95, Windows 98, Windows NT, Windows 2000, Solaris-SPARC, Solaris-Intel, and Linux.
Should I use the Production Release or Reference Implementation of the Solaris JDK software and JRE?
The following applies to versions prior to 1.3.0. Starting with J2SE 1.3.0, only the production release exists.
There is no Solaris reference implementation.
Reference Implementation - Those who
want the latest Solaris implementation of the JDK software
or JRE release and do not require optimized performance can
obtain the reference implementations:
JDK 1.1 Reference Implementation
JRE 1.1 Reference Implementation
JDK 1.2 Reference Implementation
JRE 1.2 Reference Implementation
The Solaris binaries are built from the same source code as
the Windows version. The 1.1 reference implementations for
Solaris do not include a JIT. Reference implementations are
distributed as (essentially) a tar file which may be unpacked
in any directory, so that root permission is not required
for installation.
Production Release - In contrast, customers
whose applications/applets will be released as products, and
who need a Solaris JRE or JDK software with optimized performance,
should use the Solaris production releases:
JDK production release
JRE production release
The production releases are based on the reference implementation
of the same version number, and include a JIT compiler, additional
performance tuning, and bug fixes. The production releases
are installed as standard Solaris packages, which require
root permission for installation.
Varying levels of technical support are available
for both the Reference and Production releases through the
standard Solaris support channels.
For a further overview of differences between
these Solaris JDK software offerings, see JDK
1.1 for Solaris - Binary Products Overview
What about a version
for my favorite platform? When can I get it?
These are extremely popular and important questions.
What we can currently say is:
Amiga, NeXT, OS/2, Windows 3.1, Windows 32s, Macintosh, ...
http://java.sun.com/cgi-bin/java-ports.cgi)
How do I download Java
technology and/or Java 2 SDK software? How do I install it?
You can get our releases either with a World
Wide Web (WWW) browser or by anonymous ftp. For details, including
installation instructions, visit:
The Java 2 Platform web site (http://java.sun.com/j2se/)
Choose the software you want, and go from there.
Where can I find
information about HotJava browser?
The current version of HotJava browser is 1.1Beta1
and is available at HotJava. This page has
links to an email address for comments and to HotJava browser
known bugs.
How can I get started
programming in the Java programming language?
See our page which can guide you in the right direction:
Getting
Started with Java technology.
Do I need special server software to use applets?
No. Java applets may be served by any HTTP server.
On the server side they are handled the same as any other
file, such as a text, image, or sound file. All the special
action happens when the applet class files are interpreted
on the client side by a Java technology-enabled browser, such
as HotJava browser or 1.x or Netscape 3.x/4.x.
Who is licensing Java technology?
See our "Who's Licensing Java?" page:
Who's
Licensing Java?
(http://java.sun.com/licensees.html)
Is JavaScript technology
available? How do I find out more about it?
The initial version of the JavaScript technology
is available in current releases of Netscape Navigator 3.x.
What are the security
problems I've heard about JavaScript technology scripts?
JavaScript technology is a scripting language
used with Netscape Navigator. There have been reports of privacy
problems with JavaScript technology, and Netscape is committed
to addressing those concerns. JavaScript technology cannot
be used to invoke Java applets. The privacy problems reported
with JavaScript technology are not present in Java applets.
I can't find the
API documentation on any classes in the sun.* packages. Where
is it?
The short answer is that we provide documentation
only for the public classes in java.*. We do not provide documentation
for sun.* because those are the Sun-specific implementation,
and specifically not part of the Java technology API standard,
and are therefore subject to change without notice.
In general, we don't provide javadoc documentation
for sun.* classes in order to discourage developers from writing
programs that use them. For further explanation, see the next
question.
However, if you must have it, the documentation
for sun.* is available in the doc comments in the community
source code release available separately, mentioned in question
Why developers
should not write programs that call 'sun' packages
Java Software supports into the future only
classes in java.* packages, not sun.* packages. In general,
API in sun.* is subject to change at any time without notice
Where can I get
the Java programming language source code?
Java Software has two separate bundles of source
code that you can obtain at no charge:
The Java 2 SDK, Standard Edition itself contains a file
called src.zip that contains the source code
for the public classes in the java package.
Because this does not contain sun.* classes, you cannot
do a complete build of the Java technology from these source
files. These source files are for your information, to supplement
the documentation, so you can see how Java technology works.
|
Introduction
What are the standards?
W3C Standards
What is the W3C
What does it do?
What are the W3C standards?
HTML 4.0
XML 1.0
XHTML 1.0, 1.1, XHTML Modularization
CSS - Cascading Stylesheets
DOM
ECMA Standards
What is the ECMA?
What does it do?
What are the ECMA standards?
ECMAScript
What are the advantages of using Standards?
Accessibility
To software/machines
To people
Stability
Conclusions
Introduction
Tim Berners-Lee’s dream for his invention, the World Wide Web,
is a common space where users can share in formation to work together, to play, and to socialize .
As web developers, creating business, social, and educational
sites, we turn this dream in to reality.
But in this period of tremendous growth, the Web needs guidance
to realize its full potential.web standards are this guidance. These standards help ensure that
everyone has access to the information we are provid in g,
and also make web development faster and more enjoyable.
Standards compliance makes it easier for people with special
needs to use the Web. Blind people may have their computer
read web pages to them. People with poor eyesight may have
pages rearranged and magnified for easier reading. And people
using hand-held devices can browse the Web
just as easily as those using high-end
workstations.
As we will explain, there are also
many
practical reasons
for developers to be concerned with web standards.
Search engines can do a better job of indexing sites, for
example. Using browser-specific code often doubles or triples
the work to create Web pages, and leaves a lot to be desired when new media are
introduced. This situation will
only get worse without the sound direction of Web
standards.
Some people fear that standards are limiting. In reality,
they remove much of the tedious labour involved in Web
development, and give developers more time and more flexibility
to be truly creative. They are both open to future improvement
and mindful of past technology.
Many uses of the Web, including some that are only dreamed
of today, will not be possible, or will be more difficult,
without widespread standards compliance. At the moment, there
are systems and software that are very common, seemingly close
to universal, but who knows what tomorrow will bring? Tying
ourselves to the control of any single company means limiting
our future to the fortunes and misfortunes which that one
company can or will provide. Maintaining universal standards
will allow the Web to survive while
encouraging innovation to continue
at its current pace.
What are the standards?
2.1 W3C Standards
What is the W3C?
The World Wide Web Consortium (W3C)
is an international industry consortium
dedicated to “leading the Web to its full potential“.
It’s led by Tim Berners-Lee, the inventor of the Web. Founded in 1994, the W3C has
more than 450 member organizations - including
Microsoft, America Online
(parent company of Netscape
Communications), Apple
Computer, Adobe, Macromedia, Sun Microsystems, and a variety
of other hardware and software manufacturers, content providers,
academic institutions, and telecommunications companies.
What does it do?
The W3C develops open specifications (de facto standards)
to enhance the interoperability of web-related products. W3C
Recommendations are developed by working groups consisting
of Consortium members and invited experts. Working groups
obtain general consensus from companies and other organizations
involved in creating applications for the Web,
and create Working Drafts and Proposed Recommendations. These
are then submitted to the W3C membership and director, for
formal approval as W3C Recommendations. More information regarding
this process and the review stages can be obtained from the
W3C Website.
What are the W3C standards?
HTML 4.0 - HyperText Markup Language
HyperText Markup Language (HTML) is widely used on the Web for adding structure to text documents. Browsers interpret
these documents, representing the structure in media-specific ways to the user. For example, visual browsers
typically display the strong element (<strong>
… </strong>) as bold text, while
text-to-speech readers might emphasize that text when pronouncing it.
With the help of Cascading
Style Sheets (CSS) the author may define how structural
elements are to be represented, overriding
the browser defaults.
XML 1.0 - Extensible Markup Language
Example of part of an XML document
<addressbook>
<entry>
<name>Bill Gates</name>
<email>bgates@microsoft.com</email>
</entry>
<entry>
<name>Marc Andreesen</name>
<email>marca@netscape.com</email>
</entry>
<entry>
<name>Jon S. von Tetzchner</name>
<email>jon@opera.com</email>
</entry>
</addressbook>
Extensible Markup Language (XML) is a markup language like
HTML, but instead of having a single, fixed set of elements,
it allows you to define your own - or use a set made by someone
else. It even allows using multiple sets within a single document
- by using XML
namespaces.
Some applications of XML, such as XHTML and MathML, have already
become W3C Recommendations. Others are currently W3C Working
Drafts.
Style sheet standards, such as CSS and XSL, offer a variety
of options for specifying how XML elements are to be rendered.
Standards-compliant support for direct rendering of XML is
spotty in browsers, so for presenting information to humans,
HTML (or XHTML) with CSS-driven styling is the way to go.
XML is mostly used for machine-to-machine
communication today.
XML is more flexible than HTML, primarily because of the
ability to add your own elements and make your own structural
systems. This makes it an ideal format for the organization
of large quantities of data - it is already in use in many
databases and search engines.
XHTML 1.0, 1.1, and Modularization
XHTML 1.0 is a reformulation of HTML as an XML application.
XHTML 1.0 can be seen as ideologically coming from HTML 4.01,
and being technically stricter because of XML’s influence.
XHTML will display in your browser identically to the equivalent
HTML. You might want to use XHTML if there is any chance you’re
going to need to reprocess your content, for example to send
it to a PDA; XML’s stricter syntax rules make automatic
processing of XHTML much easier and cheaper than ordinary HTML.
Ideologically, XHTML 1.0 inherits the following
general concepts from HTML 4.01:
That presentation and document formatting
should be separated via style sheets
That documents should be made accessible
That documents should be internationalized
<
XHTML 1.0 also uses the model of three DTDs: Strict, Transitional,
and Frameset. This model originally emerged in
HTML 4.0 and followed through to HTML 4.01.
Some important technical practices from XML onto XHTML includes:
That all document types are declared via the correct DOCTYPE
declaration
That the structure of a conforming document contain the
DOCTYPE declaration, an html element with the XHTML namespace
declared, a head element including the title element, and a body element
That all elements and attribute names are written in lower case, and that all attribute values are quoted
That all non-empty elements (e.g. p, li) are properly
terminated with a closing tag
That all empty elements (e.g. br, hr, img) are properly
terminated with a trailing slash
(<br />)
That documents validate against
the DTD that is declared
HTML 1.1 is made up of three primary parts:
The XHTML 1.0 Strict DTD (with minor
modifications)
XHTML Modularization
The Ruby Annotation
If you’d like to author documents in XHTML 1.1, you
can do so in a couple of ways. The first is by using the public
XHTML 1.1 DTD. By doing this, your work will be extremely
structured because there are virtually no presentational attributes
in XHTML 1.1. The separation of structure and presentation
is complete here, and all of your presentation work will go
in a style sheet.
Another means of authoring documents in XHTML 1.1 is to tap
into XHTML Modularization. This is the breakdown of familiar
components of HTML and XHTML (such as text, tables, frames,
forms) into discrete chunks. You can then write your own DTD
and use only those components you require. This is extensibility
in action, essentially giving you,
the Web author, the opportunity to customize your markup.
The Ruby Annotation is a special means of dealing with certain
Asian character annotations. Ruby falls under the work being
done with internationalization.
CSS - Cascading Style Sheets
Cascading Style Sheets (CSS) is a mechanism for changing the appearance of HTML or XML elements, by assigning styles to element types, self-defined
classes of elements or individual instances.
Stylesheets can be used to consistently define the appearance
of an entire site. Following the introduction of CSS, the
W3C recommended that layout-specific features in HTML be phased
out and replaced by stylesheets, creating
a simpler and more structural World Wide Web.
DOM 1 - Document Object Model
Level 1
The DOM allows the full power and interactivity of a scripting language (such as ECMAScript, the
standardized version of JavaScript) to be exerted on a web
page. (In programming terms, the Document Object Model (DOM)
Level 1 is an Application Programming Interface (API) for
interacting with Web pages.) It
gives the scripting language easy access to the structure,
content, and presentation of a document which is written in
such languages as HTML and CSS.
The DOM is compatible with future improvements in technology;
it will allow any scripting language to interact with whatever
languages are being used in the document. This standard will
not only make it easier to program dynamic HTML, but will
also make adapting to future Internet technology much less
painful.
ECMA Standards
What is the ECMA?
The European
Computer Manufacturers Association (ECMA) is an organization
officially founded in 1961 in order to meet the need for standardizing
computer operational formats, including programming languages
and input/output codes.
The ECMA is based in Geneva, Switzerland,
near the headquarters of the international Organization for Standardization (ISO) and
the international
Electrotechnical Commission (IEC). In 1994, the organization’s
name was changed to the ECMA - European Association for Standardizing
Information and Communication Systems, in
order to reflect its broader range of activities.
What does it do?
The main role of the ECMA is to develop Standards and Technical
Reports in the area of information and communication technology.
As ECMA is an association of companies and not an official
standardization institute, they often collaborate with official
national or international institutes.
ECMA Standards have been accepted as a base for international and European standards
Of these standards 85 have been accepted as international standards by the international
Organization for Standardization (ISO). in
addition, 25 have been accepted as European standards by the
European Telecommunications Standards
institute (ETSI).
What are the ECMA standards?
ECMAScript (standardized JavaScript)
ECMAScript is a standardized scripting
language, based largely on Netscape’s JavaScript and
Microsoft’s JScript. The ECMAScript standard is defined
by ECMA’s Technical Committee 39 (TC-39).
The main use of ECMAScript, which is an object-based language,
is to manipulate the objects in
Web pages which are specified by the Document Object Model (DOM). These objects (effectively, the
elements which make up web pages, or the web pages as a wholes)
can then be added to, deleted, moved, or have their properties
changed. This lets Web developers implement such effects as animated text, graphic
roll-overs, and pages that change based on user input without
having to be reloaded.
The current ECMAScript specification is ECMA Standard ECMA-262,
ECMAScript
Language Specification, 2nd edition.
What are the advantages of using Web standards?
Accessibility
Software / machines
Complying with web standards can give your web pages greater
visibility in Web searches. The
structural information present in compliant documents makes
it easy for search engines to access and evaluate the information
in those documents, and they get indexed
more accurately.
Because use of Web standards makes
it easier for server-side as well as client-side software
to understand the structure of your document, adding a search
engine to your own site becomes
easier and gives better results.
Standards are written so that old browsers will still understand
the basic structure of your documents. Even if they can’t
understand the newest and coolest additions to the standards,
they’ll be able to display the content of your site.
The same, of course, applies to robots - systems that collect
information from your site on behalf of search engines and
other indexers.
Compliant code gives you the opportunity of validating your
page with a validation service. Validators process your documents
and present you with a list of errors. This makes finding
and correcting errors a lot easier,
and can save you a lot of time.
Compliant documents can easily be converted to other formats,
such as databases or Word documents. This allows for more
versatile use of the information within documents on the World
Wide Web, and simplified migration
to new systems - hardware as well as software - including
devices such as TVs and PDAs.
To people
Accessibility
is an important idea behind many
Web standards, especially HTML.
Not only does this mean allowing the web to be used by people
with disabilities, but also allowing web pages to be understood
by people using browsers other than the usual ones - including
voice browsers that read Web pages aloud to people with sight impairments, Braille
browsers that translate text into
Braille, hand-held browsers with very little monitor space,
teletext displays, and other unusual output devices.
As the variety of web access methods increases, adjusting
or duplicating Websites to satisfy
all needs will become increasingly difficult (indeed, some
say it’s impossible even today). Following standards
is a major step towards solving this problem. Making
your sites standards-compliant will help ensure not only that
traditional browsers, old and new, will all be able to present
sites properly, but also that they will work with unusual
browsers and media.
Some consequences of ignoring standards are obvious: the
most basic consequence is that you will restrict access to
your site. How much business sense does it make to limit your
audience to only a fraction of those who wish be a part of
it? For a business site, denying access to even small portions
of a target audience can make a big difference to your profit
margin. For an educational site, it makes sense to allow access
not only to affluent, able-bodied school-children with graphical
browsers, but also to children in regions with poorly-developed
infrastructure who are best served by text-only browsing,
or disabled students using specialized
browsers.
The same principle applies to all types of Websites
— while straying from the standards and taking advantage
of browser-specific features may be tempting, the increased
accessibility which comes from standards-compliance will lead
to far greater rewards in the long run.
Stability
Most Web standards are generally
designed with forward- and backward-compatibility in mind
— so that data using old versions of the standards will
continue to work in new browsers, and data using new versions
of the standards will “gracefully degrade” to
produce an acceptable result in older browsers.
Because a Website may go through
several teams of designers during
its lifetime, it is important that those people are able to
comprehend the code and to edit it easily. Web standards offer
a set of rules that every Web developer
can follow, understand, and become familiar with: When one
developer designs a site to the standards, another will be
able to pick up where the former left off.
Conclusion
As web developers, we are constantly trying to address the
problem of inconsistencies between the renderings of Web
pages by different browsers and browser versions. This necessitates
either time-consuming double/multiple coding, or coding for
a single browser which makes it
harder, if not impossible, for some of the public to use the
site. This situation will be made even worse with the advent
of additional hardware and software which will be able to
browse the Web, such as telephones, pagers, and PDAs.
Web standards are not arcane laws
decreed by ivory-tower organizations. , the standards are
for the most part decided by representatives of the same people
who use them — browser makers, Web
developers, content providers, and other organizations.
Writing Web pages in accordance
with the standards shortens site development time and makes
pages easier to maintain. Debugging and troubleshooting become
easier, because the code follows a standard. No longer do
you have to worry about the coding and maintenance
for several versions of code that are supposed to accomplish
the same presentation.One version of your site,
and that is it.
The universal adoption of Web standards
is becoming of paramount importance.
The mission of The Web Standards
Project is to make the Web a better place, for developers
and for end-users, by encouraging browser and Web
page editor makers to follow the standards in
their applications. This effort will be greatly helped when
Web developers use the
standards as a matter of course, and insist that generators and renderers of their code comply
with the standards.
The reasons we have given should give you,
the Web developer, plenty of incentive to begin using standards,
and also plenty of ammunition with which you can encourage
your place of business and fellow
developers to use those standards.
|
What are Cascading Style Sheets?
Why do style sheets exist?
Why use style sheets?
Who defines the CSS standard? Is it one person? A company?
What can be done with style sheets that can not be accomplished with regular HTML?
Is there anything that CAN'T be replaced by style sheets?
How do I design for backward compatibility using style sheets?
What browsers support style sheets? To what extent?
Do any WYSIWYG editors support creation of CSS? Any text editors?
Can you use someone's style sheet without permission?
What does the "Cascading" in "Cascading Style Sheets" mean?
Which style specification method should be used? Why?
What are the advantages and disadvantages of the various style specification methods?
As a reader, how can I make my browser recognize my own style sheet?
How do you override the underlining of hyperlinks?
1. What are Cascading Style Sheets?
A Cascading Style Sheet (CSS) is a list of statements
(also known as rules) that can assign various rendering
properties to HTML elements. Style rules can be specified
for a single element occurrence, multiple elements, an entire
document, or even multiple documents at once. It is possible
to specify many different rules for an element in different
locations using different methods. All these rules are collected
and merged (known as a "cascading" of styles)
when the document is rendered to form a single style rule
for each element.
2. Why do style sheets exist?
SGML (of which HTML is a derivative) was meant to be a
device-independent method for conveying a document's structural
and semantic content (its meaning.) It was never meant to
convey physical formatting information. HTML has crossed
this line and now contains many elements and attributes
which specify visual style and formatting information. One
of the main reasons for style sheets is to stop the creation
of new HTML physical formatting constructs and once again
separate style information from document content.
3. Why use Style Sheets?
Style sheets allow a much greater degree of layout and
display control than has ever been possible thus far in
HTML. The amount of format coding necessary to control display
characteristics can be greatly reduced through the use of
external style sheets which can be used by a group of documents.
Also, multiple style sheets can be integrated from different
sources to form a cohesive tapestry of styles for a document.
Style sheets are also backward compatible - They can be
mixed with HTML styling elements and attributes so that
older browsers can view content as intended.
4. Who defines the CSS standard? Is
it one person? A company?
The W3C
(the organization in charge of defining the HTML standards)
creates and develops the CSS specifications with public
input from the W3C www-style mailing list discussion forum
and feedback from the member companies that comprise the
W3C Consortium (which include companies such as Apple, Microsoft,
and Netscape along with over 150 others.)
The "Cascading
Style Sheets Level 1" recommendation is edited
and maintained by Håkon Lie and Bert Bos of the W3C.
The CSS2
recommendation is is edited and maintained by Håkon
Lie, Bert Bos, Chris Lilley and Ian Jacobs.
5. What can be done with style sheets
that can not be accomplished with regular HTML?
Many of the recent extensions to HTML have been tentative
and somewhat crude attempts to control document layout.
Style sheets go several steps beyond, and introduces complex
border, margin and spacing control to most HTML elements.
It also extends the capabilities introduced by most of the
existing HTML browser extensions. Background colors or images
can now be assigned to ANY HTML element instead
of just the BODY element and borders can now be applied
to any element instead of just to tables. For more information
on the possible properties in CSS, see the Index DOT Css
Property Index.
6. Is there anything that CAN'T
be replaced by Style Sheets?
Quite a bit actually. Style sheets only specify information
that controls display and rendering information. Virtual
style elements that convey the NATURE of the content can
not be replaced by style sheets, and hyperlinking and multimedia
object insertion is not a part of style sheet functionality
at all (although controlling how those objects appear IS
part of style sheets functionality.) The CSS1 specification
has gone out of its way to absorb ALL of the HTML
functionality used in controlling display and layout characteristics.
For more information on the possible properties in CSS,
see the Index DOT Css Property Index.
Rule of Thumb:if an HTML element or
attribute gives cues as to how its contents should be displayed,
then some or all of its functionality has been absorbed
by style sheets.
7. How do I design for backward compatibility
using Style Sheets?
Existing HTML style methods (such as <font
SIZE > and <b>)
may be easily combined with style sheet specification methods.
Browsers that do not understand style sheets will use the
older HTML formatting methods, and style sheets specifications
can control the appearance of these elements in browsers
that support CSS1.
8. What browsers support style sheets?
To what extent?
Microsoft's Internet Explorer version 3.0 Beta 2 and above
supports CSS, as does Netscape Communicator 4.0 Beta 2 and
above and Opera 3.5 and above. Take note that the early
implementations in these browsers did not support ALL
of the properties and syntax described in the full CSS1
specification and beyond. Later versions have been getting
much closer to full CSS1 compliance, but then comes the
next hurdle - CSS2...it was such a big leap over CSS1 that
it has taken the browsers years to come close to supporting
a majority of CSS2's features. Mozilla and Opera's current
versions both offer excellent CSS standards compliance.
The Macintosh version of Internet Explorer is said to be
very impressive in its CSS capabilities as well, but PC
IE lags behind these implementations. Quite a few other
implementations of CSS now exist in browsers that are not
as widely-used (such as Amaya, Arena and Emacs-W3), but
coverage of features in these documents currently only covers
Internet Explorer, NCSA Mosaic, Netscape and Opera browsers.
9. Do any WYSIWYG editors support
the creation of Style Sheets? Any text-based HTML editors?
As support for CSS in browsers has matured in the last
year, both WYSIWYG and Text-based HTML editors have appeared
that allow the creation or the assistance of creating Cascading
Style Sheet syntax. There are now at least two dozen editors
supporting CSS syntax in some form.
10. Can you use someone else's Style
Sheet without permission?
This is a somewhat fuzzy issue. As with HTML tags, style
sheet information is given using a special language syntax.
Use of the language is not copyrighted, and the syntax itself
does not convey any content - only rendering information.
It is not a great idea to reference an external style sheet
on someone else's server. Doing this is like referencing
an in-line image from someone else's server in your HTML
document. This can end up overloading a server if too many
pages all over the net reference the same item. It can't
hurt to contact the author of a style sheet, if known, to
discuss using the style sheet, but this may not be possible.
In any case, a local copy should be created and used instead
of referencing a remote copy.
11. What does the "Cascading"
in "Cascading Style Sheets" mean?
Style Sheets allow style information to be specified from
many locations. Multiple (partial) external style sheets
can be referenced to reduce redundancy, and both authors
as well as readers can specify style preferences. In addition,
three main methods can be employed by an author to add style
information to HTML documents, and multiple approaches for
style control are available in each of these methods. In
the end, style can be specified for a single element using
any, or all, of these methods. What style is to be used
when there is a direct conflict between style specifications
for an element?
Cascading comes to the rescue. A document can have styles
specified using all of these methods, but all the information
will be reduced to a single, cohesive "virtual"
Style Sheet. Conflict resolution is based on each style
rule having an assigned weight according to its importance
in the scheme of things. A rule with a higher overall importance
will carry a higher weight. This will be used in place of
a competing style rule with a lower weight/importance. A
hierarchy of competing styles is thus formed creating a
"cascade" of styles according to their assigned
weights. The algorithm used to determine this cascading
weight scale is fairly complex.
For more information, see the section on cascading in the
CSS1
Specification.
12. Which style specification method
should be used? Why?
The answer to this one is tricky. The short answer is:
"it depends." The long answer is, however, another
story.
If you are planning on using more than one style specification
method in your document, you must also worry about Cascading
Order of Style methods (see question 11.)
If you are going to use only one method, then some guidelines
about the nature of each method need to be kept in mind.
The answer to this question is also very much related to
the advantages and disadvantages to using each of them (next
question.)
Method 1: External Style Sheets (The
LINK
[-->Index DOT Html] element)
This method should be used if you want to apply the same
style to multiple documents. Each document can reference
the stand-alone style sheet and use the styles contained
within. Using this method, the appearance of many documents
can be controlled using a single or small number of style
sheets. This can save a LOT of time for an author.
Method 2: Embedded Style Sheets (The
Style
[-->Index DOT Html] element)
The syntax used with Method 2 is the same as that for
Method 1. This method is a happy medium between External
Style Sheets and Inline Styles (see below.). It should be
used in place of Method 1 if you only want to specify styles
for a single document. This method should also be used when
you want to specify a style for multiple tag types at once
or the list of style definitions is of larger size.
Method 3: Inline Styles (STYLE attribute
to HTML elements)
If you only have to apply style to one or a few elements
in a single document, your best bet will often be an Inline
Style. This method attaches a style definition within the
HTML element it is modifying.
13. What are the advantages/disadvantages
of the various style methods?
Each method of specifying style information has something
going for it (else it would not exist), but each method
also has drawbacks as well. This question is very closely
related to the previous question.
These factors should be considered when planning your use
of Style Sheets.
External Style Sheets
Advantages
- Can control styles for multiple documents
at once
- Classes can be created for use on multiple
HTML element types in many documents
- Selector and grouping methods can be
used to apply styles under complex contexts
Disadvantages
- An extra download is required to import
style information for each document
- The rendering of the document may be
delayed until the external style sheet is loaded
- Becomes slightly unwieldy for small quantities
of style definitions
Embedded Style Sheets
Advantages
- Classes can be created for use on multiple
tag types in the document
- Selector and grouping methods can be
used to apply styles under complex contexts
- No additional downloads necessary to
receive style information
Disadvantages
- This method can not control styles for
multiple documents at once
Inline Styles
Advantages
- Useful for small quantities of style
definitions
- Can override other style specification
methods at the local level so only exceptions need to
be listed in conjunction with other style methods
Disadvantages
- Does not distance style information from
content (a main goal of SGML/HTML)
- Can not control styles for multiple documents
at once
- Author can not create or control classes
of elements to control multiple element types within
the document
- Selector grouping methods can not be
used to create complex element addressing scenarios
14. As a reader, how can I make my
browser recognize my own style sheet?
Netscape
It is not possible to do this in Netscape yet (as of version
4.0.)
Internet Explorer 3.0 (Win95/NT) [It is possible to do this at least in Windows95/NT, but
no user interface is provided. Unknown how this might be
accomplished on other operating systems.]
- Open the Registry editor (Start..Run..regedit..ENTER)
- Under the 'HKEY_LOCAL_MACHINE\Software\Microsoft\InternetExplorer\Styles'
key, Edit..New..String Value
- The new value should be called 'StyleSheet Pathname'
- For the value, type in the full directory path of
your .css style sheet.
Internet Explorer 4.0 (Win95/NT)
- Under the View menu, select 'Internet Options'.
- Under the 'General' tab, choose the 'Accessibility'
button.
- Choose the 'Format documents using my style sheet'
check box and 'Browse...' to the location of your .css
style sheet.
15. How do you override the underlining
of hyperlinks?
CSS has the ability to explicitly control the status of
underlining for an element - even for hyperlinks. The correct
way to do this in an external or document-level style sheet
is:
A { text-decoration:
none }
and within an anchor element as:
<a HREF="example.htm"
STYLE="text-decoration: none">link text</a>
Note: The underlining of hyperlinks
is a long-standing visual convention that assists in the
visual identification of active hyperlink areas. Many users
expect to see hyperlinks underlined and may be
confused and/or irritated if they are not used. User-defined
style sheets address this user need by allowing the user
to have final control over this feature. Unfortunately,
wide support for this ability does not yet exist.
|
Don't depend on initialization?
Limit access to your classes, methods, and variables?
Make everything final (unless there's a good reason not to)?
Don't depend on package scope?
Don't use inner classes?
Avoid signing your code?
If you must sign your code, put it all in one archive file?
Making classes noncloneable?
Making classes nonserializeable?
Making classes nondeserializeable?
Comparison of classes by name?
Don't depend on initialization
Most
Java developers think there is no way to allocate an
object without running a constructor. But this isn't
true: there are several ways to allocate noninitialized
objects.
The easy way to protect yourself against this problem
is to write your classes so that before any object does
anything, it verifies that it has been initialized.
You can do this as follows:
1.Make all variables private. If you want to allow outside
code to access variables in an object, this should be
done via get and set methods. (This keeps outside code
from accessing noninitialized variables.) If you're
following Rule 3, you'll make the get and set methods
final.
2.Add a new private boolean variable, initialized, to
each object.
3. Have each constructor set the initialized variable
as its last action before returning.
4. Have each nonconstructor method verify that initialized
is true before doing anything. (Note that you may have
to make exceptions to this rule for methods 5. 5. called
by your constructors. If you do this, it's best to make
the constructors call only private methods.)
If your class has a static initializer, you will need
to do the same thing at the class level. Specifically,
for any class that has a static initializer, follow
these steps:
1. Make all static variables private. If you want to
allow outside code to access static variables in the
class, this should be done via static get and set methods.
This keeps outside code from accessing noninitialized
static variables. If you're following Rule 3, you'll
make the get and set methods final.
2. Add a new private static boolean variable, classInitialized,
to the class.
3. Have the static constructor set the initialized variable
as its last action before returning.
4.Before doing anything, have each static method and
each constructor verify that classInitialized is true.
(Note: constructors are required to call a constructor
of the superclass, or another constructor of the same
class, as their first action. So you will have to do
that before you check classInitialized.)
Limit access to your classes, methods, and variables
Every class, method, and variable that
is not private provides a potential entry point for an
attacker. By default, everything should be private. Make
something nonprivate only with good reason, and document
that reason.
Make everything final (unless there's a good reason not to)
If a class or method isn't final, an attacker
could try to extend it in a dangerous and unforeseen way.
By default, everything should be final. Make something
nonfinal only if there is a good reason, and document
that reason.
You might think you can prevent an attacker from extending
your class or its methods by declaring the class nonpublic.
But if a class isn't public, it must be accessible from
within the same package, and as Rule 4 (below) says, you
shouldn't to rely on package scope access restrictions
for security.
This advice may seem harsh. After all, the rule is asking
you to give up extensibility, which is one of the main
benefits of using an object-oriented language like Java.
But when you're trying to provide security, extensibility
is your enemy: it just provides an attacker with more
ways to cause trouble.
Don't depend
on package scope
Classes, methods, and variables that aren't
explicitly labeled as public, private, or protected are
accessible within the same package. Don't rely on this
for security. Java classes aren't closed, so an attacker
could introduce a new class into your package and use
this new class to access the things you thought you were
hiding. (A few packages, such as java.lang, are closed
by default, and a few Java virtual machines (JVMs) let
you close your own packages. But you're better off assuming
packages aren't closed.)
Package scope makes a lot of sense from a software-engineering
standpoint, since it prevents innocent, accidental access
to things you want to hide. But don't depend on it for
security
Don't use inner classes
Some Java language books say only the outer
classes that enclose them can access inner classes. But
this isn't true. Java byte code has no concept of inner
classes, so inner the compiler into ordinary classes that
happen to be accessible to any code in the same package
translates classes. And Rule 4 says not to depend on package
scope for protection.
But wait, it gets worse. An inner class gets access to
the fields of the enclosing outer class, even if the fields
are declared private. And the inner class is translated
into a separate class. To let this separate class access
the fields of the outer class, the compiler silently changes
these fields from private to package scope! It's bad enough
that the inner class is exposed; but it's even worse that
the compiler is silently overruling your decision to make
some fields private. Don't use inner classes if you can
help it. (Ironically, the new JDK 1.2 PrivilegedAction
API requires you to use an inner class to write privileged
code. For more details, see our book Securing Java and
the developer.com article referenced below.) That's one
reason we don't like the PrivilegedAction API.)
Avoid signing your code
Code that isn't signed will run without
any special privileges. And code with no special privileges
is much less likely to do damage.
Of course, some of your code might have to acquire and
use privileges to perform some dangerous operation. Work
hard to minimize the amount of privileged code, and audit
the privileged code more carefully than the rest.
If you
must sign your code, put it all in one archive file
By following this rule, you will help prevent
an attacker from carrying out a mix-and-match attack,
in which the attacker constructs a new applet or library
that links some of your signed classes together with malicious
classes, or links together signed classes that you never
meant to be used together. By signing a group of classes
together, you make such attacks more difficult. Existing
code-signing systems do an inadequate job of preventing
mix-and-match attacks, so this rule cannot prevent such
attacks completely. But using a single archive can't hurt.
Some code-signing systems let you examine other classes
to see who signed them. If you're using a code-signing
system that allows this, you can put code into the static
constructors of your classes to verify that the "surrounding"
classes have been signed by the expected person.
This measure doesn't completely prevent mix-and-match
attacks, since an adversary can still mix together classes
you signed at different times -- for example, by mixing
version 1 of Class A with version 2 of Class B. If you're
worried about this kind of inter-version mix-and-match
attack, you can put each class's "version stamp"
in a public final variable, and then have each class check
the version stamps of its surrounding classes
Make
your classes noncloneable
Java's object cloning mechanism can
allow an attacker to manufacture new instances of classes
you define, without executing any of your constructors.
If your class isn't cloneable, the attacker can define
a subclass of your class, and make the subclass implement
java.lang.Cloneable. This lets an attacker create new
instances of your class. The new instances are made
by copying the memory images of existing objects; though
this is sometimes an acceptable way to make a new object,
it often is not.
Rather than worry about this, you're better off making
your objects noncloneable. You can do this by defining
the following method in each of your classes:
public final void clone() throws java.lang.CloneNotSupportedException
{
throw new java.lang.CloneNotSupportedException();
}
If you want your class to be cloneable, and you've considered
the
consequences of that choice, then you can still protect
yourself. If you're
defining a clone method yourself, make it final. If
you're relying on a
nonfinal clone method in one of your superclasses, then
define this
method:
public final void clone() throws java.lang.CloneNotSupportedException
{
super.clone();
}
Make your
classes nonserializeable
Serialization is dangerous because it
allows adversaries to get their hands on the internal
state of your objects. An adversary can serialize one
of your objects into a byte array that can be read.
This allows the adversary to inspect the full internal
state of your object, including any fields you marked
private, and including the internal state of any objects
you reference.
To prevent this, you can make your object impossible
to serialize. To achieve this goal, declare the writeObject
method:
private final void writeObject(ObjectOutputStream out)
throws java.io.IOException {
throw new java.io.IOException("Object cannot be serialized");
}
This method is declared final so that a subclass defined
by the adversary cannot override it
Make your
classes nondeserializeable
This rule is even more important than
the previous one. Even if your class isn't serializeable,
it may still be deserializeable. An adversary can create
a sequence of bytes that happens to deserialize to an
instance of your class. This is dangerous, since you
do not have control over what state the deserialized
object is in. You can think of deserialization as another
kind of public constructor for your object; unfortunately
it's a kind of constructor that is difficult for you
to control.
You can prevent this kind of attack by making it impossible
to deserialize a byte stream into an instance of your
class. You can do this by declaring the readObject method:
private final void readObject(ObjectInputStream in)
throws java.io.IOException {
throw new java.io.IOException("Class cannot be deserialized");
}
As above, this method is declared final to prevent the
adversary from overriding it
Don't
compare classes by name
Sometimes you want to compare the classes
of two objects to see whether they are the same; or you
want to see whether an object has a particular class.
When you do this, be aware that there can be multiple
classes with the same name in a JVM. It is a mistake to
compare classes by name since different classes can have
the same name. A better method is to compare class objects
for equality directly. For example, given two objects,
A and B, if you want to see whether they are the same
class, use this code.
|
A simple event handler to display cut/copy/paste events
A simple frame containing a "toolbar" made up of several java.awt.Button objects (ToolbarFrame)
GuiScreens
AlignmentExample
DynamicIconExample
HtmlLabel
ProgressBarExample
ProgressMonitorInputExample
SplashScreen
ThumbNailFileView
RoundedLineBorder
Add a background image in JTable
Adding a row
Dynamically compute and display the column total in a cell
Sorting the table
Use different fonts in different cells
Display any JComponent in a cell
ASCII Value Table
A simple event handler to display cut/copy/paste events
/*CCPHandler.java
A simple event handler to display cut / copy / paste events.
*/
import java.awt.event.*;
public class CCPHandler implements ActionListener
{
public final static String CUT = "cut";
public final static String COPY = "copy";
public final static String PASTE = "paste";
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if (command == CUT) { // We can do this since we're
comparing constants.
System.out.println("Got Cut event");
}
else if (command == COPY) {
System.out.println("Got Copy event");
}
else if (command == PASTE) {
System.out.println("Got Paste event");
}
}
}
ToolbarFrame
/* ToolbarFrame.java
A simple frame containing a "toolbar" made
up of several java.awt.Button
objects. We'll be converting the Buttons to JButtons in the
ToolbarFrame2.java file.
*/
import java.awt.*;
import java.awt.event.*;
public class ToolbarFrame1 extends Frame {
Button cutButton, copyButton, pasteButton;
public ToolbarFrame1() {
super("Toolbar Example (AWT)");
setSize(450, 250);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
ActionListener printListener = new ActionListener()
{
public void actionPerformed(ActionEvent ae) {
System.out.println(ae.getActionCommand());
}
};
Panel toolbar = new Panel();
toolbar.setLayout(new FlowLayout(FlowLayout.LEFT));
cutButton = new Button("Cut");
cutButton.addActionListener(printListener);
toolbar.add(cutButton);
copyButton = new Button("Copy");
copyButton.addActionListener(printListener);
toolbar.add(copyButton);
pasteButton = new Button("Paste");
pasteButton.addActionListener(printListener);
toolbar.add(pasteButton);
// The "preferred" BorderLayout add call
add(toolbar, BorderLayout.NORTH);
}
public static void main(String args[]) {
ToolbarFrame1 tf1 = new ToolbarFrame1();
tf1.setVisible(true);
}
}
GuiScreens
/* GuiScreens.java
A quick utility to print out graphic device information.
Will work on
systems with multiple monitors.
*/
import java.awt.*;
import javax.swing.*;
public class GuiScreens {
public static void main(String[] args) {
Rectangle virtualBounds = new Rectangle();
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gs = ge.getScreenDevices();
JFrame frame[][] = new JFrame[gs.length][];
for (int j = 0; j < gs.length; j++) {
GraphicsDevice gd = gs[j];
System.out.println("Device " + j + ":
" + gd);
GraphicsConfiguration[] gc = gd.getConfigurations();
frame[j] = new JFrame[gc.length];
for (int i=0; i < gc.length; i++) {
System.out.println(" Configuration " + i +
": " + gc[i]);
System.out.println(" Bounds: " + gc[i].getBounds());
virtualBounds = virtualBounds.union(gc[i].getBounds());
frame[j][i] = new JFrame("Config: " + i, gc[i]);
frame[j][i].setBounds(50, 50, 400, 100);
frame[j][i].setLocation(
(int)gc[i].getBounds().getX() + 50,
(int)gc[i].getBounds().getY() + 50);
frame[j][i].getContentPane().add(new JTextArea("Config:\n"
+ gc[i]));
frame[j][i].setVisible(true);
}
System.out.println("Overall bounds: " + virtualBounds);
}
}
}
AlignmentExample
/* AlignmentExample.java
A simple demonstration of text alignment in JLabels.
*/
import javax.swing.*;
import java.awt.*;
public class AlignmentExample {
public static void main(String[] args) {
// Create the labels and set alignment
JLabel label1 = new JLabel("BottomRight",
SwingConstants.RIGHT);
JLabel label2 = new JLabel("CenterLeft", SwingConstants.LEFT);
JLabel label3 = new JLabel("TopCenter", SwingConstants.CENTER);
label1.setVerticalAlignment(SwingConstants.BOTTOM);
label2.setVerticalAlignment(SwingConstants.CENTER);
label3.setVerticalAlignment(SwingConstants.TOP);
// Add borders to the labels . . . more on Borders
later in the book!
label1.setBorder(BorderFactory.createLineBorder(Color.black));
label2.setBorder(BorderFactory.createLineBorder(Color.black));
label3.setBorder(BorderFactory.createLineBorder(Color.black));
// Put it all together . . .
JFrame frame = new JFrame("AlignmentExample");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p = new JPanel(new GridLayout(3, 1, 8, 8));
p.add(label1);
p.add(label2);
p.add(label3);
p.setBorder(BorderFactory.createEmptyBorder(8, 8, 8,
8));
frame.setContentPane(p);
frame.setSize(200,200);
frame.setVisible(true);
}
}
DynamicIconExample
/* DynamicIconExample.java
Example of an icon that changes form.
*/
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
public class DynamicIconExample {
public static void main(String[] args) {
// Create a couple of sliders to control the icon size.
final JSlider width = new JSlider(JSlider.HORIZONTAL,
1, 150, 75);
final JSlider height = new JSlider(JSlider.VERTICAL,
1, 150, 75);
// A little icon class that uses the current slider values.
class DynamicIcon implements Icon {
public int getIconWidth() { return width.getValue();
}
public int getIconHeight() { return height.getValue();
}
public void paintIcon(Component c, Graphics g, int
x, int y) {
g.fill3DRect(x, y, getIconWidth(), getIconHeight(),
true);
}
};
Icon icon = new DynamicIcon();
final JLabel dynamicLabel = new JLabel(icon);
// A listener to repaint the icon when sliders are
adjusted.
class Updater implements ChangeListener {
public void stateChanged(ChangeEvent ev) {
dynamicLabel.repaint();
}
};
Updater updater = new Updater();
width.addChangeListener(updater);
height.addChangeListener(updater);
// Lay it all out.
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container c = f.getContentPane();
c.setLayout(new BorderLayout());
c.add(width, BorderLayout.NORTH);
c.add(height, BorderLayout.WEST);
c.add(dynamicLabel, BorderLayout.CENTER);
f.setSize(210,210);
f.setVisible(true);
}
}
HtmlLabel
/* HtmlLabel.java
A JLabel that uses inline HTML to format its text.
*/
import javax.swing.*;
public class HtmlLabel extends JPanel {
public static final String markup = "line 1"
+ "big blue line 2 line 3";
public static void main(String argv[]) {
JPanel p = new JPanel(new java.awt.GridLayout(0, 1));
p.add(new JLabel(markup)); p.add(new java.awt.Label(markup));
JFrame f = new JFrame("HtmlLabel");
f.setContentPane(p); f.setSize(600, 200);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
ProgressBarExample
/* ProgressBarExample.java
A demonstration of the JProgressBar component. The component tracks the
progress of a for loop.
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ProgressBarExample extends JPanel {
JProgressBar pbar;
static final int MY_MINIMUM=0;
static final int MY_MAXIMUM=100;
public ProgressBarExample() {
pbar = new JProgressBar();
pbar.setMinimum(MY_MINIMUM);
pbar.setMaximum(MY_MAXIMUM);
add(pbar);
}
public void updateBar(int newValue) {
pbar.setValue(newValue);
}
public static void main(String args[]) {
final ProgressBarExample it = new ProgressBarExample();
JFrame frame = new JFrame("Progress Bar Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(it);
frame.pack();
frame.setVisible(true);
for (int i = MY_MINIMUM; i <= MY_MAXIMUM; i++)
{
final int percent=i;
try {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
it.updateBar(percent);
}
});
java.lang.Thread.sleep(100);
} catch (InterruptedException e) {;}
}
}
}
ProgressMonitorInputExample
/* ProgressMonitorInputExample.java
Simpilar to the ProgressMonitorExample except that we can now use an
actual input file to monitor rather than inducing progress manually.
The file to load should be passed as a command line argument.
*/
import java.io.*;
import java.awt.*;
import javax.swing.*;
public class ProgressMonitorInputExample {
public ProgressMonitorInputExample(String filename)
{
ProgressMonitorInputStream monitor;
try {
monitor = new ProgressMonitorInputStream(
null, "Loading "+filename, new FileInputStream(filename));
while (monitor.available() > 0) {
byte[] data = new byte[38];
monitor.read(data);
System.out.write(data);
}
} catch (FileNotFoundException e) {
JOptionPane.showMessageDialog(null, "Unable to
find file: "
+ filename, "Error", JOptionPane.ERROR_MESSAGE);
} catch (IOException e) {;}
}
public static void main(String args[]) {
new ProgressMonitorInputExample(args[0]);
}
}
SplashScreen
/* SplashScreen.java
A simple application to show a title screen in the center of the screen
for the amount of time given in the constructor. This class includes
a sample main() method to test the splash screen, but it's meant for use
with other applications.
*/
import java.awt.*;
import javax.swing.*;
public class SplashScreen extends JWindow {
private int duration;
public SplashScreen(int d) {
duration = d;
}
// A simple little method to show a title screen in
the center
// of the screen for the amount of time given in the
constructor
public void showSplash() {
JPanel content = (JPanel)getContentPane();
content.setBackground(Color.white);
// Set the window's bounds, centering the window
int width = 450;
int height =115;
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
int x = (screen.width-width)/2;
int y = (screen.height-height)/2;
setBounds(x,y,width,height);
// Build the splash screen
JLabel label = new JLabel(new ImageIcon("oreilly.gif"));
JLabel copyrt = new JLabel
("Copyright 2002, O'Reilly & Associates",
JLabel.CENTER);
copyrt.setFont(new Font("Sans-Serif", Font.BOLD,
12));
content.add(label, BorderLayout.CENTER);
content.add(copyrt, BorderLayout.SOUTH);
Color oraRed = new Color(156, 20, 20, 255);
content.setBorder(BorderFactory.createLineBorder(oraRed,
10));
// Display it
setVisible(true);
// Wait a little while, maybe while loading resources
try { Thread.sleep(duration); } catch (Exception e)
{}
setVisible(false);
}
public void showSplashAndExit() {
showSplash();
System.exit(0);
}
public static void main(String[] args) {
// Throw a nice little title page up on the screen first
SplashScreen splash = new SplashScreen(10000);
// Normally, we'd call splash.showSplash() and get on
with the program.
// But, since this is only a test...
splash.showSplashAndExit();
}
}
ThumbNailFileView
/* ThumbNailFileView.java
A simple implementation of the FileView class that
provides a 16x16 image of
each GIF or JPG file for its icon. This could be
SLOW for large images, as we
simply load the real image and then scale it.
*/
import java.io.File;
import java.awt.*;
import javax.swing.*;
import javax.swing.filechooser.*;
import javax.swing.plaf.metal.MetalIconFactory;
public class ThumbNailFileView extends FileView {
private Icon fileIcon = MetalIconFactory.getTreeLeafIcon();
private Icon folderIcon = MetalIconFactory.getTreeFolderIcon();
private Component observer;
public ThumbNailFileView(Component c) {
// We need a component around to create our icon’s
image
observer = c;
}
public String getDescription(File f) {
// We won’t store individual descriptions,
so just return the
// type description.
return getTypeDescription(f);
}
public Icon getIcon(File f) {
// Is it a folder?
if (f.isDirectory()) { return folderIcon; }
// Ok, it’s a file, so return a
custom icon if it’s an image file
String name = f.getName().toLowerCase();
if (name.endsWith(".jpg") || name.endsWith(".gif"))
{
return new Icon16(f.getAbsolutePath());
}
// Return the generic file icon if it’s
not
return fileIcon;
}
public String getName(File f) {
String name = f.getName();
return name.equals("") ? f.getPath() : name;
}
public String getTypeDescription(File f) {
String name = f.getName().toLowerCase();
if (f.isDirectory()) { return "Folder"; }
if (name.endsWith(".jpg")) { return "JPEG
Image"; }
if (name.endsWith(".gif")) { return "GIF
Image"; }
return "Generic File";
}
public Boolean isTraversable(File f) {
// We’ll mark all directories as
traversable
return f.isDirectory() ? Boolean.TRUE : Boolean.FALSE;
}
public class Icon16 extends ImageIcon {
public Icon16(String f) {
super(f);
Image i = observer.createImage(16, 16);
i.getGraphics().drawImage(getImage(), 0, 0, 16, 16,
observer);
setImage(i);
}
public int getIconHeight() { return 16; }
public int getIconWidth() { return 16; }
public void paintIcon(Component c, Graphics g, int x,
int y) {
g.drawImage(getImage(), x, y, c);
}
}
}
RoundedLineBorder
/* RoundedLineBorder.java
A simple demontstration of the LineBorder class built with rounded
corners.
*/
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
public class RoundedLineBorder extends JPanel {
public RoundedLineBorder() {
super(true);
setLayout(new BorderLayout());
JLabel label = new JLabel("Rounded Corners");
label.setHorizontalAlignment(JLabel.CENTER);
LineBorder line = new LineBorder(Color.blue, 2, true);
label.setBorder(line);
add(label, BorderLayout.CENTER);
}
public static void main(String s[]) {
JFrame frame = new JFrame("Rounded Line Border");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 200);
frame.setContentPane(new RoundedLineBorder());
frame.setVisible(true);
}
}
Add a background image in JTable
/* File: Table.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public class Table
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Table");
frame.addWindowListener( new WindowAdapter() {
public void windowClosing(WindowEvent e)
{
Window win = e.getWindow();
win.setVisible(false);
win.dispose();
System.exit(0);
}
} );
// Create your own sub-class of JTable rather than using
anonymous class
JTable table = new JTable( 15, 3 )
{
public Component prepareRenderer(TableCellRenderer renderer,
int row, int column)
{
Component c = super.prepareRenderer( renderer, row,
column);
// We want renderer component to be transparent so background
image is visible
if( c instanceof JComponent )
((JComponent)c).setOpaque(false);
return c;
}
};
// Use our version of JScrollPane
MyScrollPane sp = new MyScrollPane( table );
// Set the background image
ImageIcon image = new ImageIcon( "codeguruwm.gif"
);
sp.setBackgroundImage( image );
frame.getContentPane().add( sp );
frame.pack();
frame.show();
}
}
// File: MyScrollPane.java
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.metal.*;
import com.sun.java.swing.plaf.motif.*;
import com.sun.java.swing.plaf.windows.*;
class MyScrollPane extends JScrollPane
{
public MyScrollPane(Component view, int vsbPolicy, int
hsbPolicy)
{
super( view, vsbPolicy, hsbPolicy );
// Set the component to transparent
if( view instanceof JComponent )
((JComponent)view).setOpaque(false);
}
public MyScrollPane(Component view)
{
this(view, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
}
public MyScrollPane(int vsbPolicy, int hsbPolicy)
{
this(null, vsbPolicy, hsbPolicy);
}
public MyScrollPane()
{
this(null, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
}
public void paint(Graphics g)
{
if( image != null )
{
// Draw the background image
Rectangle d = getViewport().getViewRect();
for( int x = 0; x < d.width; x += image.getIconWidth()
)
for( int y = 0; y < d.height; y += image.getIconHeight()
)
g.drawImage( image.getImage(), x, y, null, null );
// Do not use cached image for scrolling
getViewport().setBackingStoreEnabled(false);
}
super.paint( g );
}
public void setBackgroundImage( ImageIcon image )
{
this.image = image;
}
ImageIcon image = null;
}
Adding a row
Note that if you are using your own subclass of AbstractTableModel(),
this doesn't apply to you. Your TableModel should provide
such a feature.
Here's the code snippet you can use to insert a blank
row at the end of the table.
if( table.getModel() instanceof DefaultTableModel )
{
int cols = table.getModel().getColumnCount();
((DefaultTableModel)table.getModel()).addRow(new Object[cols]);
}
In the code above, we make a check whether the table
model is an instance of a DefaultTableModel. This is
required because when you create JTable giving it initial
data, Swing creates an anonymous subclass of AbstractTableModel.
If you are using your own TableModel, make sure that
addRow() is supported.
Dynamically compute and display the column total in a cell
/*File: TotalRowExample.java
package jp.gr.java_conf.tame.swing.examples;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.text.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;
class DecimalRenderer extends DefaultTableCellRenderer
{
DecimalFormat formatter;
DecimalRenderer(String pattern) {
this(new DecimalFormat(pattern));
}
DecimalRenderer(DecimalFormat formatter) {
this.formatter = formatter;
setHorizontalAlignment(JLabel.RIGHT);
}
public void setValue(Object value) {
setText((value == null) ? ""
: formatter.format(((Double)value).doubleValue()));
}
}
public class TotalRowExample extends JFrame {
final private int TOTAL_ROW = 3;
final private int TOTAL_COLUMN = 1;
TotalRowExample() {
super( "Total Row Example" );
final DecimalFormat formatter = new DecimalFormat("###,##0.00");
DefaultTableModel dm = new DefaultTableModel() {
public void setValueAt(Object value, int row, int col)
{
Vector rowVector = (Vector)dataVector.elementAt(row);
if (col == TOTAL_COLUMN) {
Double d = null;
if (value instanceof Double) {
d = (Double)value;
} else {
try {
d = new Double(
((Number)formatter.parse((String)value)).doubleValue());
} catch (ParseException ex) {
d = new Double(0.0);
}
}
rowVector.setElementAt(d, col);
} else {
rowVector.setElementAt(value, col);
}
}
public boolean isCellEditable(int row, int col) {
if (row == TOTAL_ROW) return false;
return true;
}
public Class getColumnClass(int col) {
if (col == TOTAL_COLUMN) return Number.class;
return String.class;
}
};
dm.setDataVector(
new Object[][]{
{"coffee",new Double(0.0)},
{"tea" ,new Double(0.0)},
{"cocoa" ,new Double(0.0)},
{"total" ,new Double(0.0)}},
new Object[]{"Item","Price"});
JTable table = new JTable( dm ) {
public void editingStopped(ChangeEvent e) {
super.editingStopped(e);
reCalcurate(getModel());
repaint();
}
};
table.getColumn("Price").setCellRenderer(
new DecimalRenderer(formatter));
JScrollPane scroll = new JScrollPane(table);
Container content = getContentPane();
content.add(scroll);
setSize( 300, 120 );
setVisible(true);
}
private void reCalcurate(TableModel ml) {
if (ml == null) return;
double total = 0.0;
for (int i=0;i<TOTAL_ROW;i++) {
total += ((Double)ml.getValueAt(i,TOTAL_COLUMN)).doubleValue();
}
ml.setValueAt(new Double(total),TOTAL_ROW,TOTAL_COLUMN);
}
public static void main(String[] args) {
TotalRowExample frame = new TotalRowExample();
frame.addWindowListener( new WindowAdapter() {
public void windowClosing( WindowEvent e ) {
System.exit(0);
}
});
}
}
Sorting the table
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.text.*;
import javax.swing.*;
import javax.swing.table.*;
public class SortableTableExample extends JPanel {
public SortableTableExample(){
setLayout(new BorderLayout());
String[] headerStr = {"Name","Date","Size","Dir"};
int[] columnWidth = {100,150,100,50};
SortableTableModel dm = new SortableTableModel() {
public Class getColumnClass(int col) {
switch (col) {
case 0: return String.class;
case 1: return Date.class;
case 2: return Integer.class;
case 3: return Boolean.class;
default: return Object.class;
}
}
public boolean isCellEditable(int row, int col) {
switch (col) {
case 1: return false;
default: return true;
}
}
public void setValueAt(Object obj, int row, int col)
{
switch (col) {
case 2: super.setValueAt(new Integer(obj.toString()),
row, col); return;
default: super.setValueAt(obj, row, col); return;
}
}
};
dm.setDataVector(new Object[][]{
{"b" ,getDate("98/12/02"),new Integer(14),new
Boolean(false)},
{"a" ,getDate("99/01/01"),new Integer(67),new
Boolean(false)},
{"d" ,getDate("99/02/11"),new Integer(2)
,new Boolean(false)},
{"c" ,getDate("99/02/27"),new Integer(7)
,new Boolean(false)},
{"foo" ,new Date() ,new Integer(5) ,new Boolean(true)},
{"bar" ,new Date() ,new Integer(10),new Boolean(true)}},
headerStr);
JTable table = new JTable(dm);
//table.setShowGrid(false);
table.setShowVerticalLines(true);
table.setShowHorizontalLines(false);
SortButtonRenderer renderer = new SortButtonRenderer();
TableColumnModel model = table.getColumnModel();
int n = headerStr.length;
for (int i=0;i<n;i++) {
model.getColumn(i).setHeaderRenderer(renderer);
model.getColumn(i).setPreferredWidth(columnWidth[i]);
}
JTableHeader header = table.getTableHeader();
header.addMouseListener(new HeaderListener(header,renderer));
JScrollPane pane = new JScrollPane(table);
add(pane, BorderLayout.CENTER);
}
public static void main(String[] args) {
JFrame f= new JFrame("SortableTable Example");
f.getContentPane().add(new SortableTableExample(), BorderLayout.CENTER);
f.setSize(400, 160);
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}
});
}
private static DateFormat dateFormat =
DateFormat.getDateInstance(DateFormat.SHORT, Locale.JAPAN);
private static Date getDate(String dateString) {
Date date = null;
try {
date = dateFormat.parse(dateString);
} catch(ParseException ex) {
date = new Date();
}
return date;
}
class HeaderListener extends MouseAdapter {
JTableHeader header;
SortButtonRenderer renderer;
HeaderListener(JTableHeader header,SortButtonRenderer
renderer) {
this.header = header;
this.renderer = renderer;
}
public void mousePressed(MouseEvent e) {
int col = header.columnAtPoint(e.getPoint());
int sortCol = header.getTable().convertColumnIndexToModel(col);
renderer.setPressedColumn(col);
renderer.setSelectedColumn(col);
header.repaint();
if (header.getTable().isEditing()) {
header.getTable().getCellEditor().stopCellEditing();
}
boolean isAscent;
if (SortButtonRenderer.DOWN == renderer.getState(col))
{
isAscent = true;
} else {
isAscent = false;
}
((SortableTableModel)header.getTable().getModel())
.sortByColumn(sortCol, isAscent);
}
public void mouseReleased(MouseEvent e) {
int col = header.columnAtPoint(e.getPoint());
renderer.setPressedColumn(-1); // clear
header.repaint();
}
}
}
Use different fonts in different cells
// File: MultiFontCellTableExample.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.border.*;
import jp.gr.java_conf.tame.swing.table.*;
public class MultiFontCellTableExample extends JFrame
{
public MultiFontCellTableExample() {
super( "Multi-Font Cell Example" );
AttributiveCellTableModel ml = new AttributiveCellTableModel(8,3);
CellFont cellAtt =(CellFont)ml.getCellAttribute();
JTable table = new JTable( ml );
table.setRowHeight(26);
table.setCellSelectionEnabled(true);
table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
table.setDefaultRenderer(Object.class ,new AttributiveCellRenderer());
JScrollPane scroll = new JScrollPane( table );
FontPanel fontPanel = new FontPanel(table, cellAtt);
Box box = new Box(BoxLayout.X_AXIS);
box.add(scroll);
box.add(new JSeparator(SwingConstants.HORIZONTAL));
box.add(fontPanel);
getContentPane().add( box );
setSize( 400, 200 );
setVisible(true);
}
class FontPanel extends JPanel {
String[] str_size = {"10","12","14","16","20","24"};
String[] str_style = {"PLAIN","BOLD","ITALIC"};
JComboBox name,style,size;
FontPanel(final JTable table, final CellFont cellAtt)
{
setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
Box box = new Box(BoxLayout.X_AXIS);
JPanel p2 = new JPanel(new GridLayout(3,1));
JPanel p3 = new JPanel(new GridLayout(3,1));
JPanel p4 = new JPanel(new FlowLayout());
p2.add(new JLabel("Name:"));
p2.add(new JLabel("Style:"));
p2.add(new JLabel("Size:"));
Toolkit toolkit = Toolkit.getDefaultToolkit();
name = new JComboBox(toolkit.getFontList());
style = new JComboBox(str_style);
size = new JComboBox(str_size);
size.setEditable(true);
JButton b_apply = new JButton("Apply");
b_apply.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int[] columns = table.getSelectedColumns();
int[] rows = table.getSelectedRows();
if ((rows == null) || (columns == null)) return;
if ((rows.length<1)||(columns.length<1)) return;
Font font = new Font((String)name.getSelectedItem(),
style.getSelectedIndex(),
Integer.parseInt((String)size.getSelectedItem()));
cellAtt.setFont(font, rows, columns);
table.clearSelection();
table.revalidate();
table.repaint();
}
});
p3.add(name);
p3.add(style);
p3.add(size);
p4.add(b_apply);
box.add(p2);
box.add(p3);
add(box);
add(p4);
}
}
public static void main(String[] args) {
MultiFontCellTableExample frame = new MultiFontCellTableExample();
frame.addWindowListener( new WindowAdapter() {
public void windowClosing( WindowEvent e ) {
System.exit(0);
}
});
}
}
Display any JComponent in a cell
// File: Table.java
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public class Table
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Table");
frame.addWindowListener( new WindowAdapter() {
public void windowClosing(WindowEvent e)
{
Window win = e.getWindow();
win.setVisible(false);
win.dispose();
System.exit(0);
}
} );
JTable table = new JTable( 6,4 )
{
public TableCellRenderer getCellRenderer(int row, int
column) {
TableColumn tableColumn = getColumnModel().getColumn(column);
TableCellRenderer renderer = tableColumn.getCellRenderer();
if (renderer == null) {
Class c = getColumnClass(column);
if( c.equals(Object.class) )
{
Object o = getValueAt(row,column);
if( o != null )
c = getValueAt(row,column).getClass();
}
renderer = getDefaultRenderer(c);
}
return renderer;
}
public TableCellEditor getCellEditor(int row, int column)
{
TableColumn tableColumn = getColumnModel().getColumn(column);
TableCellEditor editor = tableColumn.getCellEditor();
if (editor == null) {
Class c = getColumnClass(column);
if( c.equals(Object.class) )
{
Object o = getValueAt(row,column);
if( o != null )
c = getValueAt(row,column).getClass();
}
editor = getDefaultEditor(c);
}
return editor;
}
};
// Buttons
table.setValueAt( new JButton("Button"), 0,
0 );
table.setValueAt( new JButton("Button"), 0,
1 );
// Combobox
JComboBox combo = new JComboBox( new String[] {"First",
"Second", "Third"} );
table.setValueAt( combo, 1, 1 );
// Labels
table.setValueAt( new JLabel("Label"), 1,
0 );
JLabel label = new JLabel( "Label", new ImageIcon(
table.getClass().getResource("new.gif") ),
JLabel.LEFT);
table.setValueAt( label, 1, 2 );
// Scrollbar
table.setValueAt( new JScrollBar(JScrollBar.HORIZONTAL),
2,1 );
// RadioButtons
JRadioButton b1 = new JRadioButton( "Group1 Button1"
);
JRadioButton b2 = new JRadioButton( "Group1 Button2"
);
JRadioButton b3 = new JRadioButton( "Group1 Button3"
);
ButtonGroup g1 = new ButtonGroup();
g1.add( b1 );
g1.add( b2 );
g1.add( b3 );
table.setValueAt( b1, 3, 0 );
table.setValueAt( b2, 3, 1 );
table.setValueAt( b3, 3, 2 );
table.setDefaultRenderer( JComponent.class, new JComponentCellRenderer()
);
table.setDefaultEditor( JComponent.class, new JComponentCellEditor()
);
JScrollPane sp = new JScrollPane(table);
frame.getContentPane().add( sp );
frame.pack();
frame.show();
}
}
class JComponentCellRenderer implements TableCellRenderer
{
public Component getTableCellRendererComponent(JTable
table, Object value,
boolean isSelected, boolean hasFocus, int row, int column)
{
return (JComponent)value;
}
}
// File: JComponentCellEditor.java
import java.awt.Component;
import java.awt.event.*;
import java.awt.AWTEvent;
import java.lang.Boolean;
import javax.swing.table.*;
import javax.swing.event.*;
import java.util.EventObject;
import javax.swing.tree.*;
import java.io.Serializable;
import javax.swing.*;
public class JComponentCellEditor implements TableCellEditor,
TreeCellEditor,
Serializable {
protected EventListenerList listenerList = new EventListenerList();
transient protected ChangeEvent changeEvent = null;
protected JComponent editorComponent = null;
protected JComponent container = null; // Can be tree
or table
public Component getComponent() {
return editorComponent;
}
public Object getCellEditorValue() {
return editorComponent;
}
public boolean isCellEditable(EventObject anEvent) {
return true;
}
public boolean shouldSelectCell(EventObject anEvent)
{
if( editorComponent != null && anEvent instanceof
MouseEvent
&& ((MouseEvent)anEvent).getID() == MouseEvent.MOUSE_PRESSED
)
{
Component dispatchComponent = SwingUtilities.getDeepestComponentAt(editorComponent,
3, 3 );
MouseEvent e = (MouseEvent)anEvent;
MouseEvent e2 = new MouseEvent( dispatchComponent, MouseEvent.MOUSE_RELEASED,
e.getWhen() + 100000, e.getModifiers(), 3, 3, e.getClickCount(),
e.isPopupTrigger() );
dispatchComponent.dispatchEvent(e2);
e2 = new MouseEvent( dispatchComponent, MouseEvent.MOUSE_CLICKED,
e.getWhen() + 100001, e.getModifiers(), 3, 3, 1,
e.isPopupTrigger() );
dispatchComponent.dispatchEvent(e2);
}
return false;
}
public boolean stopCellEditing() {
fireEditingStopped();
return true;
}
public void cancelCellEditing() {
fireEditingCanceled();
}
public void addCellEditorListener(CellEditorListener
l) {
listenerList.add(CellEditorListener.class, l);
}
public void removeCellEditorListener(CellEditorListener
l) {
listenerList.remove(CellEditorListener.class, l);
}
protected void fireEditingStopped() {
Object[] listeners = listenerList.getListenerList();
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==CellEditorListener.class) {
// Lazily create the event:
if (changeEvent == null)
changeEvent = new ChangeEvent(this);
((CellEditorListener)listeners[i+1]).editingStopped(changeEvent);
}
}
}
protected void fireEditingCanceled() {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==CellEditorListener.class) {
// Lazily create the event:
if (changeEvent == null)
changeEvent = new ChangeEvent(this);
((CellEditorListener)listeners[i+1]).editingCanceled(changeEvent);
}
}
}
// implements javax.swing.tree.TreeCellEditor
public Component getTreeCellEditorComponent(JTree tree,
Object value,
boolean isSelected, boolean expanded, boolean leaf,
int row) {
String stringValue = tree.convertValueToText(value,
isSelected,
expanded, leaf, row, false);
editorComponent = (JComponent)value;
container = tree;
return editorComponent;
}
// implements javax.swing.table.TableCellEditor
public Component getTableCellEditorComponent(JTable
table, Object value,
boolean isSelected, int row, int column) {
editorComponent = (JComponent)value;
container = table;
return editorComponent;
}
}
ASCII Value Table
| DEC |
HEX |
CHARACTER |
DEC |
HEX |
CHARACTER |
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
0
1
2
3
4
5
6
7
8
9
0A
0B
0C
0D
0E
0F
10
11
12
13
14
15
16
17
18
19
1A
1B
1C
1D
1E
1F
20
21
22
23
24
25
26
27
28
29
2A
2B
2C
2D
2E
2F
30
31
32
33
34
35
36
37
38
39
3A
3B
3C
3D
3E
3F
|
ctl@ NUL
ctlA SOH
ctlB STX
ctlC ETX
ctlD EOT
ctlE ENQ
ctlF ACK
ctlG BELL
ctlH BS
ctlI HT
ctlJ LF
ctlK VT
ctlL FF
ctlM CR
ctlN SO
ctlO SI
ctlP DLE
ctlQ DC1
ctlR DC2
ctlS DC3
ctlT DC4
ctlU NAK
ctlV SYN
ctlW ETB
ctlX CAN
ctlY EM
ctlZ SUB
ctl[ ESC
ctl\ FS
ctl] GS
ctl^ RS
ctl_ US
Space
!
| 98 62 b
#
$|
%|
&|
'
(
)
*
+
,
-
.
/
0
1
2
3
4
5
6
7
8
9
:
;
<
=
>
?
|
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
60
61
63
64
65
66
67
68
69
6A
6B
6C
6D
6E
6F
70
71
72
73
74
75
76
77
78
79
7A
7B
7C
7D
7E
7F
|
40
41
42
43
44
45
46
47
48
49
4A
4B
4C
4D
4E
4F
50
51
52
53
54
55
56
57
58
59
5A
5B
5C
5D
5E
5F
`
a
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
{
|
}
~
DEL
|
@
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
[
\
]
^
_
|
|
|