Select Lists - The Select Object

Note: As with the new Scroll Object, the Select Object now uses layer-based events. It can now be positioned relatively and you don't have to pass mouse coordinates to the object - it is all done automatically. However, the big disadvantage of using this technique is that it is no longer compatible with document-base mouse event code such as the Drag Object. If you use the drag object along with the select object, the select will not work at all.

The Select Object, like the other form like objects, can be used to replace the need for using standard HTML select lists. You can make the select list look exactly the way you want and works similarly to the way a Java applet works. You set a few parameters, add the items in the select list, and it'll generate all the code necessary for it to operate.

Initializing Select Objects

Here a screen capture of what the default select list looks like under Netscape/Win95 (text sizes change slightly depending on OS, browser, and fonts installed):

In order to create a list like this you have to supply the image that will be used as the "click-able" part. The rest of the select list is generated with CSS. You can choose all the colors that are used - text color, background color, highlight colors etc, the font-family and size, and even how offset the text is (so that you can center the text). The image that I've used for the "click-able part" (the select bar as I call it) is this:


select.gif (100x16)

The height and width of that image determine the overall dimensions of the select list. These values along with the location of the image must be passed into the object when initializing your select list.

This is the general format for creating a new Select object:


objectName = new Select(name,nestref,x,y,image,width,height)

where:

Example:


myselect = new Select("myselect",null,50,100,"select.gif",100,16)

Notes:

Adding Items (Options) To The Select List

To add options to the list you use the addOptions() method. The list can support any number of options, you just define the text that will show in the list followed by its associated value in a consecutive list:


objectName.addOptions(

text,value,

text,value,

text,value,

text,value)

Examples:


myselect.addOptions(

'One',1,

'Two',2,

'Three',3,

'Four',4)



myselect.addOptions(

'Select a Page:','',

'Home','../index.html',

'Clipping','../clipping/clipping.html',

'Nesting Layers','../nesting/nesting.html',

'DynLayer','../dynlayer/dynlayer.html')

Though it is not necessary to define your own dimensions, fonts, and colors for your select list, I have built into the Select object many methods and properties by which you can customize your select lists. The following sections will explain how to use them.

Setting the Dimensions of the Options

Option Sizes

The width and height of the options in the list can be set by the setDimensions() method:


objectName.setDimensions(optionWidth,optionHeight)

Example:


myselect.setDimensions(83,13)

Important: You must call the setDimensions() method before you add the options to the Select list. When you add options to the select list it adds them according to the height of the options. The height of the options must be finilized before any of the options are added.

The setDimensions() method is optional, if you do not define it, it will default to the entire width, and a height of 13 pixels.

Text and List Locations

You can define where the text is located within its confines. This may be necessary when you change the font and size of the text to make the text appear centered. I've included these 5 properties to the object by which you do this:

You can also set the horizontal position of the entire list with respect to the select image by setting the listX property. This is useful when you want to make some kind of weird looking select list.

You can set any one of optionX, optionY, textX, textY, or listX directly:


objectName.optionX = 3

objectName.optionY = -1

objectName.textX = 2

objectName.textY = 0

objectName.listX = 12

Or you can again use the setDimensions() method to define them along with the width and the height:


objectName.setDimensions(optionWidth,optionHeight,optionX,optionY,textX,textY,listX)

Example:


myselect.setDimensions(83,13,3,-1,2,0,12)

If you don't specify any of these dimensions the object will default to (this.w,13,3,0,4,1,0)

Setting the Styles

Font and Size of Text:

Use the setFont() method to change your fonts:


objectName.setFont(fontName,size,other)

where:

Examples:


myselect.setFont('Arial',8)

myselect.setFont('Arial',8,'text-spacing:5pt; line-height:11pt;')

Colors

You set the colors of the list with the setColors() method:


objectName.setColors(bgOff,bgOn,optionOff,optionOn,text,border)

where

Setting Up The HTML and JavaScript

After you've initialized and set all the options for your select object, you also have to set up the HTML and JavaScript in order to draw the select list and allow it to operate.

Immediately following your last setup method you must then call the build() method.


myselect = new Select('myselect',50,50,'select.gif',100,16)

myselect.setDimensions(83,13)

myselect.addOptions(

'One',1,

'Two',2,

'Three',3,

'Four',4)

myselect.build()

The build() method finalizes your settings and puts together the CSS and HTML for the select list. The build() method creates a property called div which is a String that contains all the DIV tags the select list requires. This string must be document.written somewhere within your BODY.


<BODY onLoad="init()">



<SCRIPT LANGUAGE="JavaScript">

document.writeln(myselect.div)

</SCRIPT>



</BODY>

At some point after the div property is written, you then must activate Select object by calling the activate() method:


objectName.activate()

This can be done immediately after the document.write() or in the default init() function, doesn't matter:

Here's a complete page showing how to properly set up a select list:


<HTML>

<HEAD>

<TITLE>The Dynamic Duo - Custom Forms [Select Lists] Demo 1</TITLE>

<!-- Source code for Select list is in select.js -->

<SCRIPT LANGUAGE="JavaScript" SRC="dynlayer.js"></SCRIPT>

<SCRIPT LANGUAGE="JavaScript" SRC="select.js"></SCRIPT>

<SCRIPT LANGUAGE="JavaScript">

<!--



ns4 = (document.layers)? true:false

ie4 = (document.all)? true:false



myselect = new Select('myselect',null,150,50,'select.gif',100,16)

myselect.setDimensions(83,13)

myselect.addOptions(

'One',1,

'Two',2,

'Three',3,

'Four',4)

myselect.build()



function init() {

	myselect.activate()

}



//-->

</SCRIPT>

</HEAD>



<BODY onLoad="init()">



<SCRIPT LANGUAGE="JavaScript">

document.write(myselect.div)

</SCRIPT>



</BODY>

</HTML>

View selectlists1.html for this select list example. View Source Code

But we're not quite finished yet. There is a few more things to mention...

Retrieving the Value of Select Objects

Remember the whole point of having a select list is to be able to use it for some purpose, for a submitting a form to a CGI program, or making a redirection.

To retrieve the value of the selected option, just capture the objects value property.


objectName.value

Before the user has selected any of the options, the value is a string of "undefined". If you'd like the value to default to something else simply overwrite the value before you build() the select list.

View selectlists2.html to check the value of the select list. View Source Code

The onChange Event Handler

I've also built my own onChange event handler into the Select object - it works the same way as the onChange handler works with the default form select lists. After the user selects an option, you can define what will happen. You can call another function, or execute any statement you'd like. This allows you to make any sort of "add-on" function you'd like. You could make it automatically submit a form, or redirect the user to another page.

Because of it's usefullness, I've already included a redirection add-on function and I will use it to demonstrate how the onChange handler can be used.

First you make some function that is going to execute when the onChange handler is called:


function SelectRedirect(url) {

	if (url!='') document.location.href = url

	return false

}

Note: I recommend always returning false in handler functions as that function does

Now assign that function to the onChange handler you specify the function similarly to the way you would with normal HTML:


myselect.onChange = "SelectRedirect(myselect.value)"

View selectlists3.html for a redirection select list example. View Source Code

Final Notes

Dynamic Layer:

The select object initializes itself as a Dynamic Layer Object as well. So any of the methods of the Dynamic Layer Object can be used on the entire select list - such as hide(), show(), slideBy() etc. But I made the DynLayer as a property of the select object. To access the DynLayer you use the lyr property:


objectName.lyr.hide()

objectName.lyr.show()

objectName.lyr.moveTo(80,120)

etc.

Visibility, Z-Index:

Both these CSS properties can be applied to the select list by using the visibility and zIndex select object properties. Here's an example:


objectName.visiblity = "hidden"

objectName.zIndex = 4

Drop-Down Animation:

By default the select list will slide open for an animated effect. You can change the speed and increment values by changing the speed and slideInc parameters:


objectName.speed = 20      // 20 ms per step

objectName.slideInc = 10   // moves 10 pixels per step

If you set slideInc to null the list will just pop open - no animation at all.

Select Object Source Code


// Select Object

// Copyright 1998 Dan Steinman

// Available at the Dynamic Duo (http://www.dansteinman.com/dynduo/)

// May 23, 1998.  Last Updated October 17, 1998.

// In order to use this code you must keep this disclaimer



ns4 = (document.layers)? true:false

ie4 = (document.all)? true:false



function Select(name,nestref,x,y,image,width,height) {

	this.name = name

	this.nestref = nestref

	this.nest = (nestref)? nestref+'.document.' : ""

	this.x = x

	this.y = y

	this.w = width

	this.h = height

	this.image = image

	this.slideInc = 7

	this.speed = 20

	this.listH = 1

	this.optionText = new Array()

	this.optionValues = new Array()

	this.hl = -1

	this.value = null

	this.onChange = null

	this.visibility = null

	this.zIndex = null

	this.div = ''

	this.css = ''

	this.setDimensions = SelectSetDimensions

	this.setDimensions(this.w,13,3,0,4,1,0)

	this.setFont = SelectSetFont

	this.setFont('Arial',8)

	this.setColors = SelectSetColors

	this.setColors('white','black','black','white','black','black')

	this.addOptions = SelectAddOptions

	this.toggle = SelectToggle

	this.build = SelectBuild

	this.activate = SelectActivate

}

function SelectSetDimensions(optionW,optionH,optionX,optionY,textX,textY,listX) {

	this.optionW = optionW

	this.optionH = optionH

	if (arguments.length==7) {

		this.optionX = optionX

		this.optionY = optionY

		this.textX = textX

		this.textY = textY

		this.listX = listX

	}

}

function SelectSetFont(fontName,size,other) {

	this.font = fontName

	this.size = size

	this.other = (other)? other : ""

}

function SelectSetColors(bgOff,bgOn,optionOff,optionOn,text,border) {

	this.bgOff = bgOff

	this.bgOn = bgOn

	this.optionOff = optionOff

	this.optionOn = optionOn

	this.textColor = text

	this.brColor = border

}

function SelectAddOptions() {

	for (var i=0;i<arguments.length/2;i++) {

		this.optionText[i] = arguments[2*i]

		this.optionValues[i] = arguments[2*i+1]

		this.listH += this.optionH

	}

}

function SelectBuild() {

	this.css = '<STYLE TYPE="text/css">\n'+

	css(this.name+'Select',this.x,this.y,this.w,this.h,null,this.visibility,this.zIndex)+

	css(this.name+'Bar',0,0)+

	css(this.name+'BarC',0,0,this.w,this.h)+

	css(this.name+'Text',this.textX,this.textY,this.w)+

	css(this.name+'List',this.listX,-this.listH+this.h,this.optionW,this.listH,this.brColor)+

	css(this.name+'ListI',1,0,this.optionW-2,this.listH-1)

	for (var i=0;i<this.optionText.length;i++) {

		this.css += css(this.name+'Option'+i,0,i*this.optionH,this.optionW-2,this.optionH,this.bgOff)+

		css(this.name+'Option'+i+'T',this.optionX,this.optionY)+

		css(this.name+'Option'+i+'C',0,i*this.optionH,this.optionW-2,this.optionH)

	}

	this.css += '.'+this.name+'TextStyle {font-family:"'+this.font+'"; font-size:'+this.size+'pt; color:'+this.textColor+'; '+this.other+'}\n'+

	'.'+this.name+'off {font-family:"'+this.font+'"; font-size:'+this.size+'pt; color:'+this.optionOff+'; '+this.other+'}\n'+

	'.'+this.name+'on {font-family:"'+this.font+'"; font-size:'+this.size+'pt; color:'+this.optionOn+'; '+this.other+'}\n'+

	'</STYLE>'

	this.div = '<DIV ID="'+this.name+'Select">\n'+

	'<DIV ID="'+this.name+'List">\n'+

	'<DIV ID="'+this.name+'ListI">\n'

	for (var i=0;i<this.optionText.length;i++) {

		this.div += '<DIV ID="'+this.name+'Option'+i+'"><DIV ID="'+this.name+'Option'+i+'T"><SPAN CLASS="'+this.name+'off">'+this.optionText[i]+'</SPAN></DIV></DIV>\n'+

		'<DIV ID="'+this.name+'Option'+i+'C"></DIV>\n'

	}

	this.div += '</DIV>\n'+

	'</DIV>\n'+

	'<DIV ID="'+this.name+'Bar">\n'+

	'<IMG NAME="'+this.name+'Img" SRC="'+this.image+'" WIDTH='+this.w+' HEIGHT='+this.h+'>\n'+

	'<DIV ID="'+this.name+'Text"><SPAN CLASS="'+this.name+'TextStyle">'+this.optionText[0]+'</SPAN></DIV>\n'+

	'</DIV>\n'+

	'<DIV ID="'+this.name+'BarC"></DIV>\n'+

	'</DIV>\n'

	document.write(this.css)

}

function SelectActivate() {

	this.lyr = new DynLayer(this.name+'Select',((this.nestref)?this.nestref:null))

	this.lyr.clipInit()

	this.listlyr = new DynLayer(this.name+'List',this.nest+this.name+'Select')

	this.listlyr.slideInit()

	this.barlyr = new DynLayer(this.name+'BarC',this.nest+this.name+'Select')

	if (ns4) this.barlyr.event.captureEvents(Event.MOUSEDOWN)

	this.barlyr.event.onmousedown = new Function('SelectToggle('+this.name+')')

	for (var i=0;i<this.optionText.length;i++) {

		this.optionlyr = new Array()

		this.optionlyr[i] = new DynLayer(this.name+'Option'+i+'C',this.nest+this.name+'Select.document.'+this.name+'List.document.'+this.name+'ListI')

		if (ns4) this.optionlyr[i].event.captureEvents(Event.MOUSEDOWN | Event.MOUSEOVER)

		this.optionlyr[i].event.onmousedown = new Function('SelectChange('+this.name+','+i+')')

		this.optionlyr[i].event.onmouseover = new Function('SelectOver('+this.name+','+i+')')

		this.optionlyr[i].event.onmouseout = new Function('SelectOut('+this.name+','+i+')')

	}

}

function SelectOver(o,i) {

	setBGColor(o.name+'Option'+i,o.nest+o.name+'Select.document.'+o.name+'List.document.'+o.name+'ListI',o.bgOn)

	layerWrite(o.name+'Option'+i+'T',o.nest+o.name+'Select.document.'+o.name+'List.document.'+o.name+'ListI.document.'+o.name+'Option'+i,'<SPAN CLASS="'+o.name+'on">'+o.optionText[i]+'</SPAN>')

	return false

}

function SelectOut(o,i) {

	setBGColor(o.name+'Option'+i,o.nest+o.name+'Select.document.'+o.name+'List.document.'+o.name+'ListI',o.bgOff)

	layerWrite(o.name+'Option'+i+'T',o.nest+o.name+'Select.document.'+o.name+'List.document.'+o.name+'ListI.document.'+o.name+'Option'+i,'<SPAN CLASS="'+o.name+'off">'+o.optionText[i]+'</SPAN>')

	return false

}

function SelectChange(o,i) {

	layerWrite(o.name+'Text',o.nest+o.name+'Select.document.'+o.name+'Bar','<SPAN CLASS="'+o.name+'TextStyle">'+o.optionText[i]+'</SPAN>')

	o.value = o.optionValues[i]

	eval(o.onChange)

	o.toggle(o)

}

function SelectToggle(o) {

	if (!o.opened) {

		o.lyr.clipTo(null,null,o.listH+o.h,null)

		if (o.slideInc==null) {

			o.listlyr.moveTo(null,o.h)

			o.opened = true

		}

		else o.listlyr.slideTo(null,o.h,o.slideInc,o.speed,o.name+'.opened = true')

	}

	else {

		if (o.slideInc==null) {

			o.listlyr.moveTo(null,-o.listH+o.h)

			o.lyr.clipTo(null,null,o.h,null)

			o.opened = false

		}

		else o.listlyr.slideTo(null,-o.listH+o.h,o.slideInc,o.speed,o.name+'.opened = false; '+o.name+'.lyr.clipTo(0,'+o.w+','+o.h+',0);')

	}

	return false

}

function SelectRedirect(url) {

	if (url!='') document.location.href = url

	return false

}



// Required functions are css(), setBGColor() and layerWrite()



// Changes the background color of a layer

function setBGColor(id,nestref,color) {

	if (ns4) {

		var lyr = (nestref)? eval('document.'+nestref+'.document.'+id):document.layers[id]

		lyr.document.bgColor = color

	}

	else if (ie4) document.all[id].style.backgroundColor = color

}



// Re-writes the contents of a layer

function layerWrite(id,nestref,text) {

	if (ns4) {

		var lyr = (nestref)? eval('document.'+nestref+'.document.'+id):document.layers[id]

		lyr.document.open()

		lyr.document.write(text)

		lyr.document.close()

	}

	else if (ie4) document.all[id].innerHTML = text

}



// Generic CSS function to return CSS syntax with the given parameters

function css(id,left,top,width,height,color,vis,z) {

	var str = (left!=null && top!=null)? '#'+id+' {position:absolute; left:'+left+'; top:'+top+'; ' : '#'+id+' {position:relative; '

	if (width!=null) str += 'width:'+width+'; '

	if (height!=null) str += 'height:'+height+'; clip:rect(0,'+width+','+height+',0); '

	if (color!=null) str += 'background-color:'+color+'; layer-background-color:'+color+'; '

	if (vis!=null) str += 'visibility: '+vis+'; '

	if (z!=null) str += 'z-index: '+z+'; '

	str += '}\n'

	return str

}

Custom Forms:
Buttons
Radio Buttons
Checkboxes
Select Lists

Home Next Lesson: Scroll Object
copyright 1998 Dan Steinman