Wednesday, October 21, 2009

12.4 Offering Body Text Size Choices to Users



[ Team LiB ]










12.4 Offering Body Text Size Choices to Users


NN 6, IE 5




12.4.1 Problem



You want to let users choose the relative
font size for the content of the page.





12.4.2 Solution



Create a user interface element that lets users select from three or
four different font sizes. Each choice invokes the
changeSizeStyle(
)
function shown in the Discussion. This
function enables a style sheet whose ID is passed as an argument and
disables the rest. All of the related style sheets apply themselves
to the body element. As an added bonus, the
changeSizeStyle( ) function calls upon the
cookies.js library (Recipe 1.9) to preserve the
setting to be applied to the page the next time the user visits.





12.4.3 Discussion



This is a three-part solution, involving HTML for the font size
controller, style sheets, and scripts. The result is a small
controller on the page that lets users select from three font size
bases upon which the rest of the page renders, as shown in Figure 12-1.




Figure 12-1. Text size controller for users



HTML for the controller defines one surrounding
div element and several nested
img elements. Three of the img
elements are surrounded by links, whose onclick
event handlers invoke the changeSizeStyle( )
function. To prevent blank space from occurring between the images,
avoid source code line breaks between elements. The following HTML
code inserts line breaks inside element tags:



<div id="textSizer">
<img src="fontSizer.jpg" height="18" width="72" alt="Font Sizer"><a
href="" onclick="changeSizeStyle('smallStyle'); return false"><img
class="textSize" src="fontSmall.jpg" height="18" width="18"
alt="Smallest" /></a><a href="" onclick="changeSizeStyle(''); return false"><img
class="textSize" src="fontMedium.jpg" height="18" width="18" alt="Default" /></a><a
href="" onclick="changeSizeStyle('largeStyle'); return false"><img
class="textSize" src="fontLarge.jpg" height="18" width="18" alt="Biggest" /></a>
</div>


The style sheet portion of this solution consists of several distinct
style elements (or they could be imported via
link elements). Each style
element has an id attribute assigned to it that
comes into play during script execution. By default, the controller
is not rendered, but scripts take care of this, as discussed shortly:



<style id="normalStyle" type="text/css">
body {font-family:Verdana, Helvetica, sans-serif;
font-size:small}
#textSizer {margin-left:80%; display:none}
.textSize {border:1px solid black}
</style>
<style id="sizer" type="text/css" disabled="disabled">
@import url("textSizer.css");
</style>
<style id="smallStyle" type="text/css" disabled="disabled">
@import url("smallFont.css");
</style>
<style id="largeStyle" type="text/css" disabled="disabled">
@import url("largeFont.css");
</style>


Each of the imported style sheets consists of a single rule. One,
textSizer.css, is for the controller:



#textSizer {display:block}


The smallFont.css file consists of the following
rule:



body {font-size:xx-small}


The largeFont.css file has the following:



body {font-size:large}


The JavaScript portion relies on the cookies.js
library (Recipe 1.9) and consists of two functions and a
statement that executes one of the functions while the page loads:



<script type="text/javascript" src="cookies.js"></script>
<script type="text/javascript">
// enable/disable style sheet per cookie setting
function setSizeStyle( ) {
if (document.getElementById) {
document.getElementById("sizer").disabled = false;
var styleCookie = getCookie("fontSize");
var styleIDs = ["smallStyle", "largeStyle"];
for (var i = 0; i < styleIDs.length; i++) {
if (styleCookie = = styleIDs[i]) {
document.getElementById(styleIDs[i]).disabled = false;
} else {
document.getElementById(styleIDs[i]).disabled = true;
}
}
}
}
// set active style now, before content renders
setSizeStyle( );

// invoked by clicking on sizer icons
function changeSizeStyle(styleID) {
setCookie("fontSize", styleID, getExpDate(180, 0, 0));
setSizeStyle( );
}
</script>


Users' choices are preserved as a cookie value so
that the previous setting is applied on the next visit to the page.



Despite the comparatively small amount of CSS, HTML, and JavaScript
code involved for this solution, there is quite a bit going on here
so that the application runs well in most modern browsers, yet
degrades gracefully in older browsers.



The controller consists entirely of images so that even as the body
font size is adjusted, the label's text
won't change as well. While the label could be given
an inline style attribute to override the more
remote style settings, using an image is easier. If the label text
were allowed to resize, the position of the clickable images would
shift with each click, driving users crazy. While the example here
uses a non-positioned element and a percentage length for the left
margin, you might find it more appealing to turn it into an
absolute-positioned element that is keyed to some other
relative-positioned wrapper element in your design.



Style sheet definitions are set up to allow a default font size to
govern the page for even the older browsers that may respect style
sheets but not the W3C DOM syntax used for style sheet manipulation.
Notice that this example does not specify a specific font size in any
unit. Font sizing is always a problem in browsers due to their quirky
behavior with regard to user settings in the browser and operating
system. Using relative sizes suggests that we let users determine
their default sizes outside of our application, and they can choose
to display your font sets either in a smaller or larger font than the
default. This also assumes that more detailed font size settings
throughout each page's document are also relative,
rather than absolute. Thus, top-level headlines may be specified in
em units to derive the desired larger size, but always relative to
the surrounding body element's
current size. In a way, this approach embraces the flaws of the
browser world, leaving the precise display up to the user. Your job
as designer is to make sure the content flows appropriately in a
variety of sizes.



Three initially disabled style elements provide
alternative display characteristics (using the backward-compatible,
yet XHTML-friendly syntax for the disabled
attribute). For example, while the default style sheet completely
hides the size controller, one of the three disabled style sheets has
the power�when enabled�to show the controller to the
user. The same is true for either of the other body font style
sheets. Because all three of these style elements
come after the default style sheet, if any one of them is enabled,
the last specification for a particular style property wins the
competition (according to CSS cascading precedence rules). The job
for the script is to enable or disable the extra style sheets as
needed. Redirection to an imported style sheet is needed to keep
Navigator 4 from applying the style rule, regardless of the
disabled attribute setting.



To make the user choice stick on the next visit by the user, the
scripts call upon the cookie reading and writing routines from the
cookies.js library shown in Recipe 1.9. Make
sure that this library is loaded ahead of the scripts that control
the font sizing.



Most of the work is handled by the setSizeStyle(
)
function. Using the presence of the
document.getElementById( ) method in the browser
as a threshold point (thus limiting this to IE 5 or later and NN 6 or
later), the function immediately enables the style sheet that lets
the controller be visible. Next it looks for the existence of the
cookie from a previous visit. If it's there, the
value (the ID of the style sheet used) becomes the ID of the style
sheet to enable, while the other alternate is disabled. There is no
need to disable the default style because the new one overrides the
font-size property, while leaving all other
default settings intact. The mechanism shown in the example allows
for additional size settings in case you wish to offer more than the
three shown here. Simply add the style element
with its own unique ID, and add that ID to the array inside the
function, as well as to the parameter of the
onclick event handler of the new
image's surrounding hyperlink element.



Because the only objects that the setSizeStyle( )
function operates on are style elements defined
earlier in the page, the function can run before the body and its
objects are part of the current object model. As shown in the
preceding script, a single call to setSizeStyle( )
immediately following the function's definition
invokes the method as the head portion loads.



When a user clicks on one of the sizer images, the
onclick event handler invokes the
changeSizeStyle(
)
function, passing the ID of the style
sheet to apply to the content. This function changes the cookie
setting and then calls setSizeStyle( ) to finish
the job. The setSizeStyle( ) function becomes a
vital module for the entire application.





12.4.4 See Also



Recipe 1.9 for cookie utilities; Recipe 11.4 for importing style
sheets.









    [ Team LiB ]



    No comments:

    Post a Comment