Select Lists - The Select Object

Note: I will be updating this code soon, there are a few problems under Unix and it uses deprecated code (eg. layerWrite() instead of DynLayer Write method), so use at your own risk! It does work though.

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