Working with Dynamic Page Layout Maureen Smith Professor, Saddleback College CIM 271B - Tutorial 1 Objectives • In this tutorial you will: – Arrange objects using CSS positioning attributes – Learn about the history and theory of DHTML – Learn how DHTML is implemented on different browsers – Work with cross-browser DHTML pages – Create and link to an API of customized JavaScript functions – Arrange objects using JavaScript – Create an animation using JavaScript Session 1.1 • In this session you’ll be introduced to the theory and history of DHTML – Will learn how to control the placement of objects on your Web page with CSS – Will learn about style sheet attributes that control the appearance of your objects – Finally, will apply your knowledge to design layout of an opening page for Avalon books Introduction to DHTML • Early in HTML development, were limited to static Web pages – Authors/browser developers began to look for ways to create more dynamic presentations whose content and design could be changed after page had been loaded – Early attempts involved applets (small programs browser would retrieve and install along with Web page) • Starting with 4.0 versions of Netscape and IE, a new approach was offered – HTML code itself supported dynamic elements – Unlike applets, no additional software was needed to create and display dynamic pages – These enhancements are known as dynamic HTML or DHTML • DHTML involves interaction of 3 elements: – The HTML code of the page – Cascading style sheets to define appearance – A scripting language, usually JavaScript or VBScript, to control behavior of elements • By working with these elements, author can create documents that dynamically interact with the user – Some uses for DHTML include: – Animated text that moves and changes in response to user action – Pop-up menus that provide users with quick access to other pages in site without devoting valuable screen space to a long, complicated list of links – Web pages that retrieve their content from external data sources, giving authors more freedom in type of material they can display • Terry wants you to create an opening page for Avalon Books that contains animated text and graphics – Figure 1-1 shows general appearance and content she wants – Image of Avalon Books’ best-selling fiction book – Image of Avalon Books’ best-selling nonfiction book – Image of a person reading a book, which contains a link to rest of the site – Text string “Avalon” – Text string “Books” • Terry wants single word “Avalon” to appear near top of page and drop vertically down – At a certain point, it should stop dropping and the word “Books” should appear, moving to right from behind “Avalon” – After that, three other images should appear on screen in sequence (see Figure 1-2) • To create this page, need to know how to place objects at specific coordinates – Then need to know how to move those objects – Placing objects on page can be done by using style attributes of the CSS language Positioning Objects with CSS • Cascading style sheets were originally used to control appearance of content – An extension called CSS-Positioning, or CSS-P, added ability to control layout of the page – Eventually became part of CSS2 specs, though will still occasionally see term “CSS-P” used to refer specifically to those style attributes • With CSS, can define position of any element enclosed in a two-sided HTML tag – Style attributes for positioning an object are: position:position_type; left:value; top:value; – where position_type indicates type of positioning used with the object, left indicates location of left edge of the object, and top indicates location of object’s top edge – Left and top values can be defined in absolute coordinates or as a percentage of width of parent object – Default unit is pixels • There are four possible values for position attribute: absolute, relative, fixed, static • An absolute position places object at a defined coordinate in the document, regardless of the object’s initial location or the location of other objects on the page – Figure 1-3 shows object that has been placed at the (30, 100) coordinate on the page, that is, 30 pixels to the right and 100 pixels down from upper-left corner of display window • Absolute position is always determined relative to upper-left corner of parent object – A positive top value places object down from top edge; a negative value places object above top edge – Similarly, a positive left value places object to right of left edge and a negative value places object to left of the left edge • In most cases, the parent object will be browser’s display window, but as shown in Figure 1-4, object can also be positioned within another element on the page – 30 pixels to right and 100 down from upper-left corner of its parent element • A relative position places object a a point relative to its location in the natural flow of the document – Object shown in Figure 1-5 is moved 30 pixels to left and 100 down from where browser would have originally placed the object • Placing an object by using relative positioning can be an exercise in frustration – How will you know default location of object unless you first render page in your browser? – Even then, default location may change from one browser to another as well as under different monitor resolutions – General rule is to use absolute positioning whenever you have objects that are seemingly independent of each other and use relative positioning for objects that appear related – Figure 1-6 shows how relative positioning can be used to achieve interesting visual effect with words within a sentence • Fixed position value places object at a fixed location in window – Object will remain at that fixed position and will not scroll with other elements – Currently major browsers do not support fixed attribute value • The static position value places object in its natural position in the flow of the document as determined by the browser – You are letting the browser handle layout of the object for you – If you use static positioning, you cannot define values for the top and left attributes Layering Objects • Frequently, positioned objects overlap – When this happens you need to specify which object is placed on top – By default, objects that appear later in HTML file are placed on top of earlier elements – To specify your own stacking order, use the zindex style attribute: z-index: value; – where value is a positive or negative integer, or the value “auto” • Objects with a higher z-index value are placed on top of objects with lower zindexes – Figure 1-7 shows effect of z-index • If two objects have same z-index value, object defined later will be shown on top – A z-index value of 0, or “auto” causes object to be placed in its default layer, just as if no zindex value was defined in the first place – Note that the z-index attribute has no effect for objects from within different parent elements – Z-index value can only be used to layer objects within same parent element Controlling Object Visibility • Usually the only reason for hiding an object is that you’re going to “unhide it” later using a script – Can do this by using visibility attribute: visibility: visibility_type; – where visibility_type is visible, inherit, or hidden – The visible makes the object visible on page – Setting visibility attribute to inherit (default) causes object to inherit the visibility property of its parent element – Setting it to hidden causes browser to hide object, but the object still takes up space on page and browser will have to flow other document objects around it – If you want to hide object and have it take up no space, use display attribute with value “none” display: none; – Figure 1-8 shows difference between visibility: hidden and display:none attribute • Only IE allows you to change display attribute after the browser has loaded page Working with Overflow and Clipping • Other attributes to consider when using CSS for layout are the dimensions of your object – Can define width and height of each object by using width/height attributes width: value; height: value; – where value is the width and height values as measured in absolute or relative units, or as a percentage of width or height of parent element – If you do not define height/width values, browser will choose one based on content of the object • If content of object is greater than dimensions you’ve allowed, can control how browser handles extra content overflow: overflow_type; – where overflow_type is visible, hidden, scroll, or auto – Setting it to visible causes browser to increase size to fit the extra content (default) – In case of text, browser will usually only increase object’s height, leaving width at the specified value – Using an overflow value of hidden keeps object at the specified size and hides extra content – If set to scroll, browser keeps object at specified size and adds scroll bars to view extra content – Setting it to auto will display scroll bars only as needed – See Figure 1-9 • Netscape through 4.7 supports only hidden and visible values; IE supports all four • Closely related to overflow attribute is the clip attribute – Allows you to define a rectangular region through which object’s content can be viewed – Anything that lies outside boundary of the rectangle is hidden – Clipping can be used to hide certain portions of the page’s content until needed clip: rect(top, right, bottom, left); – where top, right, bottom, left define coordinates of the rectangle – The coordinates are all relative to top and left edges of the object – A clip value of rect(10, 175, 125, 75) defines a rectangle whose top and bottom edges lie 10 and 125 pixels from top edge of object and whose right and left edges lie 175 and 75 pixels from object’s left edge – See Figure 1-10 • The top, right, bottom, left values can also be set to “auto,” which moves clipping region to top, right, bottom, left edges of the object – A clip value of rect(10, auto, 125, 75) creates a clipping rectangle whose right edge matches the right edge of the object, while the rest of the edges are clipped • Clip attribute can be used only with absolute positioning Creating an Opening Screen for Avalon Books • Ready to create an opening screen for Avalon Books – First task will be to position items on page using various CSS positioning attributes – See Avalon.html • Each object (including words “Avalon” and “Books”) has been placed in a separate <DIV> container tag – Not necessary at this point to put the two words in separate containers, will prove useful later on when you apply animation to page • Also note that each object has a different ID value – The script you’ll write will use these ID values as a reference for each object • To position these objects, will use absolute positioning – By trial and error, you arrive at following coordinates for each object: – Place word “Avalon” at (175,260)--175 pixels from left edge of window and 260 down from top edge – Place word “Books” at (320,260) – Place AB.jpg at (230,40) – Place Fiction.jpg at (5,5) – Place NFiction.jpg at (475,5) • When you use absolute positioning, important to make sure that coordinates work for different monitor resolutions – If you place object at (750,500), will be off the screen for users with 640 x 480 monitors! • Now can modify each object’s style to include this info – See Avalon_13.html • Terry gives you go ahead to add animation to page – Will start by learning how to use style attributes in JavaScript program Session 1.2 • In this session you will learn how DHTML is implemented in Netscape and IE – Will see how to detect the type of browser your user is running and how to create code that works for both – Will learn how to create an API, an external file of customized commands and functions – Will see how to write JavaScript to modify style attributes of your objects The Document Object Model • Writing DHTML code requires an understanding of the document object model, or DOM, which (in theory) makes every element available to the scripting language – In actual practice most browsers do not offer a complete DOM, though versions 4.0/5.0 of IE come close – By accessing the document object model through DHTML, author can write scripts that control almost every element – Document is not longer static, but becomes an app that can be manipulated in response to actions by user or programs written by page developer – Document model can be thought of as a hierarchy of elements, with window object at top of the tree – See Figure 1-13 Element Collections • In JavaScript you translate this hierarchy into reference names, which indicate location of element in DOM hierarchy – Elements can be grouped into element collections, which are arrays of all the elements of a particular type document.collection[i].property; – where collection is name of the collection, – i is either an index number or ID name of the collection object – property is a JavaScript property of the object – First object in collection has an index number of 0 – Can also use ID names of individual elements in place of index number – Syntax of this type of reference name is either: document.collection[“id”] or document.collection.id – where id is the ID name of the element • Figure 1-14 describes different element collections and browser support – Not all element collections are supported by both Netscape and IE • For example, the object reference to first linked item named Home can be expressed using any of the following reference names: document.links[0] document.links[“Home”] document.links.Home Referencing <DIV> Containers • For Avalon Books, will need to create reference names for various <DIV> elements located on opening page – Netscape and IE use different references for <DIV> tags – Netscape refers to objects formatted with <DIV> tag as layers and places them in the layers collection document.layers[‘id”] document.layers.id document.id – where id is ID name given to <DIV> tag – Reason that Netscape uses layers collection is that there is a Netscape-supported tag called <LAYER> tag which is similar to <DIV> tag • In IE, reference syntax for same object can be any of the following: – document.all[“id”] – document.all.id – id • For example, if in your document you have created following tag: <DIV ID=“Greetings”>Welcome to Avalon Books</DIV> • Can refer to this object in Netscape by using any of the following reference names: document.layers.Greetings document.layers[“Greetings”] document.Greetings – while in IE, would probably use: document.all.Greetings document.all[“Greetings”] Greetings Referencing Styles • Syntax rules for changing one of the style attributes of an element also differ between two browsers – In Netscape, syntax for referencing a style is: object.attribute – where object is the reference name of the element and attribute is the name of the style attribute – In IE this same reference would be: object.style.attribute • Not only do the browsers differ in how they reference style attributes, but the names and values of the style attributes can also vary greatly Referencing Nested Objects • Netscape and IE also differ in how they handle nested objects – In Netscape use reference syntax: document.id1.document.id2.document.id3 – where id1 is an object at top of hierarchy, id2 is nested inside id1, id3 is nested inside id2, etc. – If you have lots of nested objects, this reference name can become quite long and complicated • With IE don’t have to worry about various levels of nested objects – As long as you’ve given a unique ID name to the object, can reference it directly, regardless of its location in hierarchy – So to reference id3, would simply use: id3 • For example, to reference Title object: <DIV ID=“Greetings”>Welcome to <SPAN ID=“Title”>Avalon Books</SPAN></DIV> • Netscape uses reference name: – – – – document.Greetings.document.Title because Title object is nested inside Greetings object However, in IE would just use ID name: Title because don’t need to worry about where it is in the object hierarchy • Any HTML code you write needs to take into account all these differences in reference name syntax Implementing the DOM • The two browsers also have some major differences in how they implement the document object model – In Netscape’s version of DOM, can’t make fundamental changes to structure of the page after page has been loaded by browser – Are also limited in how you can change the form and content of the document • Starting with version 4.0, IE’s implementation of DOM is much more flexible and robust – Scripts can dynamically alter property of any object even after page has been loaded – IE DOM even allows author to change tag associations – For example, text formatted with H1 header can be turned into H3 header “on the fly” – IE also provides additional features such as filters that allow you to change appearance of document content by adding drop shadows or other special effects – IE DOM also provides ability to retrieve info from databases – As useful as these features are, must always be implemented with knowledge that all browsers support them and workarounds must be provided • Why do IE and Netscape express DOM so differently? – They developed DHTML separately – Only in recent years that attempts have been made to create a standard DOM with standard object references – In most cases, IE has been adopted as accepted standard Creating a Cross-Browser Web Site • Clearly, the animation you develop for Avalon Books needs to accommodate both browsers – So you need to have some way of determining what type of browser user is running – Then have the browser run correct set of commands for that browser – Two ways of detecting this info: browser detection and object detection Using Browser Detection • With browser detection you determine type of browser and version user is running and then apply a script designed for that version – Assumes that you’ve done homework and have mapped out capabilities of each browser: no easy task! • Browser type can be retrieved from appName property of the navigator object – To store name of browser in a variable named “bName” would use: var bName=navigator.appName; – For Netscape, bName will have value “Netscape” – Value of bName for IE would be “Microsoft Internet Explorer – Easy enough, but detecting version is more complicated • To determine version, use appVersion property of navigator object – Unfortunately, this property includes both version number and additional text that describes features of the version – Usually you won’t need this extra info – Can extract version number from a ppVersion property by using either the parseInt() or parseFloat() methods – ParseInt() method extracts an integer value from a text string, while parseFloat() method extracts a whole number (integer plus decimal) – For example, value of navigator.appVersion property for Netscape 4.7 is: – 4.7[en]C-CCK-MCD NSCPCDD47 (Win98;I) • To extract major version number use: var bVer=parseInt(navigator.appVersion); – and the value of bVer will be 4 – If you want to store the full version number in the bVer variable, use: var bVer=parseFloat(navigator.appVersion); – which stores value 4.7 in bVer – Most of the time you will need only major version number since that is used to signify big changes in the software • These commands also work for all versions of IE, except for IE 5.0, which stores a value of 4.0 in bVer variable! – As long as your page doesn’t contain features unique to IE 5.0, should not be a problem – Will have to write a more complicated script if it is important • Once you know browser type/version, can combine these values in a new variable which you could name “browser” and save them in one compact text string var browser; var bName = navigator.appName; var bVer = parseInt(navigator.appVersion); if (bName == “Netscape” && bVer == 4) browser=“ns4”; if (bName == “Netscape” && bVer == 3) browser=“ns3”; if (bName == “Netscape” && bVer == 2) browser=“ns2”; if (bName == Microsoft Internet Explorer” && bVer == 4) browser=“ie4”; if (bName == Microsoft Internet Explorer” && bVer == 3) browser=“ie3”; if (bName == Microsoft Internet Explorer” && bVer == 2) browser=“ie2”; • For example, if user is running Netscape version 3.0, value of browser variable will be ns3 – If user is running IE 4.0 or 5.0, browser variable will have a value of ie4 Using Object Detection • Many authors recommend bypassing browser detection entirely and rely on object detection – With object detection, you check which types of DOM reference names are supported by the browser (if any) and write code to fit the reference name syntax rather than browser type – Can use fact that Netscape supports document.layers reference name for <DIV> elements, and IE uses document.all to distinguish between the two reference syntaxes – JavaScript code to do this: var isNS = false; var isIE = false; if (document.layers) isNS=true; if (document.all) isIE=true; – The variables isNS and isIE are Boolean variables that indicate whether the object reference syntax follows Netscape or IE convention – If browser recognizes term “document.layers,” will change value of the isNS variable to true, indicating that browser is using Netscape – If it recognizes term “document.all,” will change value of isIE to true for IE approach • This method has advantage that if, at future date, Netscape begins supporting IE reference syntax, authors won’t have to revise code – Other advantage is that it works for browsers such as Opera which also supports DHTML – Only problem with object detection is that you can’t distinguish between versions – If a feature on your site is supported by one version but not another, will still have to test for version number Employing Cross-Browser Strategies • Once you know capabilities of browser, will choose a cross-browser strategy – One, called page branching, creates separate pages for each browser (and could create one for each version) along with an initial page – When user opens initial page, a script determines capability of browser and automatically loads appropriate page – See Figure 1-15 – Initial page itself can be used for browsers that don’t support a scripting language • To automatically load a page into browser based on type of browser detected, use: location=URL; – where URL is the URL of new page to be loaded – Page branching commands should be placed in header section to ensure script is run before initial page is loaded • Following is code for a page that will load AvalonNS.htm page if user’s browser recognizes Netscape reference name – Failing that, will load AvalonIE.htm if it encounters a browser that supports IE – Presumably you will insert into those two pages DHTML code that is appropriate for browser detected – If browser does not support either (or scripting language at all), will finish loading page, displaying H1 header <HTML> <HEAD> <TITLE>Avalon Books</TITLE> <SCRIPT> <!--- Hide from non-JavaScript browsers if (document.layers) { location.href=“AvalonNS.htm”;} else if (document.all) { location.href=“AvalonIE.htm”;} // Stop hiding ---> </SCRIPT> </HEAD> <BODY> <H1 ALIGN=“CENTER”>Welcome to Avalon Books!</H1> </BODY> – Page branching requires you to maintain two versions of same page – In a site with several pages that may have to be updated daily, lots of extra work • Second cross-browser strategy is to use internal branching – Each piece of DHTML code is enclosed in an If…Else statement if (document.layers) { JavaScript commands for Netscape;} else if (document.all) { JavaScript commands for Internet Explorer;} – This would have to repeated every time you run a set of DHTML commands – Internal branching works well for pages without much DHTML code – Those with a lot will quickly become unwieldy and prone to errors • Many developers apply third cross-browser strategy: they create an application programming interface – An application programming interface or API is an external text file that contains custom JavaScript commands and functions – These customized functions are written to resolve any cross-browser differences – When you create a page, you link it to the API and use commands from API file in your page rather than placing code with HTML file – See Figure 1-16 • Will soon learn that Netscape and IE have different commands to hide objects on page – Rather than creating two separate pages or using internal branching every time you want to run a command to hide an object, a custom function called “hideIt(object)” can be added to API – General form of the function would be: function hideIt(object) { if (document.layers) { Commands to hide the object in Netscape;} else if (document.all) { Commands to hide the object in IE;}} – Once you link to the API file, the hideIt() command can then be accessed and run from within the page – If developer wants to hide a particular object when page is loaded, can add following command to <BODY> tag: <BODY onLoad=“hideIt(object)”> – where object is reference to the object that needs to be hidden – Since the API is in an external file, the functions it contains can be used over and over again from different pages in the site – Author does not have to go through process of reentering code, nor does the developer have to create a browser test for each page since this can be accomplished from within the API – Speeds up development time and greatly simplifies structure of the document • If you do create an API file, cannot place it in root directory of your hard drive – Causes IE to report a security error when accessing the file • You discuss the various approaches to creating a cross-browser site – Since Avalon Books contains many pages, agree that creating a custom API is best solution Creating an API for Avalon Books • You and Terry decide that the API should contain following types of commands and functions: – Commands to determine reference syntax supported by browser – Function that resolves syntactical differences in reference names between the two browsers – Function to place an object at a specific coordinate on the page – Function to move an object a certain distance from its current location – Function that returns left value of object’s position – Function that returns top value of object’s position – Function to hide an object – Function to unhide an object • Most JavaScript APIs have file extension .js, so will name this API “Avalon.js” – First commands will detect type of browser being used – See Avalon.js • This set of commands created two variables, isNS and isIE, that determine reference syntax supported by browser – By placing these outside a function command block, both isNS and isIE will be global variables and their values will be accessible from any function in the API or in the page – Will not have to perform browser test more than once • Next need a function that resolves differences in how objects are referenced by the two browsers – For this case, will work only with the style attributes of <DIV> objects – Netscape syntax: document.id.attribute – and IE syntax: id.style.attribute – where id is ID name of <DIV> tag and attribute is the style attribute – If you know object’s ID name, can create reference name for Netscape by inserting text string “document.” before ID name – IE reference name can be created by appending text string “.style” to object’s ID name – Could then apply style attribute to tail end of both reference names • If the ID of the object is stored in the variable “id,” following commands will store correct object reference for both browsers in a variable named obj: if (isNS) obj=“document.”+id; if (isIE) obj=id+”.style”; – Note that obj variable is a text string; not an object on the page – To create an object from this text string, would use eval() function – Eval() funtion will evaluate the text string and create an object based on the reference name – Entire function would look like: function getObject(id) { if (isNS) obj=“document.”+id; if (isIE) obj=id+”.style”; var object=eval(obj); return object; } • What the getObject() function will then do is take the object’s ID name and return a variable that points to the object itself--and it will do this correctly for both browsers – To reference the following element: <DIV ID=“avalon”>Avalon Books</DIV> – would use the command: getObject(“avalon”); • Note that getObject() function works only for objects at top of hierarchy – Would need more complicated function for nested objects, since Netscape refers to them differently from IE – Not a problem here--no nested objects – See Avalon_27.js Positioning Objects with JavaScript • Have entered building blocks for API file by resolving browser question and reference name issue – Now will create JavaScript functions that will position and move object correctly – JavaScript’s positioning properties work much the same as CSS with differences in how Netscape and IE express those properties • First property to consider is positioning type – Netscape: id.position=value; – while in IE: id.style.position=value; – where id is ID name of object to be positioned and value is type of position • Absolute, relative, or static – Rare that you would change position type in a script – In most cases, will set position type in HTML file via style sheet – Also note that you cannot change position type after page is loaded with Netscape, but you can with IE • Both provide several different properties for defining coordinate of the object – See Figure 1-18 • In Netscape, can define object position relative to object’s parent element using left and top properties – Or relative to page using pageX and pageY properties – In IE, location of object is always relative to parent element (usually page) – IE’s top and left properties return a text string indicating both position and the measuring unit – If you need actual values, should use the pixelTop/pixelLeft or posTop/posLeft properties – Only difference is first one returns coordinates in pixels; second in whatever unit is indicated in style sheet • As long as you use pixels as the unit, following are equivalent in Netscape and IE: – In Netscape: document.id.left=100; document.id.top=50; – In IE: id.style.pixelLeft=100; id.style.pixelTop=50; Layering Objects • Can also use JavaScript to control overlapping objects – Uses zIndex property, which works same way as z-index style attribute – For Netscape, the following shows the zIndex values for Avalon and Books objects switched – Will display object listed later in front of upper object var Za=document.Avalon.zIndex; var Zb=document.Books.zIndex; document.Avalon.zIndex=Zb; document.Books.zIndex=Za; – Equivalent code for IE: var Za=Avalon.style.zIndex; var Zb=Books.style.zIndex; Avalon.style.zIndex=Zb; Books.style.zIndex=Za; • In addition to zIndex property, Netscape supports two additional properties, above and below, which indicate object placed above and below current object – If Avalon object is stacked on top of Books object, then document.Avalon.below – refers to Books object, and document.Books.above – refers to Avalon object – No similar property is available with IE Controlling Object Visibility • Both browsers use visibility property to show or hide objects – Unfortunately, while they use same property name, use different property values – Netscape uses values “show” and “hide”: document.id.visibility=“show”; document.id.visibility=“hide”; – while in IE the values are: id.style.visibility=“visible”; id.style.visibility=“hidden”; Working with Overflow and Clipping • Can control height/width of an object by using JavaScript’s height/width properties – Operate same for Netscape and IE • If document content is greater than object’s dimensions, IE supports use of overflow property, which works like overflow style attribute – To change overflow of an object in IE: id.style.overflow=overflow_type; – where overflow_type can be visible, hidden, scroll, or auto – Netscape doesn’t currently support overflow property • Two browsers differ in how they handle the clipping rectangle – See Figure 1-19 for various Netscape properties for controlling clipping region of an object • To change clipping region for an object using Netscape: document.id.clip.top=top; document.id.clip.right=right; document.id.clip.bottom=bottom; document.id.clip.left=left; – where top, right, bottom, and left are coordinates of top, right, bottom, left edges of the clipping rectangle – Can also use clip.width and clip.height properties to set width/height of clipping rectangle without specifying exact coordinates • IE does not support separate properties for each edge – Instead you set value of clip property to a text string: id.style.clip=”rect(10, 150, 100, 20)”; Netscape Layer Methods • In addition to properties, Netscape also supports methods to give you greater control over position and size of objects – See Figure 1-20 Adding Positioning Functions to the API • Ready to add some new functions to API – First function will place an object at a specified (x, y) coordinate – Will use this function later to place objects function placeIt(id, x, y) { var object=getObject(id); if (isNS) { object.moveTo(x, y); } else if (isIE) { object.pixelLeft=x; object.pixelTop=y;}} – The placeIt() function first takes ID name of an object and uses getObject() function to create a variable that refers to the object – If browser is Netscape, object is moved to (x, y) coordiante use MoveTo() method – If browser is IE, object is moved by modifying values of pixelLeft and pixelTop coordinates – See Avalon_33.js • Next function to add shifts an object dx pixels to the right and dy pixels down from current location – Will use this function later to move objects – The function, shiftIt(), is: function shiftIt(id, dx, dy) { var object=getObject(id); if (isNS) { object.moveBy(dx, dy); } else if (isIE) { object.pixelLeft=object.pixelLeft+dx; object.pixelTop=object.pixelTop+dy;}} • Here we use moveBy() method for Netscape, and for IE add value of dx and dy to object’s current coordinates and then store new coordinate values – All coordinates are expressed in pixels by default – See Avalon_33a.js • Next two functions will return values of left/top attributes of object’s position – Will use these two functions later to determine current location of objects function xCoord(id) { var object=getObject(id); if (isNS) xc=object.left; if (isIE) xc=object.pixelLeft; return xc; } function yCoord(id) { var object=getObject(id); if (isNS) yc=object.top; if (isIE) yc=object.pixelTop; return yc; } – The xCoord() function calculates value of left or pixelLeft property for object and stores value in xc variable – That value is then returned by the function – The yCoord() functions does same thing with top or pixelTop property – See Avalon_34.js • Last two functions will be used to hide and unhide an object function hideIt(id) { var object=getObject(id); if (isNS) object.visibility=“hide”; if (isIE) object.visibility=“hidden”; } function showIt(id) { var object=getObject(id); if (isNS) object.visibility=“show”; if (isIE) object.visibility=“visible”; } – See Avalon_35.js • Should study these custom functions, comparing them to syntax that each browser requires – Nice thing about an API file is that once the custom function works, won’t worry about cross-browser differences again • Have completed API – Now will create a link to this file and use the custom functions to animate your page Session 1.3 • In this session you’ll link your page to the API file you created and use the API to control placement and movement of objects in the Avalon Books page – Will learn how to create an animated sequence, and how to control timing of that sequence – Will also learn how to adapt your page for different monitor resolutions Linking to an API File • Have put a lot of work into creating the API file – But the purpose is to remove from the Web page much of the complexity involved with designing a page for two types of browsers – Now that the API is written, can use the placeIt(), shiftIt(), and other functions as if they were native to HTML, without worrying about cross-browser problems • Before you can use commands from API file, have to link the file – Linking to an external file of JavaScript commands (such as Avalon.js file) involves simply placing a SRC property in a <SCRIPT> tag, located in head section of HTML file – Need both an opening and closing <SCRIPT> tag – When browser encounters SRC property, will run any commands from Avalon.js file – Thereafter, if your code calls any of the functions from the API, browser will be able to retrieve the functions and return the results • Because of how Netscape handles JavaScript, need to place link to API file after any <SCRIPT> tags – See Avalon_37.html Designing the Opening Screen • Terry wants to have single word “Avalon” appear near top and dorp vertically – At a certain point, it should stop dropping and word “Books” should appear moving to right from behind word Avalon – After that, the three other images should appear in sequence • To make this animation work, will place words near top of page – With Avalon stacked on top of Books to hide it – Will also place three images in current locations on page, but hidden – While some of these tasks can be performed with CSS style attributes, will use this opportunity to test the API file you created – First should remove some of the old style attributes, replacing them with new ones – See Avalon_38.html • Now will set initial places for the five objects – Coordinates for AB, Fiction, NFiction objects should remain unchanged, but avalon and books objects should be at new coordinates • • • • “avalon”: (175,10) “books”: (175,10) “AB”: (230,40)--as before “Fiction”: (5, 5)--as before • “NFiction”: (475,5)--as before • Because these are the coordinates you want when page is loaded, but not necessarily at other times, will set these coordinates within a function called placeObjects – Will run when page is loaded – PlaceObjects() function appears as follows: function placeObjects() { placeIt(“avalon”, 175, 10); placeIt(“books”, 175, 10); placeIt(“AB”, 230, 40); placeIt(“Fiction”, 5, 5); placeIt(“NFiction”, 475, 5); } • Note that since we’re using placeIt() function from API for this task, – need to specify only ID name of objects (as a text string) – API will handle whole cross-browser issue behind the scenes – See Avalon_40.html • The placeObjects() function should be run when page loads, so add this function to the onLoad event handler for <BODY> tag – See Avalon_40a.html Animating an Object • Moving an object in small increments over specified interval creates illusion of animation – First piece of animation will be word “Avalon” dropping down – Initial position is at coordinate (175,10) – Terry suggests dropping it down to (175,260), which is same coordinate used earlier when placing objects using style attributes • Means that as you move object, will need to retrieve y-coordinate, and stop moving word when value exceeds 260 – When y-coordinate value exceeds 260, will then run a function that moves word “Books” to right from behind word “Avalon” – The moveAvalon() function will appear as: function moveAvalon() { var y=yCoord(“avalon”); if (y <= 260) { shiftIt(“avalon”, 0, 10); shiftIt(“books”, 0, 10); moveAvalon(); } else { // run moveBooks function; }} • Couple important things to notice: – First, function retrieves current y-coordinate from yCoord() function you entered into API – Second, uses shiftIt() function to move both words down 10 pixels at a time – Remember, you want Books to remain behind Avalon as it moves down page – Once it has moved these two words, function calls itself to start moving process over again – Finally, if y-coordinate exceeds 260, will then run moveBooks function--not written yet--to begin moving word “Books” out from behind “Avalon” – For now will mark that spot with a comment • Only other thing missing is some way to control the timing – Browser will process these commands in milliseconds – Word “Avalon” will jump down page in blink of an eye – Need some way to slow down process Creating a Time-Delayed Command • JavaScript does not provide a pause command to temporarily halt execution of program code – Can have JavaScript execute a command after a specified time delay – Uses the setTimeout command: setTimeout(“command”, delay); – where command is a JavaScript command or expression and delay is time in milliseconds – Command must be placed in quotes – To set a 5 millisecond delay before the moveAvalon() function is run: setTimeout(“moveAvalon()”, 5); – Can have several time-delayed commands running simultaneously – If that’s the case, need to have a way of separating one time-delayed command from another – Done by assigning each command an id variable id_variable = setTimeout(“command”, delay); – To assign the moveAvalon() command its own ID, could enter: MAdelay = setTimeout(“moveAvalon()”, 5); Clearing a Time-Delayed Command • Id variable becomes important when your script needs to control behavior of a timedelayed command – If you had several time-delayed commands running, and you wanted to cancel one, would need an ID to indicate which one to cancel – Canceling a time-delayed command is done by using clearTimeout() method: clearTimeout(id_variable); – where id_variable is the ID of the time-delayed command – To cancel MAdelay command before it’s run: clearTimeout(MAdelay); – If you have a single time-delayed command, don’t need the ID; can cancel it with: clearTimeout(); Running Commands at Specified Intervals • In some scripts, will want to repeat same command at specified intervals – May write a script displaying current time which needs to be run every second – To run a command at specified intervals, rather than after a specified time delay, JavaScript provides setInterval() method id_variable=setInterval(“command”, interval); – where id_variable is an ID for the command, command is the JavaScript command that will be run repeatedly, and interval is interval, in milliseconds, between each running – The id variable is not necessary unless you need to cancel the command at some point – If you don’t need an ID, or have one timeinterval command running, use simpler form: setInterval(“command”, interval); • To cancel the command, use clearInterval() method: clearInterval(id_variable); – or, if you have only a single time-interval, with no id variable needed: clearInterval(); • Important point about setTimeout() and setInterval() methods: – After browser processes command, it proceeds to next command in script and does not wait for delay or interval time to pass – If you try to use following structure to run three functions at 50 millisecond intervals: setTimeout(“function1()”, 50); setTimeout(“function2()”, 50); setTimeout(“function3()”, 50); – browser will run all three almost simultaneously after a single 50 millisecond delay – To run them with a separation of about 50 milliseconds between them, need to use three different delay times: setTimeout(“function1()”, 50); setTimeout(“function2()”, 100); setTimeout(“function3()”, 150); Animating the Avalon Books Text • Now that you know how to control the timing, can add this feature to the moveAvalon() function function moveAvalon() { var y=yCoord(“avalon”); if (y <= 260) { shiftIt(“avalon”, 0, 10); shiftIt(“books”, 0, 10); setTimeout(“moveAvalon()”, 5); } else { // run movebooks function; }} • Now the function will move the words down 10 pixels, then wait 5 milliseconds before moving them down another 10 pixels – Generally will experiment with several different movement and time delay values – See Avalon_45.html • Next, script needs to move books out from behind avalon – MoveBooks() function will resemble moveAvalon() except that it moves only books object and it moves it from left to right – By trial and error, determine that you should move “books” from (175,260) to (320,260) – Once text is in location, script should unhide remaining figures function movebooks() { var x=xCoord(“avalon”); if (x <= 320) { shiftIt(“books”, 10, 0); setTimeout(“moveBooks()”, 5); } else { – // display the hidden images; }} • Note that instead of using yCoord() function from API, moveBooks() uses xCoord() to move object in horizontal direction – Also, parameters of shiftIt() function are now switched so books object moves 10 pixels to right every 5 milliseconds – See Avalon_46.html • Last step is to unhide the three images – Do this in a function calling showIt() function from Avalon.js API – Decide to unhide each at half-second intervals function showObjects() { setTimeout(“showIt(‘AB’)”, 500); setTimeout(“showIt(‘Fiction’)”, 1000); setTimeout(“showIt(‘NFiction’)”, 1500); } – Notice you have to insert object names in single quotes since you have to enclose entire command in double quotes – See Avalon_47.html • May have noticed that in creating this animation, each function called the next one in sequence after it was finished – Common technique to ensure effects are presented in proper order Controlling Layout for Different Monitor Resolutions • Terry noticed that you’ve created page based on monitor resolution of 640 x 480 pixels – What happens when users view page under other resolutions? – See Figure 1-31 • At sizes larger than this, images/text move progressively toward upper-left corner of window – Terry would like to see them remain in center, both horizontally and vertically – Rather than create a different page for each resolution, think of the objects as existing on a canvas that is 620 by 300 pixels – Every object would then be offset from left and top edges by a distance equal to size of the border around this imaginary canvas – Example: if dimensions are 760 x 560, border width would be (760 - 620/2 or 70 and border height would be (560 - 300)/2 or 80 pixels • Under Terry’s proposal, if the width is W, then the offset in horizontal direction would be (W - 620)/2 – If height is H, offset in vertical direction will be (H - 300)/2 – By adding offsets to current coordinates of each object, display could be centered for any resolution – However, in order to use this calculation, need to be able to determine width (W) and height (H) of each user’s display window Calculating the Size of the Display Window • Netscape and IE use different techniques to calculate width/height of window – In Netscape, these values are properties of window object, where: window.innerWidth window.innerHeight – store the width/height within the browser, excluding any toolbars, menus, status bars – To include those elements in the calculation, use the properties: window.outerWidth window.outerHeight – IE does not support these properties – Instead, have to measure width/height of the body of the document document.body.clientWidth document.body.clientHeight • Because of how IE processes this property, it can only be used after entire HTML file has been processed – If you try to evaluate these commands within header section, error message will result • To calculate W and H offsets, will add following commands to placeObjects() function: if (isNS) { W=(window.innerWidth-620)/2; H=(window.innerHeight-300)/2; } if (isIE) [ W=(document.body.clientWidth-620)/2; H=(document.body.clientHeight-300)/2; } – Don’t have to recalculate values of isNS and isIE variables since this has already been done in the API – See Avalon_51.html • Now have to add W and H values to each coordinate in placeObjects() function so that objects are placed in appropriate locations for all windows – See Avalon_52.html • Also need to change value of the coordinates used to determine where to stop moving Avalon and Books text – See Avalon_53.html Determining Screen Properties • For more general info about user’s monitor settings, can use the screen object – See Figure 1-37 Using Path Animation • Animation you did is an example of linear animation because animation takes place over a straight line, going from one point to the next (either down or to the right) – Another type is path animation, in which each coordinate in the path is entered into an array and the animation moves from point to point – Path can be any shape, as shown in Figure 1-38 • Have completed your work on Avalon Books opening page