Chapter 13
In This Chapter
Editing styles
Employing images
Executing JavaScript animations
Developing a slideshow
“To achieve style, begin by affecting none.”
— E.B. White, The Elements of Style
Once you understand how to manipulate the DOM objects using JavaScript, web pages change from static documents into interactive applications that can respond to user input, change without reloading, and deliver live data to a variety of different computing devices.
The DOM’s Style
object is a powerful tool for making a web page change its look and adapt in real time to user input or current browser conditions. The Style
object gives programmers access to CSS style properties for any selected element or collection of elements in a document. (For more on the basic rules and syntax of CSS, see Chapter 1.)
Some of the things that you can do with the Style
object are
The Style
object works the same way as other DOM objects. It includes a set of properties that you can use to get or set different aspects of a selected element.
The properties of the Style
object mirror CSS properties. The difference between the two is that the DOM Style
objects’ properties are spelled using camelCase
instead of using CSS’s dashed format.
Table 13-1 shows a few of the most commonly used Style
object properties, along with what CSS property they modify.
Table 13-1 Common Style Object Properties and Their CSS Equivalents
Property |
CSS Style |
Description |
|
background-color |
Gets or sets the background color of an element |
|
border-width |
Sets the width of all four borders of an element |
|
font-family |
Gets or sets a list of font family names assigned to the text in an element |
|
line-height |
Gets or sets the distance between lines of text |
|
text-align |
Gets or sets the horizontal alignment of text in a black element |
The Style
object returns the currently applied inline styles of an element. It doesn’t tell you what the actual style is that the browser will render because it doesn’t include styles held in the external CSS files or styles inside of style
elements.
For this reason, the Style
object is not entirely useful for getting the style of an element. In Listing 13-1, the div
element has an inline style and several style rules that are set within a style
element.
When using the Style
object to get the style properties of an element, only styles set using JavaScript or inline CSS are returned.
Listing 13-1: The Wrong Way to Get an Element’s Current Style
<html>
<head>
<title>Getting Inline Styles</title>
<style>
#myText {
color: white;
background-color: black;
font-family: Arial;
margin-bottom: 20px;
}
#stylesOutput {
font-size: 18px;
font-family: monospace;
}
</style>
<script>
function getElementStyles(e){
var colorOutput = "color: " + e.target.style.color;
var fontSizeOutput = "font size: " + e.target.style.fontSize;
document.getElementById("stylesOutput").innerHTML = colorOutput + "<br>" + fontSizeOutput;
}
</script>
</head>
<body>
<div id="myText" style="font-size: 26px;" onclick="getElementStyles(event);">Here is some text.</div>
<div id="stylesOutput"></div>
</body>
</html>
Figure 13-1 shows what happens when you load this page in a browser and click on the div
element.
The two important things to notice about the results of this script are
Style
object’s property is blank, even though the div’s color was set to white using CSS in the head.Style
object’s font size is set correctly because the CSS font-size
property was set using inline CSS.A good way to get the current style of an element is by using window.getComputedStyle()
, as shown in Listing 13-2.
Listing 13-2: The Correct Way to Get an Element's Current Style
<html>
<head>
<title>Getting Computed Styles</title>
<style>
#myText {
color: white;
background-color: black;
font-family: Arial;
margin-bottom: 20px;
}
#stylesOutput {
font-size: 18px;
font-family: monospace;
}
</style>
<script>
function getElementStyles(e){
var computedColor = window.getComputedStyle(e.target).getPropertyValue("color");
var computedSize = window.getComputedStyle(e.target).getPropertyValue("font-size");
var colorOutput = "color: " + computedColor;
var fontSizeOutput = "font size: " + computedSize;
document.getElementById("stylesOutput").innerHTML = colorOutput + "<br>" + fontSizeOutput;
}
</script>
</head>
<body>
<div id="myText" style="font-size: 26px;" onclick="getElementStyles(event);">Here is some text.</div>
<div id="stylesOutput"></div>
</body>
</html>
Figure 13-2 shows the output of Listing 13-2: showing the computed (and correct) style
property values.
Notice in Listing 13-2, the getPropertyValue
function takes the CSS property (font-size
) rather than the style
property (fontSize
). The reason is that the script is querying the value of font-size
directly from the element, rather than through the Style
object (which will only tell us about the inline styles).
To set properties of the Style
object, select the element you want the new style to apply to and then use dot notation or bracket notation to assign a new value to a property of the Style
object.
To change the border-width of an element that has the id of "borderedSquare"
, you would use the following code:
document.getElementById("borderedSquare").style.borderWidth = "15px";
You can use CSS styles to control the look of elements, but you can also use them to control the positioning of elements. By using JavaScript loops with style
property modifications, you can create basic animations fairly easily.
In Listing 13-3, a JavaScript function moves a square across the screen by using a for
loop to change the CSS 'left'
property.
Listing 13-3: Animating an Element with the Style Object
<html>
<head>
<title>JavaScript animation</title>
<style>
#square {
width: 100px;
height: 100px;
background-color: #333;
position: absolute;
left: 0px;
top: 100px;
}
</style>
<script>
function moveSquare() {
for (i=0; i<500; i++){
document.getElementById("square").style.left = i+"px";
}
}
</script>
</head>
<body onload="moveSquare();">
<div id="square"></div>
</body>
</html>
If you open this script in a browser, it seemingly opens with animation already complete. In fact, the animation actually does run, but it happens so fast that you can’t see it happening (unless you happen to have a very slow computer or very fast eyes).
What’s needed in order to make this animation run at human speed is a pause between each iteration of the loop. The most common way to create a loop with pauses is by using the setTimeout()
method of the Window
object.
The setTimeout()
method takes two arguments:
By putting a call to setTimeout()
within a function and calling the function recursively, we can gain control over how fast the animation runs. (For more on writing recursive functions, see Chapter 7.)
In Listing 13-4, the box is now moving at the much slower pace of 1 pixel per 1/100th second. This example also features a few other improvements over Listing 13-3:
Listing 13-4: Animation with the Style Object, setTimeout(), and Recursion
<html>
<head>
<title>JavaScript animation</title>
<style>
#square {
width: 100px;
height: 100px;
background-color: #333;
position: absolute;
left: 0px;
top: 100px;
}
</style>
<script>
// wait until the window is loaded
window.addEventListener('load',initialize,false);
function initialize(){
//move the square when clicked
document.getElementById("square").addEventListener('click',function(e){
//get the starting position
var left = window.getComputedStyle(e.target).getPropertyValue("left");
//convert left to a base 10 number
left = parseInt(left, 10);
moveSquare(left,100);
}, false);
}
function moveSquare(left,numMoves) {
document.getElementById("square").style.left = left+"px";
if (numMoves > 0) {
numMoves--;
left++;
setTimeout(moveSquare,10,left,numMoves);
} else {
return;
}
}
</script>
</head>
<body>
<div id="square"></div>
</body>
</html>
Figure 13-3 shows the output of Listing 13-4 when run in a browser.
HTML img
elements are normally pretty static, unchanging things — unless the image is an animation, of course. With JavaScript, effects such as the resizing of images, repositioning images, lightbox effects, rollover effects, and more are all possible by manipulating the attributes of the img
element and by changing CSS styles.
The DOM’s Image
object gives you access to the properties of an HTML img
element. Once you have that access, you can set and get values in order to change any of the valid attributes of the element. The properties of the Image
object are shown in Table 13-2.
Table 13-2 Properties of the Image Object
Property |
Description |
|
Gets or sets the value of an image’s |
|
Is true when the browser is finished loading the image |
|
Gets or sets the value of an image’s |
|
Gets or sets whether an image should be part of a server-side image-map |
|
Gets the image’s original height |
|
Gets the image’s original width |
|
Gets or sets the value of an image’s |
|
Gets or sets the value of an image’s |
|
Gets or sets the value of an image’s |
A rollover button is a button that changes in some way when the mouse pointer is hovering over it. Rollover buttons are a great way to indicate to the user that an image can be clicked. You can also use them to reveal more information about what will happen if a button or a link is clicked. You can even use them just for fun or aesthetics. Some web designers like to put so-called easter eggs into their websites that will trigger image changes or other changes on a site when a mouse hovers over them or when someone clicks on certain hidden areas on a page.
The example in Listing 13-5 shows how to create a simple image rollover effect in JavaScript.
Listing 13-5: An Image Rollover Effect
<html>
<head>
<title>Rollover image</title>
<script>
function swapImage(imgToSwap){
imgToSwap.src = "button2.png";
imgToSwap.alt = "you're mousing over my button!";
}
function swapBack(imgToSwap){
imgToSwap.src = "button1.png";
imgToSwap.alt = "mouse over me!";
}
</script>
</head>
<body>
<img src="button1.png" id="myButton" onmouseover="swapImage(this);" onmouseout="swapBack(this);" alt="mouse over me!">
</body>
</html>
Another useful user interface trick to make your websites more user-friendly is to slightly increase the size of image buttons when a user hovers over them. This nice little trick subtly indicates that the target image is clickable and provides a little bit of interactivity as well.
Listing 13-6 modifies the code from Listing 13-5 to increase the image size by 5 percent on mouseover
events.
Listing 13-6: Increasing Image Size on mouseover
<html>
<head>
<title>Rollover image size</title>
<script>
function growImage(imgToGrow){
imgToGrow.width += imgToGrow.width * .05;
imgToGrow.height += imgToGrow.width * .05;
}
function restoreImage(imgToShrink){
imgToShrink.width = imgToShrink.naturalWidth;
imgToShrink.height = imgToShrink.naturalHeight;
}
</script>
</head>
<body>
<img src="button1.png" id="myButton" onmouseover="growImage(this);" onmouseout="restoreImage(this);" alt="mouse over me!">
</body>
</html>
Slideshows (also known as carousels) are a popular way to display multiple images in a single space on a site. Often used on the homepage of websites, they can really liven up your site.
Slideshows often feature transition effects to switch between multiple images. These transition effects are generally created using a library of JavaScript functions, such as jQuery. You can also create transition effects using just ordinary JavaScript, CSS, and the DOM. In the interest of simplicity, the slideshow in Listing 13-7 only switches between images and doesn’t feature a transition of any sort.
Listing 13-7: A Slideshow Built Using JavaScript and CSS
<html>
<head>
<title>JavaScript slideshow</title>
<style>
#carousel {
position: absolute;
width: 800px;
height: 400px;
top: 100px;
left: 100px;
display: hidden;
}
</style>
<script>
var slides = [
"<div id='slide1'>my first slide<br><img src='image1.jpg'></div>",
"<div id='slide2'>my second slide<br><img src='image2.jpg'></div>",
"<div id='slide3'>my third slide<br><img src='image3.jpg'></div>"];
var currentSlide = 0;
var numberOfSlides = slides.length-1;
window.addEventListener("load",loader,false);
function loader(){
changeImage();
}
function changeImage(){
console.log("changeImage function");
if (currentSlide > numberOfSlides){
currentSlide = 0;
}
document.getElementById("carousel").innerHTML=slides[currentSlide];
console.log('displaying slide' + currentSlide + "of " + numberOfSlides);
currentSlide++;
setTimeout(changeImage,1000);
}
</script>
</head>
<body>
<div id="carousel"></div>
</body>
</html>
CSS3 and the DOM’s Style
object have properties for simplifying the task of animating elements. Used together, the animation properties can enable you to create some pretty cool animations with minimal effort. The Style
object’s animation properties are listed in Table 13-3.
Table 13-3 Animation-Related Properties of the Style Object
Property |
Description |
|
Sets all the animation properties except the |
|
Gets or sets a delay to happen before the animation starts |
|
Gets or sets whether the animation should play in reverse on some or all cycles |
|
Gets or sets the length of time an animation takes to complete one cycle |
|
Gets or sets what values are applied by the animation outside the time it’s executing |
|
Gets or sets the number of times an animation should be played |
|
Gets or sets a list of animations, using keyframe at-rules |
|
Gets or sets the speed curve that describes how the animation should progress over time |
|
Gets or sets whether the animation is running or paused. |
In Listing 13-8, a simple animation is created using CSS. The timing and keyframes of the animation are first configured with CSS, and then JavaScript is used to pause and resume the animation. With a little creativity, there are many possibilities for how you could control this animation using JavaScript.
In Listing 13-8, both the standard and prefixed CSS styles are included.
Listing 13-8: Controlling CSS3 Animation Using JavaScript
<!DOCTYPE>
<html>
<head>
<style>
#words {
position: relative;
width: 300px;
height: 200px;
text-align: center;
padding-top: 20px;
font-family: Arial;
border-radius: 6px;
color: white;
/* Chrome, Safari, Opera */
-webkit-animation-name: movewords;
-webkit-animation-duration: 6s;
-webkit-animation-timing-function: linear;
-webkit-animation-delay: 0s;
-webkit-animation-iteration-count: infinite;
-webkit-animation-direction: alternate;
-webkit-animation-play-state: running;
/* Standard syntax */
animation-name: movewords;
animation-duration: 6s;
animation-timing-function: linear;
animation-delay: 0s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-play-state: running;
}
/* Chrome, Safari, Opera */
@-webkit-keyframes movewords {
0% {background:red; left:100px; top:0px;}
25% {background:blue; left:200px; top:100px;}
50% {background:blue; left:300px; top:200px;}
75% {background:blue; left:200px; top:200px;}
100% {background:red; left:100px; top:0px;}
}
/* Standard syntax */
@keyframes movewords {
0% {background:red; left:100px; top:0px;}
25% {background:blue; left:200px; top:100px;}
50% {background:blue; left:300px; top:200px;}
75% {background:blue; left:200px; top:200px;}
100% {background:red; left:100px; top:0px;}
}
</style>
<script>
window.addEventListener("load",registerEvents,false);
function registerEvents(e){
document.getElementById("stop").addEventListener("click",stopAni,false);
document.getElementById("go").addEventListener("click",startAni,false);
}
function stopAni(){
document.getElementById("words").style.webkitAnimationPlayState = "paused";
document.getElementById("words").style.AnimationPlayState = "paused";
}
function startAni(){
document.getElementById("words").style.webkitAnimationPlayState = "running";
document.getElementById("words").style.AnimationPlayState = "running";
}
</script>
</head>
<body>
<h1 id="words">Movin' Around</h1>
<button type="button" id="stop">Pause</button>
<button type="button" id="go">Run</button>
</body>
</html>