JAVA SCRIPT - Using let in Your Browser Application

Using let in Your Browser Application


Problem

You’re interested in using let in your browser application, but aren’t sure which brows‐ ers support it (or other ECMAScript functionality), or what you need to do to get it to work.

Solution

Support for ECMAScript 6 functionality, such as let, can be difficult to determine, and may require setting flags, specifying JavaScript version numbers, or using specialized polyfills or other tools. Unfortunately, not all approaches are compatible across all the modern browsers. The support for let is a perfect example of fractured ES 6 support across browsers.

To use let in Firefox, you have to give a version number with the script tag:

<script type="application/javascript;version=1.7">
 if (true) {
 let i = 'testing let';
 console.log(i);
 }
 if (typeof i != 'undefined'){
 console.log(i);
 } else {
 console.log('undefined');
 }
</script>


In Firefox, the console output is what we would expect:


testing let
undefined

To get the same result in Internet Explorer 11, your HTML document must be HTML5, which means using the following DOCTYPE:

<!DOCTYPE html>

This puts IE 11 into edge mode, where many ES 6 features are supported. Unfortunately, IE 11 ignores any script block with a type of application/javascript;version=1.7, so you’ll have to remove the type setting for the script to work.

The same applies to Chrome. Chrome supports let if you remove Firefox’s peculiar use of type and if you enable the chrome://flags/#enable-javascript-harmony flag. In addition, you must also use strict mode, so the code needs to be modified to:


<script>
 'use strict';
 if (true) {
 let i = 'testing let';
 alert(i);
 }
 if (typeof i != 'undefined'){
 alert(i);
 } else {
 alert('undefined');
 }
</script>


This code snippet also works for IE, but not Firefox. The code also works in Opera if you enable the same Chrome Harmony flag (copy and paste the above flag URI into the location bar for Opera and click “Enable”). Safari doesn’t, at this time, support let.

EXPLAIN

The let keyword allows JavaScript developers to define block-level variables, rather than global variables or variables in a function block. 

An example is given in the solution, where the variable i is only available within the conditional block, but is undefined outside the block. JavaScript developers have pushed for the concept of let longer than most additions to ECMAScript 6, but its use in production applications must be restricted because of the difficulty to support it, as was demonstrated in the solution.

Yes, you can support it across browsers, but only when flags are set, and even then, Firefox doesn’t currently support a syntax that works for Chrome, IE, and Opera, and Safari is missing, altogether

The same holds for many of the ES 6 new language constructs: if the construct requires setting a browser flag, you have to assume your end user hasn’t set it so you can’t depend on it. This differs from supporting the new ES objects (covered in the rest of this chapter) because it’s easier to emulate a new object using a polyfill, than it is to emulate a new language construct. 

Even a translator-compiler (transpiler), such as Google’s Traceur, can only convert let into var, because there is no current workaround for the concept of let. Running the solution code snippet in the Traceur REPL (read-evaluate-print) results in the following: . 


$traceurRuntime.ModuleStore.getAnonymousModule(function() {
 "use strict";
 'use strict';
 if (true) {
 var i = 'testing let';
 alert(i);
 }
 if (typeof i != 'undefined') {
 alert(i);
 } else {
 alert('undefined');
 }
 return {};
});
//# sourceURL=traceured.js

In this case, the workaround is worse than not having a workaround, because var does not result in the same behavior as the use of let. The resulting print-out for the Traceur version is:


testing let
testing let


The variable i is printed out twice, as it is defined in the code outside the conditional block—the variable is no longer scoped to the block

JAVA SCRIPT - Adding Filter Effects to Video via Canvas

 Adding Filter Effects to Video via Canvas


Problem

You’re interested in not only playing video in your web page but also playing modified versions of the video, such as one that has been grayscaled, or manipulated in some way. 

Solution

Use HTML5 video with the Canvas element, playing the video to a scratch Canvas element:

function drawVideo() {
 var videoObj = document.getElementById("videoobj");
 // if not playing, quit
 if (videoObj.paused || videoObj.ended) return false;
 // draw video on canvas
 var canvasObj = document.getElementById("canvasobj");
 var ctx = canvasObj.getContext("2d");
 ctx.drawImage(videoObj,0,0,480,270);
 ...
 setTimeout(drawVideo,20);
}


You can then add the ability to capture the image data using the Canvas element’s getImageData(), modify the image data with whatever filter you want, and then play the image data to a second, visible Canvas element:


var pData = ctx.getImageData(0,0,480,270);
// grayscale it and set to display canvas
pData = grayScale(pData);
ctx2.putImageData(pData,0,0);


EXPLAIN

The best thing about all the new HTML5 media elements is how you can use them together. Using video and Canvas, you can not only provide custom controls, you can also provide custom video filters, too.

To play a video in a Canvas element, we’ll need to add both elements to the web page:


<video id="videoobj" controls width="480" height="270">
 <source src="videofile.mp4" type="video/mp4" />
 <source src="videofile.webm" type="video/webm" />
 </video>
 <canvas id="canvasobj" width="480" height="270"></canvas>

Both the canvas and video elements are the same width and height. To draw the video onto the canvas, we’re going to use the Canvas drawImage(). There are several variations of parameters we could use with this method, but the signature we’re interested in is the following:


void drawImage(
 in nsIDOMElement image,
 in float dx,
 in float dy,
 in float dw,
 in float dh
);

These parameters are:

• image: A reference to a Canvas element, an img element, or a Video element

• dx: x coordinate of the top-left corner of the source image

• dy: y coordinate of the top-left corner of the source image

• dw: Width of the source image (can be scaled)

• dh: Height of the source image (can be scaled)

Demonstrates a first pass at an application to modify the video playing the Canvas element. It just takes what’s showing in the video and plays it, as is, in the Canvas.

The application uses setTimeout() to test whether the video is still playing and grabs the video every 20 milliseconds, which is fast enough to provide smooth playback for human perceptions.

There is a timeupdate event handler for the Video element, but it’s only invoked every 200 milliseconds (per the W3C specification on the media elements), which is way too slow for our purposes.

A first cut at drawing video data to a canvas element


<!DOCTYPE html>
<head>
<title>Play video in canvas</title>
 <meta charset="utf-8" />
 <script>
 window.onload=function() {
 document.getElementById("videoobj").
 addEventListener("timeupdate", drawVideo, false);
 }
 function drawVideo() {
 var videoObj = document.getElementById("videoobj");
 var canvasObj = document.getElementById("canvasobj");
 var ctx = canvasObj.getContext("2d");
 ctx.drawImage(videoObj,0,0);
 }
 </script>
</head>
<body>
 <video id="videoobj" controls width="480" height="270">
 <source src="videofile.mp4" type="video/mp4" />
 <source src="videofile.webm" type="video/webm" />
 </video>
 <canvas id="canvasobj" width="480" height="270"></canvas>
</body>

In the code, during each time out event, the video is tested to see if it’s still playing before it’s grabbed and displayed in the Canvas element. The application works in all modern browsers.

The next step is to modify the video data before it’s streamed to the Canvas element. For the example, I’m going to do a crude modification of the original video to simulate how a person could perceive the video if they suffered from a form of color blindness known as protanopia.

This type of color blindness is one of the most common, and those who have it can’t perceive red light. I say “crude” because a much more accurate representation is so computationally expensive that the playback visibly stutters.

To modify the video playback, we need two things: the function to modify the data, and a scratch canvas object used to capture the video data, as it is, and then serve as our intermediate in the transformation.

We need a scratch Canvas element because we’re using the Canvas element’s getImageData() to access the actual video data, and putI mageData() to play the video data after it has been manipulated.

The getImageData() function returns an object consisting of three values: the width, the height, and the image data as a Uint8ClampedArray typed array.

Video with applied color blind filter, playing side by side with original 


<!DOCTYPE html>
<head>
<title>Protanopia</title>
 <meta charset="utf-8" />
 <script>
 // Protanopia filter
 function protanopia(pixels) {
 var d = pixels.data;
 for (var i=0; i<d.length; i+=4) {
 var r = d[i];
 var g = d[i+1];
 var b = d[i+2];
 //convert to an approximate protanopia value
 d[i] = 0.567*r + 0.433*g;
 d[i+1] = 0.558*r + 0.442*g;
 d[i+2] = 0.242*g + .758*b;
 }
 return pixels;
 }
 // event listeners
 window.onload=function() {
 document.getElementById("videoobj").
 addEventListener("play", drawVideo, false);
 }
 // draw the video
 function drawVideo() {
 var videoObj = document.getElementById("videoobj");
// if not playing, quit
 if (videoObj.paused || videoObj.ended) return false;
 // create scratch canvas
 var canvasObj = document.getElementById("canvasobj");
 var bc = document.createElement("canvas");
 bc.width=480;
 bc.height=270;
 // get contexts for scratch and display canvases
 var ctx = canvasObj.getContext("2d");
 var ctx2 = bc.getContext("2d");
 // draw video on scratch and get its data
 ctx2.drawImage(videoObj, 0, 0, 480, 270);
 var pData = ctx2.getImageData(0,0,480,270);
 // grayscale it and set to display canvas
 pData = protanopia(pData);
 ctx.putImageData(pData,0,0);
 setTimeout(drawVideo,20);
 }
 </script>
</head>
<body>
 <video id="videoobj" controls width="480" height="270">
 <source src="videofile.mp4" type="video/mp4" />
 <source src="videofile.webm" type="video/webm" />
 </video>
 <canvas id="canvasobj" width="480" height="270"></canvas>
</body>

JAVA SCRIPT - Controlling Video from JavaScript with the video Element

Controlling Video from JavaScript with the video Element


Problem

You want to embed video in your web page, without using Flash. You also want a con‐ sistent look for the video control, regardless of browser and operating system.


Solution

Use the HTML5 video element: 

<video id="meadow" poster="purples.jpg" >
 <source src="meadow.m4v" type="video/mp4"/>
 <source src="meadow.ogv" type="video/ogg" />
</video>


You can provide controls for it via JavaScript, as shown in Example 9-5. Buttons are used to provide the video control, and text in a div element is used to provide feedback on time during the playback.

Providing a custom control for the HTML5 video element :


<!DOCTYPE html>
<head>
<title>Meadow Video</title>
<script>
<style>
 video {
 border: 1px solid black;
 }
</style>
window.onload=function() {
 // events for buttons
 document.getElementById("start").addEventListener("click",startPlayback);
 document.getElementById("stop").addEventListener("click",stopPlayback);
 document.getElementById("pause").addEventListener("click",pausePlayback);
 // setup for video playback
 var meadow = document.getElementById("meadow");
 meadow.addEventListener("timeupdate",reportProgress);
 // video fallback
 var detect = document.createElement("video");
 if (!detect.canPlayType) {
 document.getElementById("controls").style.display="none";
 }
}
// start video, enable stop and pause
// disable play
function startPlayback() {
 var meadow = document.getElementById("meadow");
 meadow.play();
 document.getElementById("pause").disabled=false;
 document.getElementById("stop").disabled=false;
 this.disabled=true;
}
// pause video, enable start, disable stop
// disable pause
function pausePlayback() {
 document.getElementById("meadow").pause();
 this.disabled=true;
 document.getElementById("start").disabled=false;
 document.getElementById("stop").disabled=true;
}
// stop video, return to zero time
// enable play, disable pause and stop
function stopPlayback() {
 var meadow = document.getElementById("meadow");
meadow.pause();
 meadow.currentTime=0;
 document.getElementById("start").disabled=false;
 document.getElementById("pause").disabled=true;
 this.disabled=true;
}
// for every time divisible by 5, output feedback
function reportProgress() {
 var time = Math.round(this.currentTime);
 var div = document.getElementById("feedback");
 div.innerHTML = time + " seconds";
}
</script>
</head>
<body>
<video id="meadow" poster="purples.jpg" >
 <source src="meadow.m4v" type="video/mp4"/>
 <source src="meadow.ogv" type="video/ogg" />
</video>
<div id="feedback"></div>
<div id="controls">
<button id="start">Play</button>
<button id="stop">Stop</button>
<button id="pause">Pause</button>
</controls>
</body>


EXPLAIN

The new HTML5 video element, as with the HTML5 audio element, can be controlled with its own built-in controls, or you can provide your own. The media elements support the following methods: 

• play: Starts playing the video 

• pause: Pauses the video 

• load: Preloads the video without starting play 

• canPlayType: Tests if the user agent supports the video type The media elements don’t support a stop method, so the code emulates one by pausing video play and then setting the video’s currentTime attribute to 0, 

which basically resets the play start time. I also used currentTime to print out the video time, using Math.round to round the time to the nearest second.

The video control is providing two different video codecs: H.264 (.mp4), and Ogg Theora (.ogv). Firefox, Opera, and Chrome support Ogg Theora, but Safari and IE only support the H.264-formatted video. 

However, by providing both types, the video works in all of the browsers that support the video element. The video and audio controls are inherently keyboard-accessible. 

If you do replace the controls, you’ll want to provide accessibility information with your replacements. The video control doesn’t have built-in captioning, but work is underway to provide the API for captioning.


JAVA SCRIPT - Running a Routine When an Audio File Begins Playing

Running a Routine When an Audio File Begins Playing 


Problem

You want to provide an audio file and then pop up a question or other information when the audio file begins or ends playing.


Solution

Use the HTML5 audio element: 


<audio id="meadow" controls>
 <source src="meadow.mp3" type="audio/mpeg3"/>
 <source src="meadow.ogg" type="audio/ogg" />
 <source src="meadow.wav" type="audio/wav" />
 <p><a href="meadow.wav">Meadow sounds</a></p>
</audio>

and capture either its play event (playback has begun) or ended event (playback has finished):

var meadow = document.getElementById("meadow");
meadow.addEventListener("ended", aboutAudio);



then display the information:


function aboutAudio() {
 var info = 'This audio file is a recording from Shaw Nature Reserve';
 var txt = document.createTextNode(info);
 var div = document.createElement("div");
 div.appendChild(txt);
 document.body.appendChild(div);
}


EXPLAIN

HTML5 added two media elements: audio and video. These simple-to-use controls provide a way to play audio and video files without having to use Flash. In the solution, the audio element’s controls Boolean attribute is set, so the controls are displayed. 

The element has three source children elements, providing support for three different types of audio files: WAV, MP3, and Ogg Vorbis. 

The use of the source element allows different browsers to find the format (codec) that they support. For the example, the browser support is: 

• Firefox accepts either the WAV or Ogg Vorbis. It also accepts MP3, but uses the underlying operating system support to do so, rather than providing its own. 

• Opera supports WAV and Ogg Vorbis, but not MP3. 

• Chrome supports WAV, MP3, and Ogg Vorbis. 

• Safari supports MP3 and WAV. 

• IE supports the MP3.

A link to the WAV file is provided as a fallback, which means people using browsers that don’t support audio can still access the sound file. I could have also provided an object element, or other fallback content.

The media elements come with a set of methods to control the playback, as well as events that can be triggered when the event occurs. In the solution, the ended event is captured and assigned the event handler aboutAudio(), which displays a message about the file after the playback is finished. 

Notice that though the code is using a DOM Level 0 event handler with the window load event, it’s using DOM Level 2 event handling with the audio element. Browser support is erratic with this event handler, so I strongly recom‐ mend you use addEventListener(). However, onended does seem to work without problems when used directly in the element:


<audio id="meadow" src="meadow.wav" controls onended="alert('All done')">
 <p><a href="meadow.wav">Meadow sounds</a></p>
</audio>

It’s interesting to see the appearance of the elements in all of the browsers that currently support them. There is no standard look, so each browser provides its own interpreta‐ tion.

You can control the appearance by providing your own playback controls and using your own elements/CSS/SVG/Canvas to supply the decoration.

JAVA SCRIPT - Integrating SVG and the Canvas Element in HTML

 Integrating SVG and the Canvas Element in HTML


Problem

You want to use the canvas element and SVG together within a web page. 

Solution

One option is to embed both the SVG and the canvas element directly into the HTML page, and then access the canvas element from script within SVG:

<!DOCTYPE html>
<head>
<title>Canvas and SVG</title>
<meta charset="utf-8" />
</head>
<body>
<canvas id="myCanvas" width="400px" height="100px">
 <p>canvas item alternative content</p>
</canvas>
<svg id="svgelem" height="400">
 <title>SVG Circle</title>
 <script type="text/javascript">
 window.onload = function () {
 var context =
document.getElementById("myCanvas").getContext('2d');
 context.fillStyle = 'rgba(0,200,0,0.7)';
 context.fillRect(0,0,100,100);
 };
 </script>
 <circle id="redcircle" cx="100" cy="100" r="100" fill="red" stroke="#000" />
 </svg>
</body>

Or you can embed the canvas element as a foreign object directly in the SVG:

<!DOCTYPE html>
<html>
<head>
<title>Accessing Inline SVG</title>
<meta charset="utf-8">
</head>
<body>
<svg id="svgelem" height="400" width="600">
 <script type="text/javascript">
 window.onload = function () {
 var context2 = document.getElementById("thisCanvas").getContext('2d');
 context2.fillStyle = "#ff0000";
 context2.fillRect(0,0,200,200);
 };
 </script>
 <foreignObject width="300" height="150">
 <canvas width="300" height="150" id="thisCanvas">
 alternate content for browsers that do not support Canvas
 </canvas>
 </foreignObject>
 <circle id="redcircle" cx="300" cy="100" r="100" fill="red" stroke="#000" />
 </svg>
</body>
</html>


EXPLAIN 


 When the SVG element is embedded into the current web page, you can access HTML elements from within the SVG. However, you can also embed elements directly in SVG, using the SVG foreignObject element. This element allows us to embed XHTML, MathML, RDF, or any other XML-based syntax.

In both solutions, I was able to use getElementById(). However, if I want to manipulate the elements using other methods, such as getElementsByTagName(),

I have to be care‐ ful about which version of the method I use. For instance, I can use getElementsByTag Name() for the outer canvas element, but I would need to use the namespace version of the method, getElementsByTagNameNS, if the contained object is XML,

 such as RDF/ XML. Because the embedded object in the solution is HTML5, a namespace wasn’t necessary. Once you have the canvas context, use the element like you would from script within HTML: add rectangles, draw paths, create arcs, and so on.

Canvas? Or SVG?

Why would you use Canvas over SVG, or SVG over Canvas? The canvas element is faster in frame-type animations. With each animation, the browser only needs to redraw the changed pixels, not re-create the entire scene. 

However, the advantage you get with the canvas element animation lessen when you have to support a variety of screen sizes, from smartphone to large monitor. SVG scales beautifully.

Another advantage to SVG is that it figures in rich data visualizations with the assistance of powerful libraries, . But then, Canvas is used with 3D systems, such as WebGL, . 

But why choose one over the other? One use of SVG and Canvas together is to provide a fallback for the canvas element: the SVG writes to the DOM and persists even if Java‐ Script is turned off, while the canvas element does not. 

JAVA SCRIPT - Accessing SVG from Web Page Script

Accessing SVG from Web Page Script


Problem

You want to modify the contents of an SVG element from script within the web page. 


Solution

If the SVG is embedded directly in the web page, access the element and its attributes using the same functionality you would use with any other web page element:

var square = document.getElementById("ssquare");
square.setAttribute("width", "500");

However, if the SVG is in an external SVG file embedded into the page via an object element, you have to get the document for the external SVG file in order to access the SVG elements. The technique requires object detection because the process differs by browser:


// set element onclick event handler
window.onload=function () {
 var object = document.getElementById("object");
 var svgdoc;
 try {
 svgdoc = object.contentDocument;
 } catch(e) {
 try {
 svgdoc = object.getSVGDocument();
 } catch (e) {
 alert("SVG in object not supported in your environment");
 }
 }
 if (!svgdoc) return;
 var square = svgdoc.getElementById('square');
 square.setAttribute("width", "500");


EXPLAIN


 The first option listed in the solution accesses SVG embedded in an HTML file. You can access SVG elements using the same methods you’ve used to access HTML elements. The second option is a little more involved, and depends on retrieving the document object for the SVG document.

The first approach tries to access the contentDocument property on the object. If this fails, the application then tries to access the SVG document using getSVGDocument(). Once you have access to the SVG document object, you can use the same DOM methods you would use with elements native to the web page. Accessing SVG in an object element from script.


<!DOCTYPE html>
<head>
<title>SVG in Object</title>
<meta charset="utf-8" />
</head>
<body>
<object id="object" data="rect.svg"
style="padding: 20px; width: 600px; height: 600px">
<p>No SVG support</p>
</object>
<script type="text/javascript">
 var object = document.getElementById("object");
 object.onload=function() {
 var svgdoc;
 // get access to the SVG document object
 try {
 svgdoc = object.contentDocument;
 } catch(e) {
 try {
 svgdoc = object.getSVGDocument();
 } catch (e) {
 alert("SVG in object not supported in your environment");
 }
 }
 if (!svgdoc) return;
 var r = svgdoc.rootElement;
 // get SVG element and modify
 var square = svgdoc.getElementById('square');
 square.onclick = function() {
 var width = parseFloat(square.getAttribute("width"));
 width-=50;
 square.setAttribute("width",width);
 var color = square.getAttribute("fill");
 if (color == "blue") {
 square.setAttribute("fill","yellow");
square.setAttribute("stroke","green");
 } else {
 square.setAttribute("fill","blue");
 square.setAttribute("stroke","red");
 }
 }
 }
</script>
</body>


In addition to the different approaches to get the SVG document, you also have to handle browser differences in how the onload event handler works. Firefox and Opera fire the onload event handler for the window after all the document contents have loaded, in‐ cluding the SVG in the object element.

 However, Safari and Chrome, probably because of the shared core, fire the window.onload event handler before the SVG has finished loading. In the example code, the object is accessed in script after it has loaded; the object.on load event handler is then accessed to get the SVG document and assigned the function to the onclick event handler.

JAVA SCRIPT- Adding JavaScript to SVG

Adding JavaScript to SVG


Problem

You want to add JavaScript to an SVG file or element. 

Solution

JavaScript in SVG is included in script elements, just as with HTML, except with the addition of CDATA markup surrounding the script in case XHTML-sensitive charac‐ ters, such as < and >.

The DOM methods are also available for working with the SVG elements.

Demonstration of JavaScript within an SVG file


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" width="600" height="600">
 <script type="text/ecmascript">
 <![CDATA[
// set element onclick event handler
 window.onload=function () {
 var square = document.getElementById("square");
 // onclick event handler, change circle radius
 square.onclick = function() {
 var color = this.getAttribute("fill");
 if (color == "#ff0000") {
 this.setAttribute("fill", "#0000ff");
 } else {
 this.setAttribute("fill","#ff0000");
 }
 }
 }
 ]]>
 </script>
 <rect id="square" width="400" height="400" fill="#ff0000"
 x="10" y="10" />
</svg>


EXPLAIN

As the solution demonstrates, SVG is XML, and the rules for embedding script into XML must be adhered to. This means providing the script type within the script tag, as well as wrapping the script contents in a CDATA block. If you don’t have the CDATA section, and your script uses characters such as < or &, your page will have errors, because the XML parser treats them as XML characters, not script.

The DOM methods, such as document.getElementById(), aren’t HTML specific; they’re usable with any XML document, including SVG. What’s new is the SVG-specific fill attribute, an attribute unique to SVG elements, such as rect. 

The code in the solution is a standalone SVG file, with a .svg extension. If we were to embed the SVG within an HTML file, , the color-changing animation would work the same. The CDATA section is removed because all modern browsers understand the SVG is now in an HTML context. If the file is XHTML, though, add them back.

SVG element , embedded into an HTML page





<!DOCTYPE html>
<html>
<head>
<title>Accessing Inline SVG</title>
<meta charset="utf-8">
</head>
<body>
<svg width="600" height="600">
 <script>
 // set element onclick event handler
 window.onload=function () {
 var square = document.getElementById("square");
 // onclick event handler, change circle radius
 square.onclick = function() {
 var color = this.getAttribute("fill");
 if (color == "#ff0000") {
 this.setAttribute("fill","#0000ff");
 } else {
 this.setAttribute("fill","#ff0000");
 }
 }
 }
 </script>
 <rect id="square" width="400" height="400" fill="#ff0000"
x="10" y="10" />
</svg>
</body>
</html>

Using SVG Libraries

There aren’t quite as many libraries for working with SVG as there are for working with Canvas, but the ones that exist are very handy. One of the most popular is the D3 library, . 

Three other popular libraries include the granddaddy of the SVG libraries, Raphaël, and the newer Snap.svg and SVG.js. All three can simplify SVG cre‐ ation and animation. You can even use Raphaël in both jsBin and jsFiddle, . The following code snippet shows an example of using Raphaël:


// Creates canvas 320 × 200 at 10, 50
var paper = Raphael(10, 50, 320, 400);
// Creates circle at x = 150, y = 140, with radius 100
var circle = paper.circle(150, 140, 100);
// Sets the fill attribute of the circle to red (#f00)
circle.attr("fill", "#f0f");
// Sets the stroke attribute of the circle to white
circle.attr("stroke", "#ff0");

JAVA SCRIPT - Creating a Dynamic Line Chart in Canvas

Creating a Dynamic Line Chart in Canvas


Problem

You want to display a line chart in your web page, but the data changes over time, and you want to dynamically update it. 

Solution

Use the canvas element and the path method to create the chart. When the data changes, update the chart:

var array1 = [[100,100], [150, 50], [200,185],
 [250, 185], [300,250], [350,100], [400,250],
 [450, 100], [500,20], [550,80], [600, 120]];
var imgcanvas = document.getElementById("imgcanvas");
if (imgcanvas.getContext) {
 var ctx = imgcanvas.getContext('2d');
 // rect one
 ctx.strokeRect(0,0,600,300);
 // line path
 ctx.beginPath();
 ctx.moveTo(0,100);
 for (var i = 0; i < array1.length; i++) {
 ctx.lineTo(array1[i][0], array1[i][1]);
 }
 ctx.stroke();
}

EXPLAIN


Canvas paths are the way to create arbitrary shapes in Canvas. After getting the canvas context, ctx, the path is begun with a call to ctx.beginPath(), which begins a new Canvas path. The next line of code is ctx.moveTo, which moves the drawing “pen” to a beginning location, but without drawing. From that point, several lineTo() calls are made using an array of paired values representing the x,y location for each line endpoint. 

After the path has been defined, it’s drawn. We’re not creating a closed path, so I’m not using ctx.closePath(), which would draw all the defined lines and then attempt to draw a line from the ending point to the beginning point. Instead, I’m drawing the line given the points that have been defined, using ctx.stroke(). 

The appearance of the drawing is influenced by two Canvas settings: strokeStyle and fillStyle. The strokeStyle setting sets the color for the outline of a drawing, while the fillStyle does the same for the drawing filling: 


ctx.strokeStyle="black";
ctx.fillStyle="#ff0000;

Any CSS setting will do, or you can use a CanvasGradient or CanvasPattern. You can use the rgba setting to add transparency:

ctx.fillStyle="rgba(255,0,0,0.5)";

You can also use the globalAlpha setting to set the transparency for any drawing that follows:


ctx.globalAlpha = 0.2;

You can further control the appearance of the drawing outline by changing the stroke’s line width:

ctx.line

To dynamically update the chart, you can incorporate timers, and either replace the path (by creating an entirely new context, which would erase the old), or add the new line chart to the same chart.

 shows a web page that creates the line in the solution and then creates two others, each drawn after a short period of time using timers. The colors for the stroke path are changed between lines.

Using timers to dynamically update a line chart


<!DOCTYPE html>
<head>
<title>Canvas Chart</title>
<meta charset="utf-8" />
</head>
<body>
<canvas id="imgcanvas" width="650" height="350">
<p>Include an image that has a static representation of the chart</p>
</canvas>
<script>
 var points = [[[100,100], [150, 50], [200,185],
 [250, 185], [300,250], [350,100], [400,250],
 [450, 100], [500,20], [550,80], [600, 120]],
 [[100,100], [150, 150], [200,135],
 [250, 285], [300,150], [350,150], [400,280],
 [450, 100], [500,120], [550,80], [600, 190]],
 [[100,200], [150, 100], [200,35],
 [250, 185], [300,10], [350,15], [400,80],
 [450, 100], [500,120], [550,80], [600, 120]]];
 var colors = ['black','red','green'];
 var imgcanvas = document.getElementById("imgcanvas");
 if (imgcanvas.getContext) {
 var ctx = imgcanvas.getContext('2d');
// rectangle wrapping line chart
 ctx.strokeRect(0,0,600,300);
 points.forEach(function(element, indx, arry) {
 setTimeout(function() {
 // set up beginning
 ctx.beginPath();
 ctx.moveTo(0,100);
 ctx.strokeStyle = colors[indx];
 for (var i = 0; i < element.length; i++) {
 ctx.lineTo(element[i][0], element[i][1]);
 }
 ctx.stroke();
 }, indx * 5000);
 });
 }
</script>
</body>

Simplify Your Canvas Charts Using a Library

It doesn’t have to be difficult to create a chart using Canvas from scratch, but why walk the steps taken by others? There are several excellent libraries that can simplify not only chart making but other Canvas effects. Over 50 libraries for chart making are listed in a TechSlides Page, including the in‐ creasingly popular D3, . 

Most of the libraries are freely available, though some do charge a fee for commercial use. One of the libraries, Highcharts, even provides demonstrations that you can edit in jsFiddle, making it easy to try out the library’s capability. 

It’s dependent on jQuery, reducing the code to an absurdly simple level. As an example, one of the demonstrations is for a very professional line chart, with plot lines and labels,. Yet the code to create this example is equivalent to that in the following code block, which I modified to feature my own locations and temperature metric, which you can try yourself at jsFiddle: 


$(function () {
 $('#container').highcharts({
 title: {
 text: 'Monthly Average Temperature',
 x: -20 //center
 },
 subtitle: {
 text: 'Source: Weather.com',
 x: -20
 },
 xAxis: {
 categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
 },
 yAxis: {
 title: {
 text: 'Temperature (°F)'
 },
 plotLines: [{
 value: 0,
 width: 1,
 color: '#808080'
 }]
 },
 tooltip: {
 valueSuffix: '°F'
 },
 legend: {
 layout: 'vertical',
 align: 'right',
 verticalAlign: 'middle',
 borderWidth: 0
 },
 series: [{
 name: 'Seattle, WA',
 data: [47,51,55,59,65,70,75,75,70,60,52,47]
 }, {
 name: 'Grand Isle, VT',
 data: [27,31,40,54,67,76,81,79,71,57,45,33]
 }, {
 name: 'St. Louis, MO',
 data: [40,45,55,67,77,85,89,88,81,69,56,43]
 }]
 });
 });


Not only is the plotted chart professional looking, it’s zoomable, which means you can move your mouse cursor over the chart to examine the plot points in detail. That level of interactivity isn’t necessarily trivial in Canvas, because one of the downsides to Canvas is the fact that you can’t attach event handlers to the individual elements of Canvas— only to the Canvas area itself.

Not being able to attach an event to individual elements means that you’ll have to keep track of where the mouse is, and what’s underneath it at any point in time

Java Converting Epoch Seconds to DMYHMS

Java Converting Epoch Seconds to DMYHMS

Problem

You need to convert a number of seconds since 1970 into a Date .

Solution

Just use the Date constructor.

Explained

“The Epoch” is the beginning of time as far as modern operating systems go. Unix
time, and some versions of Windows time, count off inexorably the seconds since
the epoch. On systems that store this in a 32-bit integer, time is indeed running out.
Let’s say we wanted to find out when the Unix operating system, whose 32-bit ver-
sions use a 32-bit date, will get into difficulty. We take a 32-bit integer of all ones,
and construct a Date around it. The Date constructor needs the number of millisec-
onds since 1970, so we multiply by 1,000:

/** When does the UNIX date get into trouble? */
public class Y2038 {
public static void main(String[] a) {
// This should yield 2038AD, the hour of doom for the
// last remaining 32-bit UNIX systems (there will be
// millions of 64-bit UNIXes by then).
long expiry = 0x7FFFFFFFL;
System.out.println("32-bit UNIX expires on " +
Long.toHexString(expiry) + " or " +
new java.util.Date(expiry * 1000));
}
}


Sure enough, the program reports that 32-bit Unixes will expire in the year 2038 (you might think I knew that in advance if you were to judge by the name I gave the class; in fact, my web site has carried the Y2038 warning to Unix users for several years now). At least Unix system managers have more warning than most of the gen- eral public had for the original Y2K problem.

> java Y2038
32-bit UNIX expires on 7fffffff or Mon Jan 18 22:14:07 EST 2038
>

At any rate, if you need to convert seconds since 1970 to a date, you know how.

JAVA SCRIPT - Using a Timer to Automatically Update the Page with Fresh Data

Using a Timer to Automatically Update the Page with Fresh Data


Problem

You want to display entries from a file, but the file is updated frequently. 

Solution

Use Ajax and a timer to periodically check the file for new values and update the display accordingly. The Ajax we use is no different than any other Ajax request. We’ll use a GET, because we’re retrieving data.

 We put together the request, attach a function to the onreadysta techange event handler, and send the request: 


var xmlhttp;
// prepare and send XHR request
function populateList() {
 var url = 'text.txt'; // change to full url to prevent caching problems
 xmlhttp.open('GET', url, true);
 xmlhttp.onreadystatechange = processResponse;
 xmlhttp.send(null);
}

In the code that processes the response, we just place the new text into a new unordered list item and append it to an existing ul element:

// process return
function processResponse() {
 if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
 var li = document.createElement("li");
 var txt = document.createTextNode(xmlhttp.responseText);
 li.appendChild(txt);
 document.getElementById("update").appendChild(li);
 setTimeout(populateList,15000);
 } else if (xmlhttp.readyState == 4 && xmlhttp.status != 200) {
 console.log(xmlhttp.responseText);
 }
}

The new part is the addition of the setTimeout() in the code. It triggers the entire process again in 15 seconds.The process is started by creating the xmlHttpRequest object in the Window load event handler, and then calling populateList() the first time:

window.onload=function() {
 xmlhttp = new XMLHttpRequest();
 populateList();
}


EXPLAIN

The fact that we’re doing a direct request on a static text file might be new, but remember that a GET request is more or less the same as the requests we put into the location bar of our browsers. If something works in the browser, it should successfully return in an Ajax GET request…within reason. 

The key to using timers with Ajax calls is to make sure that the last call is completed before making the next. By adding the call to setTimeout() at the end of the Ajax call, we trigger the timer when we know an outstanding request isn’t being processed. We can also put in a check for the request status, and cancel the timer event altogether if we’re concerned about hitting a failing service, over and over again. When I ran the application that included the solution code, 

I changed the text file by using the Unix echo command: 


$ echo "This is working" > text.txt

JAVA SCRIPT - Creating a Dynamic Line Chart in Canvas

Creating a Dynamic Line Chart in Canvas


Problem

You want to display a line chart in your web page, but the data changes over time, and you want to dynamically update it. 

Solution

Use the canvas element and the path method to create the chart. When the data changes, update the chart: 

var array1 = [[100,100], [150, 50], [200,185],
 [250, 185], [300,250], [350,100], [400,250],
 [450, 100], [500,20], [550,80], [600, 120]];
var imgcanvas = document.getElementById("imgcanvas");
if (imgcanvas.getContext) {
 var ctx = imgcanvas.getContext('2d');
 // rect one
 ctx.strokeRect(0,0,600,300);
 // line path
 ctx.beginPath();
 ctx.moveTo(0,100);
 for (var i = 0; i < array1.length; i++) {
 ctx.lineTo(array1[i][0], array1[i][1]);
 }
 ctx.stroke();
}


EXPLAIN

Canvas paths are the way to create arbitrary shapes in Canvas. After getting the canvas context, ctx, the path is begun with a call to ctx.beginPath(), which begins a new Canvas path. The next line of code is ctx.moveTo, which moves the drawing “pen” to a beginning location, but without drawing. From that point, several lineTo() calls are made using an array of paired values representing the x,y location for each line endpoint. 


After the path has been defined, it’s drawn. We’re not creating a closed path, so I’m not using ctx.closePath(), which would draw all the defined lines and then attempt to draw a line from the ending point to the beginning point. Instead, I’m drawing the line given the points that have been defined, using ctx.stroke(). 

The appearance of the drawing is influenced by two Canvas settings: strokeStyle and fillStyle. The strokeStyle setting sets the color for the outline of a drawing, while the fillStyle does the same for the drawing filling:


ctx.strokeStyle="black";
ctx.fillStyle="#ff0000;

Any CSS setting will do, or you can use a CanvasGradient or CanvasPattern. You can use the rgba setting to add transparency:

ctx.fillStyle="rgba(255,0,0,0.5)";

You can also use the globalAlpha setting to set the transparency for any drawing that follows:

ctx.globalAlpha = 0.2;

You can further control the appearance of the drawing outline by changing the stroke’s line width:

ctx.line

To dynamically update the chart, you can incorporate timers, and either replace the path (by creating an entirely new context, which would erase the old), or add the new line chart to the same chart.

Shows a web page that creates the line in the solution and then creates two others, each drawn after a short period of time using timers. The colors for the stroke path are changed between lines.

Using timers to dynamically update a line chart


<!DOCTYPE html>
<head>
<title>Canvas Chart</title>
<meta charset="utf-8" />
</head>
<body>
<canvas id="imgcanvas" width="650" height="350">
<p>Include an image that has a static representation of the chart</p>
</canvas>
<script>
 var points = [[[100,100], [150, 50], [200,185],
 [250, 185], [300,250], [350,100], [400,250],
 [450, 100], [500,20], [550,80], [600, 120]],
 [[100,100], [150, 150], [200,135],
 [250, 285], [300,150], [350,150], [400,280],
 [450, 100], [500,120], [550,80], [600, 190]],
 [[100,200], [150, 100], [200,35],
 [250, 185], [300,10], [350,15], [400,80],
 [450, 100], [500,120], [550,80], [600, 120]]];
 var colors = ['black','red','green'];
 var imgcanvas = document.getElementById("imgcanvas");
 if (imgcanvas.getContext) {
 var ctx = imgcanvas.getContext('2d');
// rectangle wrapping line chart
 ctx.strokeRect(0,0,600,300);
 points.forEach(function(element, indx, arry) {
 setTimeout(function() {
 // set up beginning
 ctx.beginPath();
 ctx.moveTo(0,100);
 ctx.strokeStyle = colors[indx];
 for (var i = 0; i < element.length; i++) {
 ctx.lineTo(element[i][0], element[i][1]);
 }
 ctx.stroke();
 }, indx * 5000);
 });
 }
</script>
</body>

Simplify Your Canvas Charts Using a Library

It doesn’t have to be difficult to create a chart using Canvas from scratch, but why walk the steps taken by others? There are several excellent libraries that can simplify not only chart making but other Canvas effects. Over 50 libraries for chart making are listed in a TechSlides Page, including the in‐ creasingly popular D3, which I’ll cover in . 

Most of the libraries are freely available, though some do charge a fee for commercial use. One of the libraries, Highcharts, even provides demonstrations that you can edit in jsFiddle, making it easy to try out the library’s capability. It’s dependent on jQuery, reducing the code to an absurdly simple level. As an example, one of the demonstrations is for a very professional line chart, with plot lines and labels, 


Yet the code to create this example is equivalent to that in the following code block, which I modified to feature my own locations and temperature metric, which you can try yourself at jsFiddle:

$(function () {
 $('#container').highcharts({
 title: {
 text: 'Monthly Average Temperature',
 x: -20 //center
},
 subtitle: {
 text: 'Source: Weather.com',
 x: -20
 },
 xAxis: {
 categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
 },
 yAxis: {
 title: {
 text: 'Temperature (°F)'
 },
 plotLines: [{
 value: 0,
 width: 1,
 color: '#808080'
 }]
 },
 tooltip: {
 valueSuffix: '°F'
 },
 legend: {
 layout: 'vertical',
 align: 'right',
 verticalAlign: 'middle',
 borderWidth: 0
 },
 series: [{
 name: 'Seattle, WA',
 data: [47,51,55,59,65,70,75,75,70,60,52,47]
 }, {
 name: 'Grand Isle, VT',
 data: [27,31,40,54,67,76,81,79,71,57,45,33]
 }, {
 name: 'St. Louis, MO',
 data: [40,45,55,67,77,85,89,88,81,69,56,43]
 }]
 });
 });


Not only is the plotted chart professional looking, it’s zoomable, which means you can move your mouse cursor over the chart to examine the plot points in detail. That level of interactivity isn’t necessarily trivial in Canvas, because one of the downsides to Canvas is the fact that you can’t attach event handlers to the individual elements of Canvas— only to the Canvas area itself.

Not being able to attach an event to individual elements means that you’ll have to keep track of where the mouse is, and what’s underneath it at any point in time.

Thankfully, you can attach event handlers to SVG elements, as demonstrated.

Java Parsing Strings into Dates

Java Parsing Strings into Dates

Problem

You need to convert user input into Date or Calendar objects.

Solution

Use a DateFormat .

Explained

The DateFormat class introduced in Recipe 6.2 has some additional methods, notably
parse( ) , which tries to parse a string according to the format stored in the given
DateFormat object:

// DateParse1.java
SimpleDateFormat formatter
= new SimpleDateFormat ("yyyy-MM-dd");
String input = args.length == 0 ? "1818-11-11" : args[0];
System.out.print(input + " parses as ");
Date t;
try {
t = formatter.parse(input);
System.out.println(t);
} catch (ParseException e) {
System.out.println("unparseable using " + formatter);
}

This program parses any date back to Year Zero and well beyond Year 2000. What if the date is embedded in an input string? You could, of course, use the string’s substring( ) method to extract it, but there is an easier way. The ParsePosition object from java.text is designed to represent (and track) the posi- tion of an imaginary cursor in a string. Suppose we have genealogical data with input strings representing the times of a person’s life:

BD: 1913-10-01 Vancouver, B.C.
DD: 1983-06-06 Toronto, ON

This lists one person’s birth date (BD) and place, and death date (DD) and place. We can parse these using String.indexOf(' ') to find the space after the : character, DateFormat parse( ) to parse the date, and String.substring( ) to get the city and other geographic information. Here’s how:

// DateParse2.java
SimpleDateFormat formatter =
new SimpleDateFormat ("yyyy-MM-dd");
String input[] = {
"BD: 1913-10-01 Vancouver, B.C.",
"MD: 1948-03-01 Ottawa, ON",
"DD: 1983-06-06 Toronto, ON" };
for (int i=0; i<input.length; i++) {
String aLine = input[i];
String action;
switch(aLine.charAt(0)) {
case 'B': action = "Born"; break;
case 'M': action = "Married"; break;
case 'D': action = "Died"; break;
// others...
default: System.err.println("Invalid code in " + aLine);
continue;
}
int p = aLine.indexOf(' ');
ParsePosition pp = new ParsePosition(p);
Date d = formatter.parse(aLine, pp);
if (d == null) {
System.err.println("Invalid date in " + aLine);
continue;
}
String location = aLine.substring(pp.getIndex( ));
System.out.println(
action + " on " + d + " in " + location);
}

This works like I said it would:

Born on Wed Oct 01 00:00:00 PDT 1913 in Vancouver, B.C.
Married on Mon Mar 01 00:00:00 PST 1948 in Ottawa, ON
Died on Mon Jun 06 00:00:00 PDT 1983 in Toronto, ON

Note that the polymorphic form of parse( ) that takes one argument throws a ParseException if the input cannot be parsed, while the form that takes a ParsePosition as its second argument returns null to indicate failure.

Java Converting YMDHMS to a Calendar or Epoch Seconds

Java Converting YMDHMS to a Calendar
or Epoch Seconds

Problem

You have year, month, day, hour, minute, and maybe even seconds, and you need to
convert it to a Calendar or a Date .

Solution

Use the Calendar class’s set(y,m,d,h,m[,s]) method, which allows you to set the
date/time fields to whatever you wish. Note that when using this form and providing
your own numbers, or when constructing either a Date or a GregorianCalendar
object, the month value is zero-based while all the other values are true-origin. Pre-
sumably, this is to allow you to print the month name from an array without having
to remember to subtract one, but it is still confusing.

// GregCalDemo.java
GregorianCalendar d1 = new GregorianCalendar(1986, 04, 05); // May 5
GregorianCalendar d2 = new GregorianCalendar( );
// today
Calendar d3 = Calendar.getInstance( );
// today
System.out.println("It was then " + d1.getTime( ));
System.out.println("It is now " + d2.getTime( ));
System.out.println("It is now " + d3.getTime( ));
d3.set(Calendar.YEAR, 1915);
d3.set(Calendar.MONTH, Calendar.APRIL);
d3.set(Calendar.DAY_OF_MONTH, 12);
System.out.println("D3 set to " + d3.getTime( ));

This prints the dates as shown:

It was then Mon May 05 00:00:00 EDT 1986
It is now Thu Mar 25 16:36:07 EST 2004
It is now Thu Mar 25 16:36:07 EST 2004
D3 set to Mon Apr 12 16:36:07 EST 1915

Java Representing Dates in Other Epochs

Java Representing Dates in Other Epochs

Problem

You need to deal with dates in a form other than the Gregorian Calendar used in the
Western world.

Solution

Download the IBM calendar classes.

Explained

The only nonabstract Calendar subclass is the GregorianCalendar , as mentioned pre-
viously. However, other calendar classes do exist. IBM has a set of calendars—
Hebrew, Islamic, Buddhist, Japanese, and even an Astronomical Calendar class—that
covers most of the rest of the world. This work has been open sourced and is now
part of a project called International Components for Unicode for Java.

The calendar classes in ICU4J work in a similar fashion to the standard
GregorianCalendar class, but they have constants for month names and other infor-
mation relevant to each particular calendar. They are not subclassed from java.util.
Calendar , however, so they must be referred to by their full class name:

import
import
import
import
java.util.Locale;
com.ibm.icu.util.Calendar;
java.text.DateFormat;
com.ibm.icu.util.IslamicCalendar;
public class IBMCalDemo {
public static void main(String[] args) {
Locale ar_loc = new Locale("ar");
Calendar c = new com.ibm.icu.util.IslamicCalendar( );
DateFormat d = DateFormat.getDateInstance(DateFormat.LONG, ar_loc);
System.out.println(d.format(c.getTime( )));
}
}

I can’t include the textual output because of font limitations.

JAVA SCRIPT - Populating a Selection List from the Server

Populating a Selection List from the Server


Problem

Based on a user’s actions with another form element, you want to populate a selection list with values.

Solution

Capture the change event for the form element: 

document.getElementById("nicething").onchange=populateSelect;
In the event handler function, make an Ajax call with the form data:
var url = "nicething.php?nicething=" + value;
xmlhttp.open('GET', url, true);
xmlhttp.onreadystatechange = getThings;
xmlhttp.send(null);
In the Ajax result function, populate the selection list:
if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
 var select = document.getElementById("nicestuff");
 select.length=0;
 var nicethings = xmlhttp.responseText.split(",");
 for (var i = 0; i < nicethings.length; i++) {
 select.options[select.length] =
 new Option(nicethings[i],nicethings[i]);
 }
select.style.display="block";
} else if (xmlhttp.readyState == 4 && xmlhttp.status != 200) {
 document.getElementById('nicestuff').innerHTML =
 'Error: Search Failed!';
}

EXPLAIN

One of the more common forms of Ajax is to populate a select or other form element based on a choice made by the user. Instead of populating a select element with many options, or building a set of 10 or 20 radio buttons, you can capture the user’s choice in another form element, query a server application based on the value, and build the other form elements based on the value—all without leaving the page. 


demonstrates a simple page that captures the change event for radio but‐ tons within a fieldset element, makes an Ajax query with the value of the selected radio button, and populates a selection list by parsing the returned option list.

A comma separates each of the option items, and new options are created with the returned text having both an option label and option value. Before populating the select element, its length is set to 0. This is a quick and easy way to truncate the select element— removing all existing options, and starting fresh. 

 Creating an on-demand select Ajax application


<!DOCTYPE html>
<head>
<title>On Demand Select</title>
<style>
#nicestuff
{
 display: none;
 margin: 10px 0;
}
#nicething
{
 width: 400px;
}
</style>
</head>
<body>
<form action="backuppage.php" method="get">
 <p>Select one:</p>
 <fieldset id="nicething">
 <input type="radio" name="nicethings" value="bird" />
 <label for="bird">Birds</label><br />
 <input type="radio" name="nicethings" value="flower" />
 <label for="flower">Flowers</label><br />
 <input type="radio" name="nicethings" value="sweets" />
<label for="sweets">Sweets</label><br />
 <input type="radio" name="nicethings" value="cuddles" />
 <label for="cuddles">Cute Critters</label>
 </fieldset>
 <input type="submit" id="submitbutton" value="get nice things" />
 <select id="nicestuff"></select>
</form>
<script>
var xmlhttp;
function populateSelect() {
 var value;
 var inputs = this.getElementsByTagName('input');
 for (var i = 0; i < inputs.length; i++) {
 if (inputs[i].checked) {
 value = inputs[i].value;
 break;
 }
 }
 // prepare request
 if (!xmlhttp) {
 xmlhttp = new XMLHttpRequest();
 }
 var url = "nicething.php?nicething=" + value;
 xmlhttp.open('GET', url, true);
 xmlhttp.onreadystatechange = getThings;
 xmlhttp.send(null);
}
// process return
function getThings() {
 if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
 var select = document.getElementById("nicestuff");
 select.length=0;
 var nicethings = xmlhttp.responseText.split(",");
 for (var i = 0; i < nicethings.length; i++) {
 select.options[select.length] =
 new Option(nicethings[i], nicethings[i]);
 }
 select.style.display="block";
 } else if (xmlhttp.readyState == 4 && xmlhttp.status != 200) {
 alert("No items returned for request");
 }
}
document.getElementById("submitbutton").style.display="none";
document.getElementById("nicething").onclick=populateSelect;
</script>
</body>

The form does have an assigned action page, and a submit button that’s hidden when the script is first run. These are the backup if scripting is turned off. The application is also old school—text-based data that you can either append directly to the page (if for‐ matted as HTML), or parse using the String functions.

JSON is nice, but there’s always room for just plain text. The example uses a PHP application to populate the selection list. It could also be a Node application if you want to use JavaScript in both the client and server:

<?php
//If no search string is passed, then we can't search
if(empty($_REQUEST['nicething'])) {
 echo "No State Sent";
} else {
 //Remove whitespace from beginning & end of passed search.
 $search = trim($_REQUEST['nicething']);
 switch($search) {
 case "cuddles" :
 $result = "puppies,kittens,gerbils";
 break;
 case "sweets" :
 $result = "licorice,cake,cookies,custard";
 break;
 case "bird" :
 $result = "robin,mockingbird,finch,dove";
 break;
 case "flower" :
 $result = "roses,lilys,daffodils,pansies";
 break;
 default :
 $result = "No Nice Things Found";
 break;
 }
 echo $result;
}
?>


Progressively building form elements using Ajax or another communication technique isn’t necessary in all applications, but it is a great way to ensure a more effective form in cases where the data can change, or the form is complex.

JAVA SCRIPT - Processing JSON from an Ajax Request

Processing JSON from an Ajax Request


Problem

You want to format Ajax data as JSON, rather than text or XML. 

Solution

Create and initiate the Ajax request the same as for an XML or text data request. In this code, the service is a Node application, accessible at port 8080:

// ajax object
if (window.XMLHttpRequest) {
 httpRequest = new XMLHttpRequest();
}
// build request
var url = "http://shelleystoybox.com:8080";
httpRequest.open('GET', url, true);
httpRequest.onreadystatechange = getData;
httpRequest.send();

In the function to process the response, use the JSON object’s parse()method to convert the returned text into a JavaScript object:

function getData() {
 if (httpRequest.readyState == 4 && httpRequest.status == 200) {
 try {
 // Javascript function JSON.parse to parse JSON data
 var jsonObj = JSON.parse(httpRequest.responseText);
 console.log(jsonObj.list[0].name);
 } catch (e) {
 console.log(e.message);
 }
 }
}


The key to sending JSON in response to an Ajax request is to use whatever language’s version of the JSON.stringify() method to convert the object into a JSON-formatted string. In the following Node application, we can use the Node version of JSON to format the data. The MIME type for the data is also set to application/json:


var http = require('http');
// start server, listen for requests
var server = http.createServer().listen(8080);
server.on('request', function(req, res) {
 var titleList = {
 "list" : [
 { "id": "id1",
 "name": "Title One"
 },
 { "id": "id12",
 "name": "Another Value"
 },
 { "id": "id20",
 "name": "End of the Road"
 },
 { "id": "id24",
 "name": "One More"
 }
 ],
 "totalRecords": 4
 };
res.writeHeader(200, {"Content-Type": "application/json", "Access-Control-All
ow-Origin": "*"});
 res.end(JSON.stringify(titleList));
});

Processing JSON data from an Ajax request


var httpRequest;
// ajax object
if (window.XMLHttpRequest) {
 httpRequest = new XMLHttpRequest();
}
// build request
var url = "http://shelleystoybox.com:8080";
httpRequest.open('GET', url, true);
httpRequest.onreadystatechange = getData;
httpRequest.send();
function printData(element) {
 console.log(element.name);
}
function getData() {
 if (httpRequest.readyState == 4 && httpRequest.status == 200) {
 try {
 // Javascript function JSON.parse to parse JSON data
 var jsonObj = JSON.parse(httpRequest.responseText);
 jsonObj.list.forEach (function(element) {
 console.log(element.name);
 });
 } catch (e) {
 console.log(e.message);
 }
 }
}

Java printing Date/Time in a Given Format

Java printing Date/Time in a Given Format

Problem

You want to print the date and/or time in a locale-sensitive or otherwise-specified
format.

Solution

Use java.text.DateFormat .

Explained

To print the date in the correct format for whatever locale your software lands in,
simply use the default DateFormat formatter, which is obtained by calling DateFormat.
getInstance( ) :

import java.util.*;
import java.text.*;
public class DateFormatBest {
public static void main(String[] args) {
Date today = new Date( );
DateFormat df = DateFormat.getInstance( );
System.out.println(df.format(today));
DateFormat df_fr =
DateFormat.getDateInstance(DateFormat.FULL, Locale.FRENCH);
System.out.println(df_fr.format(today));
}
}

When I run this, it prints:

3/3/04 12:17 PM
mercredi 3 mars 2004

You can ask for a default date and time formatter ( df in the example), or a TimeFormatter or DateFormatter that extracts just the time or date portion of the Date object ( df_fr in the example). You can also request a nondefault Locale ( df_fr in the example). Five codes—FULL, LONG, MEDIUM, SHORT and DEFAULT—can be passed to describe how verbose a format you want. Suppose you want the date printed, but instead of the default format, you want it printed like “Sun 2004.07.18 at 04:14:09 PM PDT”. A look at the Javadoc page for SimpleDateFormat —the only nonabstract subclass of DateFormat —reveals that it has a rich language for specifying date and time formatting. Be aware that in so doing you are presuming to know the correct format in all locales; see Chapter 15 for why this may be a bad idea. To use a default format, of course, we can just use the Date object’s toString( ) method, and for a localized default format, we use DateFormat.getInstance( ) . But to have full control and get the “Sun 2004.07.18 at 04:14:09 PM PDT”, we construct an instance explicitly, like so:

new SimpleDateFormat ("E yyyy.MM.dd 'at' hh:mm:ss a zzz");

E means the day of the week; yyyy , MM , and dd are obviously year, month, and day. The quoted string 'at' means the string “at”. hh:mm:ss is the time; a means A.M. or P.M., and zzz means the time zone. Some of these are more memorable than others; I find the zzz tends to put me to sleep. Here’s the code:

// DateDemo.java
Date dNow = new Date( );
/* Simple, Java 1.0 date printing */
System.out.println("It is now " + dNow.toString( ));
// Use a SimpleDateFormat to print the date our way.
SimpleDateFormat formatter
= new SimpleDateFormat ("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
System.out.println("It is " + formatter.format(dNow));

You can use as many of the given symbols as needed. Where a format can be used either in text or numeric context, you can set it to a longer form by repetitions of the character. For codes marked Text , four or more pattern letters cause the formatter to use the long form; fewer cause it to use the short or abbreviated form if one exists. Thus, E might yield Mon, whereas EEEE would yield Monday. For those marked Number , the number of repetitions of the symbol gives the minimum number of dig- its. Shorter numbers are zero-padded to the given number of digits. The year is han- dled specially: yy yields an ambiguous * two-digit year (98, 99, 00, 01...), whereas yyyy yields a valid year (2001). For those marked Text and Number , three or more symbols causes the formatter to use text, while one or two make it use a number: MM might yield 01, while MMM would yield January.

Java Finding Today’s Date

Java Finding Today’s Date

Problem

You want to find today’s date.

Solution

Use a Date object’s toString( ) method.

Explained

The quick and simple way to get today’s date and time is to construct a Date object
with no arguments in the constructor call, and call its toString( ) method:

// Date0.java
System.out.println(new java.util.Date( ));

However, for reasons just outlined, we want to use a Calendar object. Just use Calendar.getInstance( ).getTime( ) , which returns a Date object (even though the name makes it seem like it should return a Time value * ) and prints the resulting Date object, using its toString( ) method or preferably a DateFormat object. You might be tempted to construct a GregorianCalendar object, using the no-argument construc- tor, but if you do this, your program will not give the correct answer when non- Western locales get Calendar subclasses of their own (which might occur in some future release of Java). The static factory method Calendar.getInstance( ) returns a localized Calendar subclass for the locale you are in. In North America and Europe it will likely return a GregorianCalendar , but in other parts of the world it might (some- day) return a different kind of Calendar . Do not try to use a GregorianCalendar ’s toString( ) method; the results are truly impressive, but not very interesting. Sun’s implementation prints all its internal state information; Kaffe’s inherits Object ’s toString( ) , which just prints the class name and the hashcode. Neither is useful for our purposes.

C> java Date1
java.util.
GregorianCalendar[time=932363506950,areFieldsSet=true,areAllFieldsSet=true,lenient=tr
ue,zone=java.util.SimpleTimeZone[id=America/Los_Angeles,offset=-
28800000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=3,sta
rtDay=1,startDayOfWeek=1,startTime=7200000,endMode=2,endMonth=9,endDay=-
1,endDayOfWeek=1,endTime=7200000],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEA
R=1999,MONTH=6,WEEK_OF_YEAR=30,WEEK_OF_MONTH=4,DAY_OF_MONTH=18,DAY_OF_YEAR=199,DAY_
OF_WEEK=1,DAY_OF_WEEK_IN_MONTH=3,AM_PM=1,HOUR=10,HOUR_OF_
DAY=22,MINUTE=51,SECOND=46,MILLISECOND=950,ZONE_OFFSET=-28800000,DST_OFFSET=3600000]

Calendar ’s getTime( ) returns a Date object, which can be passed to println( ) to print today’s date (and time) in the traditional (but non-localized) format:

/ Date2.java
System.out.println(Calendar.getInstance( ).getTime( ));

Java Program: Number Palindromes

Java Program: Number Palindromes


My wife, Betty, recently reminded me of a theorem that I must have studied in high
school but whose name I have long since forgotten: that any positive integer number
can be used to generate a palindrome by adding to it the number comprised of its
digits in reverse order. Palindromes are sequences that read the same in either direc-
tion, such as the name “Anna” or the phrase “Madam, I’m Adam” (ignoring spaces
and punctuation). 

We normally think of palindromes as composed of text, but the
concept can be applied to numbers: 13531 is a palindrome. Start with the number
72, for example, and add to it the number 27. The results of this addition is 99,
which is a (short) palindrome. Starting with 142, add 241, and you get 383. Some
numbers take more than one try to generate a palindrome. 1951 + 1591 yields 3542,
which is not palindromic. The second round, however, 3542 + 2453, yields 5995,
which is. The number 17,892, which my son Benjamin picked out of the air, requires
12 rounds to generate a palindrome, but it does terminate:

C:\javasrc\numbers>java Palindrome 72 142 1951 17892
Trying 72
72->99
Trying 142
142->383
Trying 1951
Trying 3542
1951->5995
Trying 17892
Trying 47763
Trying 84537
Trying 158085
Trying 738936
Trying 1378773
Trying 5157504
Trying 9215019
Trying 18320148
Trying 102422529
Trying 1027646730
Trying 1404113931
17892->2797227972
C:\javasrc\numbers>

If this sounds to you like a natural candidate for recursion, you are correct. Recur- sion involves dividing a problem into simple and identical steps, which can be imple- mented by a function that calls itself and provides a way of termination. Our basic approach, as shown in method findPalindrome , is:

long findPalindrome(long num) {
if (isPalindrome(num))
return num;
return findPalindrome(num + reverseNumber(num));
}

That is, if the starting number is already a palindromic number, return it; otherwise, add it to its reverse, and try again. The version of the code shown here handles sim- ple cases directly (single digits are always palindromic, for example). We won’t think about negative numbers, as these have a character at the front that loses its meaning if placed at the end, and hence are not strictly palindromic. Further, palindromic forms of certain numbers are too long to fit in Java’s 64-bit long integer. These cause underflow, which is trapped. As a result, an error message like “too big” is reported. * Having said all that, Example shows the code.

Example. Palindrome.java
/** Compute the Palindrome of a number by adding the number composed of
* its digits in reverse order, until a Palindrome occurs.
* e.g., 42->66 (42+24); 1951->5995 (1951+1591=3542; 3542+2453=5995).
*/
public class Palindrome {
public static void main(String[] argv) {
for (int i=0; i<argv.length; i++)
try {
long l = Long.parseLong(argv[i]);
if (l < 0) {
System.err.println(argv[i] + " -> TOO SMALL");
continue;
}
System.out.println(argv[i] + "->" + findPalindrome(l));
} catch (NumberFormatException e) {
System.err.println(argv[i] + "-> INVALID");
} catch (IllegalStateException e) {
System.err.println(argv[i] + "-> TOO BIG(went negative)");
}
}
/** find a palindromic number given a starting point, by
* calling ourself until we get a number that is palindromic.
*/
static long findPalindrome(long num) {
if (num < 0)
throw new IllegalStateException("went negative");
if (isPalindrome(num))
return num;
System.out.println("Trying " + num);
return findPalindrome(num + reverseNumber(num));
}
/** The number of digits in Long.MAX_VALUE */
protected static final int MAX_DIGITS = 19;
// digits array is shared by isPalindrome and reverseNumber,
// which cannot both be running at the same time.
/* Statically allocated array to avoid new-ing each time. */
static long[] digits = new long[MAX_DIGITS];
/** Check if a number is palindromic. */
static boolean isPalindrome(long num) {
if (num >= 0 && num <= 9)
return true;
int nDigits = 0;
while (num > 0) {
digits[nDigits++] = num % 10;
num /= 10;
}
for (int i=0; i<nDigits/2; i++)
if (digits[i] != digits[nDigits - i - 1])
return false;
return true;
}
static long reverseNumber(long num) {
int nDigits = 0;
while (num > 0) {
digits[nDigits++] = num % 10;
num /= 10;
}
long ret = 0;
for (int i=0; i<nDigits; i++) {
ret *= 10;
ret += digits[i];
}
return ret;
}
}