NCCOOS Trac Projects: Top | Web | Platforms | Processing | Viz | Sprints | Sandbox | (Wind)

root/Chameleon/trunk/Chameleon/js/cwc_button.js

Revision 13 (checked in by jcleary, 17 years ago)

Latest Chameleon code checkout from previous repository

Line 
1 /**
2  * @project     CWC2
3  * @revision    $Id: cwc_button.js,v 1.8 2005/05/16 11:26:27 bartvde Exp $
4  * @purpose     Java Script for managed, multi-state HTML buttons
5  * @author      DM Solutions Group (pspencer@dmsolutions.ca)
6  * @copyright
7  * <b>Copyright (c) 2003, DM Solutions Group Inc.</b>
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included
16  * in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24  * DEALINGS IN THE SOFTWARE.
25  */
26  
27 /**
28  * the purpose of this code is to conveniently manage fancy javascript buttons
29  * for the application.  It provides three types of buttons managed via a
30  * button manager.  The global button manager is created when this file is
31  * included.  The name of the global button manager is goCWCButtonManager.
32  *
33  * Buttons are created as javascript objects and added to the button manager.
34  * The CWCButton constructor is described in comments just above the CWCButton
35  * function, but here is a quick example of how to construct a button object:
36  *
37  * button = new CWCButton( "MyButton", "MyGroup" , MyFunction, null
38  *                         "images/tool_zoombounds_off.gif",
39  *                         "images/tool_zoombounds_over.gif",
40  *                         "images/tool_zoombounds_on.gif" );
41  *
42  * goCWCButtonManager.AddButton( button );
43  *
44  * This builds a new button object with its user interface controlled by the
45  * HTML image object named "MyButton" and adds it to the manager.
46  *
47  * Note that it is important for cross-browser compatibility to provide both
48  * a name and an id in your images. Here is an example image to work with this
49  * button:
50  *
51  * <img src="images/tool_zoombounds_off.gif" name="MyButton" id="MyButton">
52  *
53  * The button will belong to a group called MyGroup.  When a button belongs to
54  * a group, it is automatically converted from a normal button to a radio
55  * button (the types of buttons are described below).
56  *
57  * MyFunction is the name of a function to call when the button is activated.
58  * Note that it is just the name of the function, and does not have quotes
59  * around it.  This passes a function object to the button object so that when
60  * the button is clicked, MyFunction is called.  When MyFunction is called, the
61  * button object that called MyFunction is passed as the one and only argument
62  * to the function.  A sample MyFunction would be:
63  *
64  * function MyFunction( oButton, aMyValues )
65  * {
66  *   alert( oButton.szImageName );
67  * }
68  *
69  * The fourth argument is some value to pass to MyFuction.  This can null, a
70  * single value, or an array of values and is completely dependent on how this
71  * button is intended to be used.
72  *
73  * The fourth parameter is the "normal" state image, the image to be displayed
74  * when the button is not activated in any way.  This is a URL to the image and
75  * can be relative or absolute depending on your requirements.
76  *
77  * The remaining images are optional and will only be used if provided.  If
78  * additional images are provided, then when the button would change to a
79  * particular state (see below), then the button image will be replaced with
80  * the associated image.
81  *
82  * Buttons can be one of three types:
83  *
84  * CWCBUTTONTYPE_CLICK - this is a button that is in the SELECTED state while
85  * the mouse button is down, and in NORMAL state when it is up.  The function
86  * associated with this type of button is called once when the mouse is
87  * released.
88  *
89  * CWCBUTTONTYPE_TOGGLE - this is a sticky button that stays down after it is
90  * clicked, and pops up when it is clicked again.  The function associated with
91  * toggle buttons is called when the button is activated and disactivated.
92  *
93  * CWCBUTTON_RADIO - this is a sticky button that operates like a toggle button
94  * except that it is part of a group of buttons of which only one can be active
95  * at a time.  Clicking a radio button deselects all other buttons in the same
96  * group.  Unlike toggle buttons, the function associated with radio buttons is
97  * called only when the button is pressed.  Buttons that are deactivated when
98  * another button in the same group is activated do not call their function.
99  * Providing a group name in the constructor of a button automatically makes
100  * the button a RADIO button. 
101  *
102  * Buttons have a variety of states.
103  *
104  * CWCBUTTONSTATE_NORMAL - the button is not activated
105  * CWCBUTTONSTATE_HOVER - the mouse is over the button but it is not activated
106  * CWCBUTTONSTATE_SELECTED - the button is selected (pressed in)
107  * CWCBUTTONSTATE_DISABLED - the button is unresponsive
108  */
109  
110 //button states
111 var CWCBUTTONSTATE_NORMAL = 0;
112 var CWCBUTTONSTATE_HOVER = 1;
113 var CWCBUTTONSTATE_SELECTED = 2;
114 var CWCBUTTONSTATE_DISABLED = 3;
115
116 //button types
117 var CWCBUTTONTYPE_CLICK = 0;
118 var CWCBUTTONTYPE_TOGGLE = 1;
119 var CWCBUTTONTYPE_RADIO = 2;
120
121 //capture events in nav browsers
122 if (CWCIsNav4 || CWCIsNav6)
123 {
124     document.captureEvents(Event.MOUSEDOWN);
125     document.captureEvents(Event.MOUSEUP);
126     document.captureEvents(Event.MOUSEMOVE);
127 }
128
129 var goCWCButtonManager = new CWCButtonManager();
130
131 /**
132  * CWCButtonManager manages all the buttons and groups of buttons.
133  * A single global instance of the CWCButtonManager should be created
134  * to manage all the buttons in an application.  Adding buttons to the
135  * button manager allows them to be organized into groups and managed
136  * in an intelligent (radio button) manner
137  */
138 function CWCButtonManager()
139 {
140     this.aButtons = new Array();
141     this.aGroups = new Array();
142     this.oForm = null;
143    
144     this.currentButton = null;
145    
146     this.AddButton = CWCButtonManager_AddButton;
147     this.GetButton = CWCButtonManager_GetButton;
148 }
149
150 /**
151  * Return a CWCButton instance given a button name (which is the
152  * image name, actually)
153  * @param szImage the name of the button to retrieve
154  * @return the CWCButton instance or null if not found
155  */
156 function CWCButtonManager_GetButton( szImageName )
157 {
158     var oImage = CWCDHTML_GetImage( szImageName );
159    
160     if (oImage != null && oImage.cwcButton != null)
161         return oImage.cwcButton;
162     else
163         return null;
164 }
165
166 /**
167  * Add a button to the button manager
168  * @param oButton - the CWCButton instance to add
169  */
170 function CWCButtonManager_AddButton( oButton )
171 {
172     oButton.oManager = this;
173     oButton.index = this.aButtons.length;
174     this.aButtons[this.aButtons.length] = oButton;
175     if (oButton.szGroupName != null && oButton.szGroupName != "null" && oButton.szGroupName != "")
176     {
177         var i, theGroup = null;
178         for (i=0; i < this.aGroups.length; i++)
179         {
180             if (this.aGroups[i].szGroupName == oButton.szGroupName)
181             {
182                 theGroup = this.aGroups[i];
183                 break;
184             }
185         }
186         if (theGroup == null)
187         {
188             theGroup = new CWCButtonGroup( oButton.szGroupName );
189             this.aGroups[this.aGroups.length] = theGroup;
190         }
191         theGroup.AddButton( oButton );
192     }
193 }
194
195 /**
196  * a group of CWCButton objects managed as a mutually exclusive set.
197  * Activating one button in the group deactivates the rest.
198  * @param szGroupName - the name of this group
199  */
200 function CWCButtonGroup( szGroupName )
201 {
202     this.szGroupName = szGroupName;
203     this.aButtons = new Array();
204    
205     //function prototypes
206     this.AddButton = CWCButtonGroup_AddButton;
207     this.ActivateButton = CWCButtonGroup_ActivateButton;
208 }
209
210 /**
211  * Add a CWCButton object to this group
212  * @param oButton the button to add to this group
213  */
214 function CWCButtonGroup_AddButton( oButton )
215 {
216     oButton.oGroup = this;
217     oButton.type = CWCBUTTONTYPE_RADIO;
218     this.aButtons[this.aButtons.length] = oButton;
219 }
220
221 /**
222  * Activate one button in the group, deactivating all others.
223  * @param oButton the button to activate
224  */
225 function CWCButtonGroup_ActivateButton( oButton )
226 {
227     var i;
228     for( i=0; i < this.aButtons.length; i++ )
229     {
230         if (this.aButtons[i].szImageName != oButton.szImageName)
231         {
232             this.aButtons[i].SetState( CWCBUTTONSTATE_NORMAL );
233             this.aButtons[i].bActive = false;
234             if (oButton.oForm != null)
235             {
236                 oButton.oForm['BUTTON_TOOLSET_' + this.szGroupName].value = oButton.szImageName;
237             }   
238         }
239     }
240 }
241
242 /*
243  * construct a new button object
244  * @param szImageName - the name in the image tag in the page, used
245  *                      to grab the image object
246  * @param nType - the button type (see definitions at start of file).
247  * @param szGroup - the name of the group to put this button in, or null if no group.  Note
248  *                  that an empty string is considered a group.
249  * @param onClick - function to call when the button is clicked.  For toggle buttons, this will
250  *                  be called when the button is activated and deactivated.  For radio buttons,
251  *                  this will be called only when the button is activated (not when it is deactivated
252  *                  by the button group as part of activating another button).
253  * @param xValues - an unstructured value that is passed, as is, to the onClick
254  *                  as the second value.
255  * @param szNormalURL - the URL to use when the button is in normal state
256  * @param szHoverURL - (opt) the URL to use when the button is in normal state
257  * @param szSelectedlURL - (opt) the URL to use when the button is in normal state
258  * @param szDisabledURL - (opt) the URL to use when the button is in normal state
259  */
260 function CWCButton( szImageName, nType, szGroup, onClick, xValues, szNormalURL /* szHoverURL, szSelectedURL, szDisabledURL */ )
261 {
262     this.szGroupName = szGroup;
263     this.oGroup = null;
264    
265     //hidden feature to enable the button to control the visibility of an associated div
266     this.szDivName = '';
267    
268     this.aImages = new Array( szNormalURL, null, null, null );
269    
270     //the index at which option arguments appear.
271     var optIdx = 6;
272     if (arguments.length > optIdx)
273     {
274         this.aImages[CWCBUTTONSTATE_HOVER] = arguments[optIdx ++];
275     }
276     if (arguments.length > optIdx)
277     {
278         this.aImages[CWCBUTTONSTATE_SELECTED] = arguments[optIdx ++];   
279     }
280     if (arguments.length > optIdx)
281     {
282         this.aImages[CWCBUTTONSTATE_DISABLED] = arguments[optIdx ++];
283     }
284
285     this.szImageName = szImageName;
286     this.oImage = CWCDHTML_GetImage( szImageName );
287    
288     if (this.oImage != null)
289     {
290         this.oImage.onmouseover = CWCButton_OnMouseOver;
291         this.oImage.onmouseout = CWCButton_OnMouseOut;
292         //this.oImage.onclick = CWCButton_OnMouseClick;
293        
294         //IE specific handlers
295         this.oImage.onmousedown = null; //CWCButton_OnMouseDown;
296         this.oImage.onmouseup = null; //CWCButton_OnMouseUp;
297         //in IE, this cancels the drag action
298         this.oImage.ondragstart = CWCButton_OnDragStart;
299         this.oImage.cwcButton = this;
300     }
301     else
302     {
303         //alert( "image object for " + this.szImageName + " not found?" );
304     }
305    
306     this.onClick = onClick;
307     this.xValues = xValues;
308    
309     this.currentState = CWCBUTTONSTATE_NORMAL;
310     this.bActive = false; //set to true when selected.
311    
312     //used to track old event handlers so they can be restored.
313     this.oldMouseDown = null;
314     this.oldMouseUp = null;
315     this.oldMouseMove = null;
316    
317     this.oManager = null;
318     this.index = 0;
319     this.type = nType;
320     this.bMouseDown = false;
321    
322     //function prototypes
323     this.GetState = CWCButton_GetState;
324     this.IsDisabled = CWCButton_IsDisabled;
325     this.IsSelected = CWCButton_IsSelected;
326     this.SetState = CWCButton_SetState;
327 }
328
329 /**
330  * return the state of this button
331  */
332 function CWCButton_GetState()
333 {
334     return this.currentState;
335 }
336
337 /**
338  * return true if the button is disabled
339  */
340 function CWCButton_IsDisabled()
341 {
342     return this.currentState == CWCBUTTONSTATE_DISABLED;
343 }
344
345 /**
346  * return true if the button is selected
347  */
348 function CWCButton_IsSelected()
349 {
350     return this.currentState == CWCBUTTONSTATE_SELECTED;
351 }
352
353 /**
354  * set the state of this button
355  * @param nState the state to set
356  */
357 function CWCButton_SetState( nState )
358 {
359     if (!this.oImage) return false;
360     var previousState = this.currentState;
361     if (nState >=0 && nState <= CWCBUTTONSTATE_DISABLED)
362     {
363         //HOVER is a transient state, ignore it so toggle buttons work
364         this.currentState = nState;
365         if (this.aImages[nState] != null)
366         {
367             this.oImage.src = this.aImages[nState];
368         }
369         else
370         {
371             this.oImage.src = this.aImages[0];
372         }
373     }
374     if (this.szDivName != '' && !this.bMouseDown )
375     {
376         if (this.currentState == CWCBUTTONSTATE_SELECTED)
377         {
378             //alert( 'showing div ' + this.szDivName );
379             CWCDHTML_ShowLayer( this.szDivName );
380             //if (this.oGroup != null)
381             //{
382             //   this.oGroup.ActivateButton( this );
383             //}
384         }
385         else if (this.currentState == CWCBUTTONSTATE_NORMAL )
386         {
387             //alert( 'hiding div ' + this.szDivName );
388             CWCDHTML_HideLayer( this.szDivName );
389         }
390     }
391    
392 }
393
394 //global functions for handling events
395
396 function CWCButton_OnMouseOver( e )
397 {
398     var target;
399     if (CWCIsIE)
400     {
401         e = event;
402         target = event.srcElement;
403         e.cancelBubble = true;
404         e.returnValue = false;
405     }
406     else
407     {
408         target = e.target
409     }
410    
411     //catch the occasional error in IE
412     if (target.cwcButton == null)
413     {
414         return;
415     }
416      
417     if (!target.cwcButton.IsDisabled())
418     {
419         if (target.cwcButton.bMouseDown)
420         {
421             target.cwcButton.SetState( CWCBUTTONSTATE_SELECTED );
422         }
423         else if (!target.cwcButton.IsSelected())
424         {
425             target.cwcButton.SetState( CWCBUTTONSTATE_HOVER );
426         }
427     }
428    
429     if (!CWCIsIE)
430     {
431         //capture events if we are using netscape so we can grab mouse clicks
432         target.cwcButton.oldMouseDown = document.onmousedown;
433         document.onmousedown = CWCButton_OnMouseDown;
434         target.cwcButton.oldMouseUp = document.onmouseup;
435         document.onmouseup = CWCButton_OnMouseUp;
436     }
437     else
438     {
439         target.cwcButton.oImage.onmousedown = CWCButton_OnMouseDown;
440         target.cwcButton.oImage.onmouseup = CWCButton_OnMouseUp;
441     }
442    
443     target.cwcButton.oldMouseMove = document.onmousemove;
444     document.onmousemove = null;
445     return false;
446 }
447
448 /*
449  * handle mouse out events by setting the image state to the appropriate
450  * state depending on the type of the button.  If the image was not set
451  * active then we reset it and don't generate a click when the mouse button
452  * is released.
453  */
454 function CWCButton_OnMouseOut( e )
455 {
456     var target;
457     if (CWCIsIE)
458     {
459         e = event;
460         target = event.srcElement;
461         e.cancelBubble = true;
462         e.returnValue = false;
463     }
464     else
465     {
466         target = e.target
467     }       
468
469     //catch the occasional error in IE
470     if (target.cwcButton == null)
471     {
472         return;
473     }
474    
475     if (!target.cwcButton.IsDisabled())
476     {
477         if( !target.cwcButton.bActive || target.cwcButton.type == CWCBUTTONTYPE_CLICK)
478         {
479             target.cwcButton.SetState( CWCBUTTONSTATE_NORMAL );
480         }
481     }
482    
483     target.cwcButton.bMouseDown = false;
484    
485     //remove event handlers if necessary
486     if (!CWCIsIE)
487     {
488         document.onmouseup = target.cwcButton.oldMouseUp;
489         target.cwcButton.oldMouseUp = null;
490         document.onmousedown = target.cwcButton.oldMouseDown;
491         target.cwcButton.oldMouseDown = null;
492     }
493     else
494     {
495         target.cwcButton.oImage.onmousedown = null;
496         target.cwcButton.oImage.onmouseup = null;
497     }
498    
499     document.onmousemove = target.cwcButton.oldMouseMove;
500     target.cwcButton.oldMouseMove = null;
501
502    
503     return false;
504 }
505
506 /*
507  * handle the onclick event on the image, note that in NN4 we are
508  * faking this by calling this function from the onmouseup handler.
509  */
510 function CWCButton_OnMouseClick( e )
511 {
512     var target;
513     if (CWCIsIE)
514     {
515         e = event;
516         target = event.srcElement;
517         e.cancelBubble = true;
518         e.returnValue = false;
519     }
520     else
521     {
522         target = e.target
523     }
524    
525     if (target.cwcButton.onClick != null)
526     {
527         target.cwcButton.onClick( target.cwcButton, target.cwcButton.xValues );
528     }
529     return false;
530 }
531
532 /*
533  * handle mouse down events by setting the image state to the appropriate
534  * state depending on the type of the button.
535  */
536 function CWCButton_OnMouseDown( e )
537 {
538     var target;
539     if (CWCIsIE)
540     {
541         e = event;
542         target = event.srcElement;
543         e.cancelBubble = true;
544         e.returnValue = false;
545     }
546     else
547     {
548         target = e.target
549     }
550
551     //catch the occasional error in IE
552     if (target.cwcButton == null)
553     {
554         return;
555     }
556        
557     if (!target.cwcButton.IsDisabled())
558     {
559         target.cwcButton.bMouseDown = true;
560         target.cwcButton.SetState( CWCBUTTONSTATE_SELECTED );
561     }
562     return false;
563 }
564
565 /*
566  * handle mouse up events by setting the image state to the appropriate
567  * state depending on the type of the button.  Note that if this is a
568  * Netscape Navigator 4 browser, then we are faking an onclick event
569  * because it doesn't support onclick on images.
570  */
571 function CWCButton_OnMouseUp( e )
572 {
573     var target;
574     var bNeedClick = false;
575     if (CWCIsIE)
576     {
577         e = event;
578         target = event.srcElement;
579         e.cancelBubble = true;
580         e.returnValue = false;
581     }
582     else
583     {
584         target = e.target
585         if (e.cancelable)
586             e.cancelBubble = true;
587     }
588    
589     //catch the occasional error in IE
590     if (target.cwcButton == null)
591     {
592         return;
593     }
594        
595     if (!target.cwcButton.bMouseDown)
596     {
597         return;
598     }       
599    
600     target.cwcButton.bMouseDown = false;
601        
602     if (!target.cwcButton.IsDisabled())
603     {
604         if (target.cwcButton.IsSelected() ) //&& CWCIsNav4)
605         {
606             bNeedClick = true;
607         }
608         if (target.cwcButton.type == CWCBUTTONTYPE_CLICK)
609         {
610             target.cwcButton.SetState( CWCBUTTONSTATE_SELECTED );
611         }
612         if (target.cwcButton.type == CWCBUTTONTYPE_RADIO)
613         {
614             target.cwcButton.SetState( CWCBUTTONSTATE_SELECTED );
615             target.cwcButton.bActive = true;
616             if (target.cwcButton.oGroup != null)
617             {
618                 target.cwcButton.oGroup.ActivateButton( target.cwcButton );
619             }
620         }
621         if (target.cwcButton.type == CWCBUTTONTYPE_TOGGLE)
622         {
623             if (target.cwcButton.bActive)
624             {
625                 target.cwcButton.SetState( CWCBUTTONSTATE_NORMAL );           
626                 target.cwcButton.bActive = false;
627             }
628             else
629             {
630                 target.cwcButton.SetState( CWCBUTTONSTATE_SELECTED );
631                 target.cwcButton.bActive = true;
632             }
633         }
634     }
635    
636     if (bNeedClick)
637     {
638         CWCButton_OnMouseClick( e );
639     }
640     return false;
641 }
642
643 /**
644  *
645  */
646 function CWCButton_OnDragStart( e )
647 {
648     //alert( "ondragstart" );
649     var target;
650     if (CWCIsIE)
651     {
652         e = event;
653         target = event.srcElement;
654         e.cancelBubble = true;
655         e.returnValue = false;
656     }
657     else
658     {
659         target = e.target;
660         if (e.cancelable)
661             e.cancelBubble = true;
662     }
663 }
Note: See TracBrowser for help on using the browser.