Move parseFontFaceDescriptor to CSSPropertyParser.cpp
[chromium-blink-merge.git] / third_party / WebKit / LayoutTests / svg / carto.net / resources / selectionList.js
blobec9fb749f831f27a2c6f1d665722ec2374989041
1 /*
2 Scripts to create interactive selectionLists/Dropdown boxes in SVG using ECMA script
3 Copyright (C) <2006>  <Andreas Neumann>
4 Version 1.4, 2006-07-18
5 neumann@karto.baug.ethz.ch
6 http://www.carto.net/
7 http://www.carto.net/neumann/
9 Credits:
10 * Initial code was taken from Michel Hirtzler --> pilat.free.fr (thanks!)
11 * Thanks also to many people of svgdevelopers@yahoogroups.com
12 * Suggestions by Bruce Rindahl
14 ----
16 Documentation: http://www.carto.net/papers/svg/gui/selectionlist/
18 ----
20 current version: 1.4
22 version history:
23 0.99 (2004-10-26)
24 initial version
26 1.0 (2005-09-15)
27 allow undefined values in callback function for selectionlists that need not react on changes (suggestion by Bruce Rindahl)
28 allow selectionlist to be placed in a transformed group
29 now also works in MozillaSVG (due to changes in mapApp.js)
31 1.1 (2005-09-28)
32 removed "string" option in functionToCall (not important any more). function and object should be good enough
33 timer object from http://www.codingforums.com/showthread.php?s=&threadid=10531 is now used; attention: you need to link this script as well!
34 due to the new timer object we can now also mouse down and scroll more than one entry until we mouseup again, previously one had to click for forwarding each individual element
36 1.2 (2005-10-24)
37 removed style attributes and replaced them with individual XML attributes
38 initial tests on Opera 9 TP1, it seems to work except for the scrolling - due to a mouse-move event bug
40 1.2.1 (2005-02-07)
41 upgraded the documentation and fixed documentation errors
43 1.2.2 (2006-02-16)
44 added option to open selectionList to the top of the original box, this is useful for layouts where the selectionList is at the bottom of a page
45 added option to always put the selectionList on the top of it's parent group after activation in order to force the geometry to be on the top of all other geometry within the same group
46 improved background rectangle: these are now two rectangles: one on the bottom for the fill, one on the top for stroking
47 tested with Opera 9 TP2, works now fine, except keyboard input
49 1.2.3 (2006-02-21)
50 removed dependency on replaceSpecialChars (in file helper_functions.js) as this is not really needed in a true utf8 environment.
51 improved key event handling. People can now enter more than one key (within one second for each consequent key) and the list will jump to entries that match the keys; key events now also work in opera 9+ - however they sometimes collide with keyboard shortcuts.
53 1.3 (2006-03-11)
54 changed parameters of constructor (styling system): now an array of literals containing presentation attributes. Not hardcoded in selectionList.js anymore. Added check for number of arguments.
56 1.4 (2006-07-18)
57 added additional constructor parameter "parentNode", changed groupId to id, added methods .resize(width) and .moveTo(x,y)
58 improved scrolling (now also possible outside of the scrollbar, once the mouse is down)
60 -------
63 This ECMA script library is free software; you can redistribute it and/or
64 modify it under the terms of the GNU Lesser General Public
65 License as published by the Free Software Foundation; either
66 version 2.1 of the License, or (at your option) any later version.
68 This library is distributed in the hope that it will be useful,
69 but WITHOUT ANY WARRANTY; without even the implied warranty of
70 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
71 Lesser General Public License for more details.
73 You should have received a copy of the GNU Lesser General Public
74 License along with this library (lesser_gpl.txt); if not, write to the Free Software
75 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
77 ----
79 original document site: http://www.carto.net/papers/svg/gui/selectionlist/
80 Please contact the author in case you want to use code or ideas commercially.
81 If you use this code, please include this copyright header, the included full
82 LGPL 2.1 text and read the terms provided in the LGPL 2.1 license
83 (http://www.gnu.org/copyleft/lesser.txt)
85 -------------------------------
87 If you wish, you can modify parameters (such as "look and feel") in the function "selectionList" (constructor).
88 You can adapt colors, fonts, cellpaddings, etc.
90 -------------------------------
92 Please report bugs and send improvements to neumann@karto.baug.ethz.ch
93 If you use this control, please link to the original (http://www.carto.net/papers/svg/gui/selectionlist/)
94 somewhere in the source-code-comment or the "about" of your project and give credits, thanks!
98 function selectionList(id,parentNode,elementsArray,width,xOffset,yOffset,cellHeight,textPadding,heightNrElements,textStyles,boxStyles,scrollbarStyles,smallrectStyles,highlightStyles,triangleStyles,preSelect,openAbove,putOnTopOfParent,functionToCall) {
99     var nrArguments = 19;
100     var createSelbox= true;
101     if (arguments.length == nrArguments) {
102         //get constructor variables
103         this.id = id; //the id or node reference of the group where the
104         this.parentNode = parentNode; //can be of type string (id) or node reference (svg or g node)
105         this.elementsArray = elementsArray; //the array containing the text elements of the selectionList
106         this.width = width; //width of the selectionList in viewBox coordinates
107         this.xOffset = xOffset; //upper left corner (xOffset) of selection list in viewBox coordinates
108         this.yOffset = yOffset; //upper left corner (yOffset) of selection list in viewBox coordinates
109         this.cellHeight = cellHeight; //cellHeight in viewBox coordinates
110         this.heightNrElements = heightNrElements; //nr of elements for unfolded selectionList (number, integer)
111         this.textStyles = textStyles; //array of literals containing presentation attributes for text
112         if (!this.textStyles["font-size"]) {
113             this.textStyles["font-size"] = "11";
114         }
115         this.boxStyles = boxStyles; //array of literals containing presentation attributes for the sel box
116         if (!this.boxStyles["fill"]) {
117             this.boxStyles["fill"] = "white"; //this fill value is also used for boxes under indiv. text elements (unselected status)
118         }    
119         if (!this.boxStyles["stroke"]) {
120             this.boxStyles["stroke"] = "dimgray";
121         }    
122         if (!this.boxStyles["stroke-width"]) {
123             this.boxStyles["stroke-width"] = 1;
124         }
125         this.scrollbarStyles = scrollbarStyles; //array of literals containing presentation attributes for the scrollbar
126         this.smallrectStyles = smallrectStyles; //array of literals containing presentation attributes for the small rectangle next to selectbox
127         this.highlightStyles = highlightStyles; //array of literals containing presentation attributes for the highlighted rectangles
128         this.triangleStyles = triangleStyles; //array of literals containing presentation attributes for the triangle in the selectionList, also applies to fill of scroller
129         this.preSelect = preSelect;
130         this.openAbove = openAbove;
131         this.putOnTopOfParent = putOnTopOfParent;
132         this.functionToCall = functionToCall;
134         //calculate other values
135         this.triangleFourth = Math.round(this.cellHeight / 4); //this is only used internally
136         this.textPadding = textPadding; //this is relative to the left of the cell
137         this.textPaddingVertical = this.cellHeight - (this.cellHeight - this.textStyles["font-size"]) * 0.7; //this is relative to the top of the cell
138         this.scrollerMinHeight = this.cellHeight * 0.5; //minimal height of the scroller rect
139         
140         //references
141         this.scrollBar = undefined; //later a reference to the scrollbar rectangle
142     
143         //status variables
144         this.activeSelection = this.preSelect; //holds currently selected index value
145         this.listOpen = false; //status folded=false, open=true - previously been sLselectionVisible
146         this.curLowerIndex = this.preSelect; //this value is adapted if the user moves scrollbar
147         this.scrollStep = 0; //y-value to go for one element
148         this.scrollerHeight = 0; //height of dragable scroller bar
149         this.scrollActive = false; //determines if scrolling per up/down button is active
150         this.panY = false; //stores the y value of event
151         this.scrollCumulus = 0; //if value is less then a scrollstep we need to accumulate scroll values
152         this.scrollDir = ""; //later holds "up" and "down"
153         this.exists = true; //true means it exists, gets value false if method "removeSelectionList" is called
154         this.pressedKeys = ""; //stores key events (pressed char values)
155         this.keyTimer = undefined; //timer for resetting character strings after a given time period
156     }
157     else {
158         createSelbox = false;
159         alert("Error ("+id+"): wrong nr of arguments! You have to pass over "+nrArguments+" parameters.");
160     }
161     if (createSelbox) {
162         //timer stuff
163         this.timer = new Timer(this); //a Timer instance for calling the functionToCall
164         this.timerMs = 200; //a constant of this object that is used in conjunction with the timer - functionToCall is called after 200 ms
165         //createSelectionList
166         this.createSelectionList();
167     }
168     else {
169         alert("Could not create selectionlist with id '"+id+"' due to errors in the constructor parameters");    
170     }
173 selectionList.prototype.createSelectionList = function() {
174         var result = this.testParent();
175         if (result) {
176             //initial Rect, visible at the beginning
177             var node = document.createElementNS(svgNS,"rect");
178             node.setAttributeNS(null,"x",this.xOffset);
179             node.setAttributeNS(null,"y",this.yOffset);
180             node.setAttributeNS(null,"width",this.width);
181             node.setAttributeNS(null,"height",this.cellHeight);
182             for (var attrib in this.boxStyles) {
183                 node.setAttributeNS(null,attrib,this.boxStyles[attrib]);
184             }        
185             node.setAttributeNS(null,"id","selRect_"+this.id);
186             node.addEventListener("click", this, false);
187             this.parentGroup.appendChild(node);
188             //initial text
189             this.selectedText = document.createElementNS(svgNS,"text");
190             this.selectedText.setAttributeNS(null,"x",this.xOffset + this.textPadding);
191             this.selectedText.setAttributeNS(null,"y",this.yOffset + this.textPaddingVertical);
192             var value = "";
193             for (var attrib in this.textStyles) {
194                 value = this.textStyles[attrib];
195                 if (attrib == "font-size") {
196                     value += "px";
197                 }
198                 this.selectedText.setAttributeNS(null,attrib,value);
199             }        
200             this.selectedText.setAttributeNS(null,"pointer-events","none");
201             var selectionText = document.createTextNode(this.elementsArray[this.activeSelection]);
202             this.selectedText.appendChild(selectionText);
203             this.parentGroup.appendChild(this.selectedText);
204             //small Rectangle to the right, onclick unfolds the selectionList
205             var node = document.createElementNS(svgNS,"rect");
206             node.setAttributeNS(null,"x",this.xOffset + this.width - this.cellHeight);
207             node.setAttributeNS(null,"y",this.yOffset);
208             node.setAttributeNS(null,"width",this.cellHeight);
209             node.setAttributeNS(null,"height",this.cellHeight);
210             for (var attrib in this.smallrectStyles) {
211                 node.setAttributeNS(null,attrib,this.smallrectStyles[attrib]);
212             }        
213             node.setAttributeNS(null,"id","selPulldown_"+this.id);
214             node.addEventListener("click", this, false);
215             this.parentGroup.appendChild(node);
216             //triangle
217             var node=document.createElementNS(svgNS,"path");
218             var myTrianglePath = "M"+(this.xOffset + this.width - 3 * this.triangleFourth)+" "+(this.yOffset + this.triangleFourth)+" L"+(this.xOffset + this.width - this.triangleFourth)+" "+(this.yOffset + this.triangleFourth)+" L"+(this.xOffset + this.width - 2 * this.triangleFourth)+" "+(this.yOffset + 3 * this.triangleFourth)+" Z";
219             node.setAttributeNS(null,"d",myTrianglePath);
220             for (var attrib in this.triangleStyles) {
221                 node.setAttributeNS(null,attrib,this.triangleStyles[attrib]);
222             }        
223             node.setAttributeNS(null,"id","selTriangle_"+this.id);
224             node.setAttributeNS(null,"pointer-events","none");
225             this.parentGroup.appendChild(node);
226             //rectangle below unfolded selectBox, at begin invisible
227             this.rectBelowBox = document.createElementNS(svgNS,"rect");
228             this.rectBelowBox.setAttributeNS(null,"x",this.xOffset);
229             this.rectBelowBox.setAttributeNS(null,"y",this.yOffset + this.cellHeight);
230             this.rectBelowBox.setAttributeNS(null,"width",this.width - this.cellHeight);
231             this.rectBelowBox.setAttributeNS(null,"height",0);
232             this.rectBelowBox.setAttributeNS(null,"fill",this.boxStyles["fill"]);
233             this.rectBelowBox.setAttributeNS(null,"display","none");
234             this.parentGroup.appendChild(this.rectBelowBox);
235             //rectangle below unfolded selectBox, at begin invisible
236             this.rectAboveBox = document.createElementNS(svgNS,"rect");
237             this.rectAboveBox.setAttributeNS(null,"x",this.xOffset);
238             this.rectAboveBox.setAttributeNS(null,"y",this.yOffset + this.cellHeight);
239             this.rectAboveBox.setAttributeNS(null,"width",this.width - this.cellHeight);
240             this.rectAboveBox.setAttributeNS(null,"height",0);
241             this.rectAboveBox.setAttributeNS(null,"fill","none");
242             this.rectAboveBox.setAttributeNS(null,"stroke",this.boxStyles["stroke"]);
243             this.rectAboveBox.setAttributeNS(null,"stroke-width",this.boxStyles["stroke-width"]);
244             this.rectAboveBox.setAttributeNS(null,"display","none");
245             this.parentGroup.appendChild(this.rectAboveBox);
246         }
247         else {
248             alert("could not create or reference 'parentNode' of selectionList with id '"+this.id+"'");
249         }            
252 //test if parent group exists or create a new group at the end of the file
253 selectionList.prototype.testParent = function() {
254     //test if of type object
255     var nodeValid = false;
256     if (typeof(this.parentNode) == "object") {
257         if (this.parentNode.nodeName == "svg" || this.parentNode.nodeName == "g") {
258             this.parentGroup = this.parentNode;
259             nodeValid = true;
260         }
261     }
262     else if (typeof(this.parentNode) == "string") { 
263         //first test if Windows group exists
264         if (!document.getElementById(this.parentNode)) {
265             this.parentGroup = document.createElementNS(svgNS,"g");
266             this.parentGroup.setAttributeNS(null,"id",this.parentNode);
267             document.documentElement.appendChild(this.parentGroup);
268             nodeValid = true;
269            }
270            else {
271                this.parentGroup = document.getElementById(this.parentNode);
272                nodeValid = true;
273            }
274        }
275        return nodeValid;
278 selectionList.prototype.handleEvent = function(evt) {
279     var el = evt.currentTarget;
280     var callerId = el.getAttributeNS(null,"id");
281     var myRegExp = new RegExp(this.id);
282     if (evt.type == "click") {
283         if (myRegExp.test(callerId)) {
284             if (callerId.match(/\bselPulldown|\bselRect/)) {
285                 if (this.listOpen == false) {
286                     if (this.putOnTopOfParent) {
287                         //put list on top of the parent group (bottom in the DOM tree)
288                         this.parentGroup.parentNode.appendChild(this.parentGroup);
289                     }
290                     this.unfoldList();
291                     this.listOpen = true;
292                 }
293                 else {
294                     this.foldList();
295                     this.listOpen = false;
296                     evt.stopPropagation();
297                 }
298             }
299             if (callerId.match(/\bselHighlightSelection_/)) {
300                 this.selectAndClose(evt);
301                 evt.stopPropagation();
302             }
303         }
304         else {
305             //case that the event comes from the documentRoot element
306             //but not from the selectionList itself
307             if (!myRegExp.test(evt.target.getAttributeNS(null,"id"))) {
308                 this.foldList();
309                 this.listOpen = false;
310             }
311         }
312     }
313     if (evt.type == "mouseover") {
314         if (myRegExp.test(callerId)) {
315             if (callerId.match(/\bselHighlightSelection_/)) {
316                 for (var attrib in this.highlightStyles) {
317                     el.setAttributeNS(null,attrib,this.highlightStyles[attrib]);
318                 }        
319             }
320         }
321     }
322     if (evt.type == "mouseout") {
323         if (myRegExp.test(callerId)) {
324             if (callerId.match(/\bselHighlightSelection_/) ){
325                 el.setAttributeNS(null,"fill",this.boxStyles["fill"]);
326             }
327             if (callerId.match(/\bselScrollbarRect_/)) {
328                     this.scrollBarMove(evt);
329             }
330         }
331     }
332     if (evt.type == "mousedown") {
333         if (myRegExp.test(callerId)) {
334             if (callerId.match(/\bselScrollUpperRect_|\bselScrollLowerRect/)) {
335                 this.scrollDir = "down";
336                 this.scrollActive = true;
337                 if (callerId.match(/UpperRect/)) {
338                     this.scrollDir = "up";
339                 }
340                 this.scroll(this.scrollDir,1,true); //1 is one element to scroll, true says that we should move scrollbar
341                 this.timer.setTimeout("scrollPerButton",400)
342             }
343             if (callerId.match(/\bselScrollbarRect_/)) {
344                 //add events to document.documentElement
345                 document.documentElement.addEventListener("mousemove",this,false);
346                 document.documentElement.addEventListener("mouseup",this,false);
347                 this.scrollBarMove(evt);
348             }
349         }
350     }
351     if (evt.type == "mouseup") {
352         if (myRegExp.test(callerId)) {
353             if (callerId.match(/\bselScrollUpperRect_|\bselScrollLowerRect/)) {
354                 this.scrollActive = false;
355             }
356         }
357         if (el.nodeName == "svg" || el.nodeName == "svg:svg") {
358             document.documentElement.removeEventListener("mousemove",this,false);
359             document.documentElement.removeEventListener("mouseup",this,false);            
360             this.scrollBarMove(evt);
361         }
362     }
363     if (evt.type == "mousemove") {
364         if (el.nodeName == "svg" || el.nodeName == "svg:svg") {
365             this.scrollBarMove(evt);
366         }
367     }    //add keypress event
368     if (evt.type == "keypress") {
369         if (evt.charCode) {
370             var character = String.fromCharCode(evt.charCode).toLowerCase();
371         }
372         else {
373             //case opera and others
374             var character = String.fromCharCode(evt.keyCode).toLowerCase();
375             if (evt.keyCode == 0 || evt.keyCode == 16 || evt.keyCode == 17 || evt.keyCode == 18) {
376                 //shift key
377                 character = "";
378             }
379         }
381         this.pressedKeys += character;
383         if (character.length > 0) {
384                 if (this.keyTimer) {
385                     this.timer.clearTimeout(this.keyTimer);
386                 }
387                 this.keyTimer = this.timer.setTimeout("resetPressedKeys",1000);
388             this.scrollToKey();
389         }
390     }
393 selectionList.prototype.resetPressedKeys = function() {
394      this.keyTimer = undefined;
395      this.pressedKeys = "";
398 //this function is called when selectionList is unfolded
399 selectionList.prototype.unfoldList = function() {
400     //create temporary group to hold temp geometry
401     if (!this.dynamicTextGroup) {
402         this.dynamicTextGroup = document.createElementNS(svgNS,"g");
403         this.parentGroup.insertBefore(this.dynamicTextGroup,this.rectAboveBox);
404     }
405     var nrSelectionsOrig = this.elementsArray.length;
406     if (this.heightNrElements < nrSelectionsOrig) {
407         nrSelections = this.heightNrElements;
408     }
409     else {
410         nrSelections = nrSelectionsOrig;
411     }
412     var selectionHeight = this.cellHeight * nrSelections;
413     //build textElements from array
414     //hold currentSelection Index to unroll list at new offset
415     if ((nrSelectionsOrig - this.activeSelection) >= nrSelections) {
416         this.curLowerIndex = this.activeSelection;
417     }
418     else {
419         this.curLowerIndex = nrSelectionsOrig - nrSelections;
420     }
421     //following is a temporary YOffset that serves to distinquish between selectionLists that open above or below
422     var YOffset = this.yOffset + this.cellHeight;
423     if (this.openAbove) {
424         YOffset = this.yOffset - this.heightNrElements * this.cellHeight;
425     }
426     //adopt background rectangle
427     this.rectBelowBox.setAttributeNS(null,"height",selectionHeight);
428     this.rectBelowBox.setAttributeNS(null,"display","inherit");
429     this.rectBelowBox.setAttributeNS(null,"y",YOffset);
430     this.rectAboveBox.setAttributeNS(null,"height",selectionHeight);
431     this.rectAboveBox.setAttributeNS(null,"display","inherit");
432     this.rectAboveBox.setAttributeNS(null,"y",YOffset);
434     for (var i=0;i<nrSelections;i++) {
435         //add rectangles to capture events
436         var node = document.createElementNS(svgNS,"rect");
437         node.setAttributeNS(null,"x",this.xOffset + this.textPadding / 2);
438         node.setAttributeNS(null,"y",YOffset + this.cellHeight * i);
439         node.setAttributeNS(null,"width",this.width - this.cellHeight - this.textPadding);
440         node.setAttributeNS(null,"height",this.cellHeight);
441         node.setAttributeNS(null,"fill",this.boxStyles["fill"]);
442         node.setAttributeNS(null,"id","selHighlightSelection_" + this.id + "_" + (i + this.curLowerIndex));
443         //add event-handler
444         node.addEventListener("mouseover", this, false);
445         node.addEventListener("mouseout", this, false);
446         node.addEventListener("click", this, false);
447         node.addEventListener("keypress", this, false);
448         this.dynamicTextGroup.appendChild(node);
449         //add text-elements
450         var node = document.createElementNS(svgNS,"text");
451         node.setAttributeNS(null,"id","selTexts_" + this.id + "_" + (i + this.curLowerIndex));
452         node.setAttributeNS(null,"x",this.xOffset + this.textPadding);
453         node.setAttributeNS(null,"y",YOffset + this.textPaddingVertical + this.cellHeight * i);
454         node.setAttributeNS(null,"pointer-events","none");
455         var value = "";
456         for (var attrib in this.textStyles) {
457             value = this.textStyles[attrib];
458             if (attrib == "font-size") {
459                 value += "px";
460             }
461             node.setAttributeNS(null,attrib,value);
462         }        
463         var selectionText = document.createTextNode(this.elementsArray[this.curLowerIndex + i]);
464         node.appendChild(selectionText);
465         this.dynamicTextGroup.appendChild(node);
466     }
468     //create Scrollbar
469     if (this.heightNrElements < nrSelectionsOrig) {
470         //calculate scrollstep
471         this.scrollerHeight = (this.heightNrElements / nrSelectionsOrig) * (selectionHeight - 2 * this.cellHeight);
472         if (this.scrollerHeight < this.scrollerMinHeight) {
473             this.scrollerHeight = this.scrollerMinHeight;
474         }
475         this.scrollStep = (selectionHeight - 2 * this.cellHeight - this.scrollerHeight) / (nrSelectionsOrig - this.heightNrElements);
476         //scrollbar
477         this.scrollBar = document.createElementNS(svgNS,"rect");
478         this.scrollBar.setAttributeNS(null,"x",this.xOffset + this.width - this.cellHeight);
479         this.scrollBar.setAttributeNS(null,"y",YOffset + this.cellHeight);
480         this.scrollBar.setAttributeNS(null,"width",this.cellHeight);
481         this.scrollBar.setAttributeNS(null,"height",selectionHeight - this.cellHeight * 2);
482         for (var attrib in this.scrollbarStyles) {
483             this.scrollBar.setAttributeNS(null,attrib,this.scrollbarStyles[attrib]);
484         }        
485         this.scrollBar.setAttributeNS(null,"id","selScrollbarRect_"+this.id);
486         this.scrollBar.addEventListener("mousedown", this, false);
487         //node.addEventListener("mouseup", this, false);
488         //node.addEventListener("mousemove", this, false);
489         //node.addEventListener("mouseout", this, false);
490         this.dynamicTextGroup.appendChild(this.scrollBar);
491         //upper rectangle
492         var node = document.createElementNS(svgNS,"rect");
493         node.setAttributeNS(null,"x",this.xOffset + this.width - this.cellHeight);
494         node.setAttributeNS(null,"y",YOffset);
495         node.setAttributeNS(null,"width",this.cellHeight);
496         node.setAttributeNS(null,"height",this.cellHeight);
497         for (var attrib in this.smallrectStyles) {
498             node.setAttributeNS(null,attrib,this.smallrectStyles[attrib]);
499         }        
500         node.setAttributeNS(null,"id","selScrollUpperRect_"+this.id);
501         node.addEventListener("mousedown", this, false);
502         node.addEventListener("mouseup", this, false);
503         this.dynamicTextGroup.appendChild(node);
504         //upper triangle
505         var node = document.createElementNS(svgNS,"path");
506         var myPath = "M"+(this.xOffset + this.width - 3 * this.triangleFourth)+" "+(YOffset + 3 * this.triangleFourth)+" L"+(this.xOffset + this.width - this.triangleFourth)+" "+(YOffset + 3 * this.triangleFourth)+" L"+(this.xOffset + this.width - 2 * this.triangleFourth)+" "+(YOffset + this.triangleFourth)+" Z";
507         node.setAttributeNS(null,"d",myPath);
508         for (var attrib in this.triangleStyles) {
509             node.setAttributeNS(null,attrib,this.triangleStyles[attrib]);
510         }        
511         node.setAttributeNS(null,"pointer-events","none");
512         this.dynamicTextGroup.appendChild(node);
513         //lower rectangle
514         var node = document.createElementNS(svgNS,"rect");
515         node.setAttributeNS(null,"x",this.xOffset + this.width - this.cellHeight);
516         node.setAttributeNS(null,"y",YOffset - this.cellHeight + selectionHeight);
517         node.setAttributeNS(null,"width",this.cellHeight);
518         node.setAttributeNS(null,"height",this.cellHeight);
519         for (var attrib in this.smallrectStyles) {
520             node.setAttributeNS(null,attrib,this.smallrectStyles[attrib]);
521         }        
522         node.setAttributeNS(null,"id","selScrollLowerRect_" + this.id);
523         node.addEventListener("mousedown", this, false);
524         node.addEventListener("mouseup", this, false);
525         this.dynamicTextGroup.appendChild(node);
526         //lower triangle
527         var node = document.createElementNS(svgNS,"path");
528         var myPath = "M"+(this.xOffset + this.width - 3 * this.triangleFourth)+" "+(YOffset - this.cellHeight + selectionHeight + this.triangleFourth)+" L"+(this.xOffset + this.width - this.triangleFourth)+" "+(YOffset - this.cellHeight + selectionHeight + this.triangleFourth)+" L"+(this.xOffset + this.width - 2 * this.triangleFourth)+" "+(YOffset - this.cellHeight + selectionHeight + 3 * this.triangleFourth)+" Z";
529         node.setAttributeNS(null,"d",myPath);
530         for (var attrib in this.triangleStyles) {
531             node.setAttributeNS(null,attrib,this.triangleStyles[attrib]);
532         }        
533         node.setAttributeNS(null,"pointer-events","none");
534         this.dynamicTextGroup.appendChild(node);
535         //scrollerRect
536         var node = document.createElementNS(svgNS,"rect");
537         node.setAttributeNS(null,"x",this.xOffset + this.width - this.cellHeight);
538         node.setAttributeNS(null,"y",YOffset + this.cellHeight + this.scrollStep * this.curLowerIndex);
539         node.setAttributeNS(null,"width",this.cellHeight);
540         node.setAttributeNS(null,"height",this.scrollerHeight);
541         for (var attrib in this.smallrectStyles) {
542             node.setAttributeNS(null,attrib,this.smallrectStyles[attrib]);
543         }        
544         node.setAttributeNS(null,"pointer-events","none");
545         node.setAttributeNS(null,"id","selScroller_"+this.id);
546         this.dynamicTextGroup.appendChild(node);
547     }
548     //add event handler to root element to close selectionList if one clicks outside
549     document.documentElement.addEventListener("click",this,false);
550     document.documentElement.addEventListener("keypress",this,false);
553 //this function folds/hides the selectionList again
554 selectionList.prototype.foldList = function() {
555     this.parentGroup.removeChild(this.dynamicTextGroup);
556     this.dynamicTextGroup = null;
557     this.rectBelowBox.setAttributeNS(null,"display","none");
558     this.rectAboveBox.setAttributeNS(null,"display","none");
559     document.documentElement.removeEventListener("click",this,false);
560     document.documentElement.removeEventListener("keypress",this,false);
561     this.scrollBar = undefined;
564 selectionList.prototype.selectAndClose = function(evt) {
565     var mySelEl = evt.target;
566     var result = mySelEl.getAttributeNS(null,"id").split("_");
567     this.activeSelection = parseInt(result[2]);
568     this.curLowerIndex = this.activeSelection;
569     this.foldList();
570     this.listOpen = false;
571     this.selectedText.firstChild.nodeValue = this.elementsArray[this.activeSelection];
572     this.timer.setTimeout("fireFunction",this.timerMs);
575 selectionList.prototype.fireFunction = function() {
576     if (typeof(this.functionToCall) == "function") {
577         this.functionToCall(this.id,this.activeSelection,this.elementsArray[this.activeSelection]);
578     }
579     if (typeof(this.functionToCall) == "object") {
580         this.functionToCall.getSelectionListVal(this.id,this.activeSelection,this.elementsArray[this.activeSelection]);
581     }
582     //suggestion by Bruce Rindahl
583     //allows to initialize a selectionlist without a specific callback function on changing the selectionlist entry
584     if (typeof(this.functionToCall) == undefined) {
585         return;
586     }
589 selectionList.prototype.scrollPerButton = function() {
590     if (this.scrollActive == true) {
591         this.scroll(this.scrollDir,1,true); //1 is one element to scroll, true says that we should move scrollbar
592         this.timer.setTimeout("scrollPerButton",100)
593     }
596 selectionList.prototype.scroll = function(scrollDir,scrollNr,scrollBool) {
597     var nrSelections = this.elementsArray.length;
598     var scroller = document.getElementById("selScroller_"+this.id);
599     //following is a temporary YOffset that serves to distinquish between selectionLists that open above or below
600     var YOffset = this.yOffset + this.cellHeight;
601     if (this.openAbove) {
602         YOffset = this.yOffset - this.heightNrElements * this.cellHeight;
603     }
604     if (scrollNr < this.heightNrElements) {
605         if ((this.curLowerIndex > 0) && (scrollDir == "up")) {
606             if (scrollNr > this.curLowerIndex) {
607                 scrollNr = this.curLowerIndex;
608             }
609             //decrement current index
610             this.curLowerIndex = this.curLowerIndex - scrollNr;
611             //move scroller
612             if (scrollBool == true) {
613                 scroller.setAttributeNS(null,"y",parseFloat(scroller.getAttributeNS(null,"y"))+ this.scrollStep * -1);
614             }
615             //add upper rect elements
616             for (var i=0;i<scrollNr;i++) {
617                 var node = document.createElementNS(svgNS,"rect");
618                 node.setAttributeNS(null,"x",this.xOffset + this.textPadding / 2);
619                 node.setAttributeNS(null,"y",YOffset + this.cellHeight * i);
620                 node.setAttributeNS(null,"width",this.width - this.cellHeight - this.textPadding);
621                 node.setAttributeNS(null,"height",this.cellHeight);
622                 node.setAttributeNS(null,"fill",this.boxStyles["fill"]);
623                 node.setAttributeNS(null,"id","selHighlightSelection_" + this.id + "_" + (i + this.curLowerIndex));
624                 //add event-handler
625                 node.addEventListener("mouseover", this, false);
626                 node.addEventListener("mouseout", this, false);
627                 node.addEventListener("click", this, false);
628                 node.addEventListener("keypress", this, false);
629                 this.dynamicTextGroup.appendChild(node);
630                 //add text-nodes
631                 var node = document.createElementNS(svgNS,"text");
632                 node.setAttributeNS(null,"id","selTexts_" + this.id + "_" + (i + this.curLowerIndex));
633                 node.setAttributeNS(null,"x",this.xOffset + this.textPadding);
634                 node.setAttributeNS(null,"y",YOffset + this.textPaddingVertical + this.cellHeight * i);
635                 node.setAttributeNS(null,"pointer-events","none");
636                 var value = "";
637                 for (var attrib in this.textStyles) {
638                     value = this.textStyles[attrib];
639                     if (attrib == "font-size") {
640                         value += "px";
641                     }
642                     node.setAttributeNS(null,attrib,value);
643                 }        
644                 var selectionText = document.createTextNode(this.elementsArray[this.curLowerIndex + i]);
645                 node.appendChild(selectionText);
646                 this.dynamicTextGroup.appendChild(node);
647             }
648             //move middle elements
649             for (var j=i;j<this.heightNrElements;j++) {
650                 var node = document.getElementById("selTexts_" + this.id + "_" + (j + this.curLowerIndex));
651                 node.setAttributeNS(null,"y",parseFloat(node.getAttributeNS(null,"y")) + (this.cellHeight * scrollNr));
652                 var node = document.getElementById("selHighlightSelection_" + this.id + "_" + (j + this.curLowerIndex));
653                 node.setAttributeNS(null,"y",parseFloat(node.getAttributeNS(null,"y")) + (this.cellHeight * scrollNr));
654             }
655             //remove lower elements
656             for (var k=j;k<(j+scrollNr);k++) {
657                 var node = document.getElementById("selTexts_" + this.id + "_" + (k + this.curLowerIndex));
658                 this.dynamicTextGroup.removeChild(node);
659                 var node = document.getElementById("selHighlightSelection_" + this.id +"_" + (k + this.curLowerIndex));
660                 this.dynamicTextGroup.removeChild(node);
661             }
662         }
663         else if ((this.curLowerIndex < nrSelections - this.heightNrElements) && (scrollDir == "down")) {
664             //move Scroller
665             if (scrollBool == true) {
666                 scroller.setAttributeNS(null,"y",parseFloat(scroller.getAttributeNS(null,"y")) + this.scrollStep);
667             }
668             //remove most upper element
669             for (var i=0;i<scrollNr;i++) {
670                 var node = document.getElementById("selTexts_" + this.id + "_" + (this.curLowerIndex + i));
671                 this.dynamicTextGroup.removeChild(node);
672                 var node = document.getElementById("selHighlightSelection_" + this.id + "_" + (this.curLowerIndex + i));
673                 this.dynamicTextGroup.removeChild(node);
674             }
675             //move middle elements
676             for (var j=i;j<this.heightNrElements;j++) {
677                 var node = document.getElementById("selTexts_" + this.id + "_" + (j + this.curLowerIndex));
678                 node.setAttributeNS(null,"y",parseFloat(node.getAttributeNS(null,"y")) - (this.cellHeight * scrollNr));
679                 var node = document.getElementById("selHighlightSelection_" + this.id + "_" + (j + this.curLowerIndex));
680                 node.setAttributeNS(null,"y",parseFloat(node.getAttributeNS(null,"y")) - (this.cellHeight * scrollNr));
681             }
682             //add most lower element
683             for (var k=j;k<(j+scrollNr);k++) {
684                 var node = document.createElementNS(svgNS,"rect");
685                 node.setAttributeNS(null,"x",this.xOffset + this.textPadding / 2);
686                 node.setAttributeNS(null,"y",YOffset + this.cellHeight * (k - scrollNr));
687                 node.setAttributeNS(null,"width",this.width - this.cellHeight - this.textPadding);
688                 node.setAttributeNS(null,"height",this.cellHeight);
689                 node.setAttributeNS(null,"fill",this.boxStyles["fill"]);
690                 node.setAttribute("id","selHighlightSelection_" + this.id + "_" + (k + this.curLowerIndex));
691                 //add event-handler
692                 node.addEventListener("mouseover", this, false);
693                 node.addEventListener("mouseout", this, false);
694                 node.addEventListener("click", this, false);
695                 node.addEventListener("keypress", this, false);
696                 this.dynamicTextGroup.appendChild(node);
697                 //add text-nodes
698                 var node = document.createElementNS(svgNS,"text");
699                 node.setAttributeNS(null,"id","selTexts_" + this.id + "_" + (k + this.curLowerIndex));
700                 node.setAttributeNS(null,"x",this.xOffset + this.textPadding);
701                 node.setAttributeNS(null,"y",YOffset + this.textPaddingVertical + this.cellHeight * (k - scrollNr));
702                 node.setAttributeNS(null,"pointer-events","none");
703                 var value = "";
704                 for (var attrib in this.textStyles) {
705                     value = this.textStyles[attrib];
706                     if (attrib == "font-size") {
707                         value += "px";
708                     }
709                     node.setAttributeNS(null,attrib,value);
710                 }        
711                 var selectionText = document.createTextNode(this.elementsArray[this.curLowerIndex + k]);
712                 node.appendChild(selectionText);
713                 this.dynamicTextGroup.appendChild(node);
714             }
715             //increment current index
716             this.curLowerIndex = this.curLowerIndex + scrollNr;
717         }
718     }
719     else {
720             //remove lower elements
721             for (var i=0;i<this.heightNrElements;i++) {
722                 var node = document.getElementById("selTexts_" + this.id + "_" + (i + this.curLowerIndex));
723                 this.dynamicTextGroup.removeChild(node);
724                 var node = document.getElementById("selHighlightSelection_" + this.id +"_" + (i + this.curLowerIndex));
725                 this.dynamicTextGroup.removeChild(node);
726             }
727             if (scrollDir == "down") {
728                 this.curLowerIndex = this.curLowerIndex + scrollNr;
729             }
730             else {
731                 this.curLowerIndex = this.curLowerIndex - scrollNr;
732             }
733             for (var i=0;i<this.heightNrElements;i++) {
734                 var node = document.createElementNS(svgNS,"rect");
735                 node.setAttributeNS(null,"x",this.xOffset + this.textPadding / 2);
736                 node.setAttributeNS(null,"y",YOffset + this.cellHeight * i);
737                 node.setAttributeNS(null,"width",this.width - this.cellHeight - this.textPadding);
738                 node.setAttributeNS(null,"height",this.cellHeight);
739                 node.setAttributeNS(null,"fill",this.boxStyles["fill"]);
740                 node.setAttributeNS(null,"id","selHighlightSelection_" + this.id + "_" + (i + this.curLowerIndex));
741                 //add event-handler
742                 node.addEventListener("mouseover", this, false);
743                 node.addEventListener("mouseout", this, false);
744                 node.addEventListener("click", this, false);
745                 node.addEventListener("keypress", this, false);
746                 this.dynamicTextGroup.appendChild(node);
747                 //add text-nodes
748                 var node = document.createElementNS(svgNS,"text");
749                 node.setAttributeNS(null,"id","selTexts_" + this.id + "_" + (i + this.curLowerIndex));
750                 node.setAttributeNS(null,"x",this.xOffset + this.textPadding);
751                 node.setAttributeNS(null,"y",YOffset + this.textPaddingVertical + this.cellHeight * i);
752                 node.setAttributeNS(null,"pointer-events","none");
753                 var value = "";
754                 for (var attrib in this.textStyles) {
755                     value = this.textStyles[attrib];
756                     if (attrib == "font-size") {
757                         value += "px";
758                     }
759                     node.setAttributeNS(null,attrib,value);
760                 }        
761                 var selectionText = document.createTextNode(this.elementsArray[this.curLowerIndex + i]);
762                 node.appendChild(selectionText);
763                 this.dynamicTextGroup.appendChild(node);
764             }
765     }
768 //event listener for Scrollbar element
769 selectionList.prototype.scrollBarMove = function(evt) {
770     var scroller = document.getElementById("selScroller_" + this.id);
771     var scrollerHeight = parseFloat(scroller.getAttributeNS(null,"height"));
772     var scrollerMinY = parseFloat(this.scrollBar.getAttributeNS(null,"y"));
773     var scrollerMaxY = parseFloat(this.scrollBar.getAttributeNS(null,"y")) + parseFloat(this.scrollBar.getAttributeNS(null,"height")) - scrollerHeight;
774     //following is a temporary YOffset that serves to distinquish between selectionLists that open above or below
775     var YOffset = this.yOffset + this.cellHeight;
776     if (this.openAbove) {
777         YOffset = this.yOffset - this.heightNrElements * this.cellHeight;
778     }
779     if (evt.type == "mousedown") {
780         this.panStatus = true;
781         for (var attrib in this.triangleStyles) {
782             scroller.setAttributeNS(null,attrib,this.triangleStyles[attrib]);
783         }        
784         var coordPoint = myMapApp.calcCoord(evt,this.scrollBar);
785         this.panY = coordPoint.y;
786         var oldY = parseFloat(scroller.getAttributeNS(null,"y"));
787         var newY = this.panY - parseFloat(scroller.getAttributeNS(null,"height")) / 2;
788         if (newY < scrollerMinY) {
789             newY = scrollerMinY;
790             //maybe recalculate this.panY ??
791         }
792         if (newY > scrollerMaxY) {
793             newY = scrollerMaxY;
794         }
795         var panDiffY = newY - oldY;
796         var scrollDir = "down";
797         this.scrollCumulus = 0;
798         if(Math.abs(panDiffY) > this.scrollStep) {
799             var scrollNr = Math.abs(Math.round(panDiffY / this.scrollStep));
800             if (panDiffY > 0) {
801                 this.scrollCumulus = panDiffY - this.scrollStep * scrollNr;
802             }
803             else {
804                 this.scrollCumulus = panDiffY + this.scrollStep * scrollNr;
805                 scrollDir = "up";
806             }
807             newY = oldY + panDiffY;
808             scroller.setAttributeNS(null,"y",newY);
809             this.scroll(scrollDir,scrollNr,false);
810         }
811     }
812     if (evt.type == "mouseup" || evt.type == "mouseout") {
813         if (this.panStatus == true) {
814             var newY = parseFloat(scroller.getAttributeNS(null,"y"));
815             for (var attrib in this.smallrectStyles) {
816                 scroller.setAttributeNS(null,attrib,this.smallrectStyles[attrib]);
817             }        
818             scroller.setAttributeNS(null,"y",YOffset + this.cellHeight + this.scrollStep * this.curLowerIndex);
819         }
820         this.panStatus = false;
821     }
822     if (evt.type == "mousemove") {
823         if (this.panStatus == true) {
824             var coordPoint = myMapApp.calcCoord(evt,this.scrollBar);
825             var panNewEvtY = coordPoint.y;
826                 var panDiffY = panNewEvtY - this.panY;
827                 var oldY = parseFloat(scroller.getAttributeNS(null,"y"));
828                 var newY = oldY + panDiffY;
829                 if (newY < scrollerMinY) {
830                     newY = scrollerMinY;
831                 }
832                 if (newY > scrollerMaxY) {
833                     newY = scrollerMaxY;
834                 }
835             var panDiffY = newY - oldY;
836             if ((panDiffY < 0 && panNewEvtY <= (scrollerMaxY+scrollerHeight)) || (panDiffY > 0 && panNewEvtY >= scrollerMinY)) {
837                 this.scrollCumulus += panDiffY;
838                 var scrollDir = "down";
839                 var scrollNr = 0;
840                 if(Math.abs(this.scrollCumulus) >= this.scrollStep) {
841                     scrollNr = Math.abs(Math.round(this.scrollCumulus / this.scrollStep));
842                     if (this.scrollCumulus > 0) {
843                         this.scrollCumulus = this.scrollCumulus - this.scrollStep * scrollNr;
844                     }
845                     else {
846                         this.scrollCumulus = this.scrollCumulus + this.scrollStep * scrollNr;
847                         scrollDir = "up";
848                     }
849                     this.scroll(scrollDir,scrollNr,false);
850                 }
851                 else {
852                     if (Math.abs(this.scrollCumulus) > this.scrollStep) {
853                         scrollNr = 1;
854                         if (panDiffY < 0) {
855                             scrollDir = "up";
856                             this.scrollCumulus = this.scrollCumulus + this.scrollStep;
857                         }
858                         else {
859                             this.scrollCumulus = this.scrollCumulus - this.scrollStep;
860                         }
861                         panDiffY = this.scrollCumulus;
862                         this.scroll(scrollDir,scrollNr,false);
863                     }
864                     else {
865                         if (newY == scrollerMinY && this.curLowerIndex != 0) {
866                             this.scroll("up",1,false);
867                         }
868                         else if (newY == scrollerMaxY && this.curLowerIndex != (this.elementsArray.length - this.heightNrElements)) {
869                             this.scroll("down",1,false);
870                         }
871                     }
872                 }
873                 newY = oldY + panDiffY;
874                 scroller.setAttributeNS(null,"y",newY);
875                 this.panY = panNewEvtY;
876             }
877         }
878     }
881 selectionList.prototype.scrollToKey = function(pressedKey) {
882     var oldActiveSelection = this.activeSelection;
883     for (var i=0;i<this.elementsArray.length;i++) {
884         if (this.elementsArray[i].toLowerCase().substr(0,this.pressedKeys.length) == this.pressedKeys) {
885             if (this.listOpen == true) {
886                 this.foldList();
887             }
888             this.activeSelection = i;
889             this.unfoldList();
890             this.listOpen = true;
891             this.activeSelection = oldActiveSelection;
892             break;
893         }
894     }
897 selectionList.prototype.elementExists = function(elementName) {
898     var result = -1;
899     for (i=0;i<this.elementsArray.length;i++) {
900         if (this.elementsArray[i] == elementName) {
901             result = i;
902         }
903     }
904     return result;
907 selectionList.prototype.selectElementByName = function(elementName,fireFunction) {
908     //fireFunction: (true|false); determines whether to execute selectFunction or not
909     existsPosition = this.elementExists(elementName);
910     if (existsPosition != -1) {
911         if (this.listOpen == true) {
912             this.foldList();
913         }
914         this.activeSelection = existsPosition;
915         this.selectedText.firstChild.nodeValue = this.elementsArray[this.activeSelection];
916         if (this.listOpen == true) {
917             this.unfoldList();
918         }
919         if (fireFunction == true) {
920             this.fireFunction();
921         }
922     }
923     return existsPosition;
926 selectionList.prototype.selectElementByPosition = function(position,fireFunction) {
927     //fireFunction: (true|false); determines whether to execute selectFunction or not
928     if (position < this.elementsArray.length) {
929         if (this.listOpen == true) {
930             this.foldList();
931         }
932         this.activeSelection = position;
933         this.selectedText.firstChild.nodeValue = this.elementsArray[this.activeSelection];
934         if (this.listOpen == true) {
935             this.unfoldList();
936         }
937         if (fireFunction == true) {
938             this.fireFunction();
939         }
940     }
941     else {
942         position = -1;
943     }
944     return position;
947 selectionList.prototype.sortList = function(direction) {
948     //direction: asc|desc, for ascending or descending
949     var mySelElementString = this.elementsArray[this.activeSelection];
950     if (this.listOpen == true) {
951         this.foldList();
952     }
953     this.elementsArray.sort();
954     if (direction == "desc") {
955         this.elementsArray.reverse();
956     }
957     this.activeSelection = this.elementExists(mySelElementString);
958     if (this.listOpen == true) {
959         this.unfoldList();
960     }
962     return direction;
965 selectionList.prototype.deleteElement = function(elementName) {
966     existsPosition = this.elementExists(elementName);
967     if (existsPosition != -1) {
968         if (this.listOpen == true) {
969             this.foldList();
970         }
971         var tempArray = new Array;
972         tempArray = tempArray.concat(this.elementsArray.slice(0,existsPosition),this.elementsArray.slice(existsPosition + 1,this.elementsArray.length));
973         this.elementsArray = tempArray;
974         if (this.activeSelection == existsPosition) {
975             this.selectedText.firstChild.nodeValue = this.elementsArray[this.activeSelection];
976         }
977         if (this.activeSelection > existsPosition) {
978             this.activeSelection -= 1;
979         }
980         if (this.listOpen == true) {
981             this.unfoldList();
982         }
983     }
984     return existsPosition;
987 selectionList.prototype.addElementAtPosition = function(elementName,position) {
988     if (position > this.elementsArray.length) {
989         this.elementsArray.push(elementName);
990         position = this.elementsArray.length - 1;
991     }
992     else {
993         var tempArray = new Array;
994         tempArray = tempArray.concat(this.elementsArray.slice(0,position),elementName,this.elementsArray.slice(position,this.elementsArray.length));
995         this.elementsArray = tempArray;
996     }
997     if (this.listOpen == true) {
998         this.foldList();
999     }
1000     if (position <= this.activeSelection) {
1001         this.activeSelection += 1;
1002     }
1003     if (this.listOpen == true) {
1004         this.unfoldList();
1005     }
1006     return position;
1009 selectionList.prototype.getCurrentSelectionElement = function() {
1010     return this.elementsArray[this.activeSelection];
1013 selectionList.prototype.getCurrentSelectionIndex = function() {
1014     return this.activeSelection;
1017 selectionList.prototype.removeSelectionList = function() {
1018     //remove all Elements of selectionList
1019     this.exists = false;
1020     while (this.parentGroup.hasChildNodes()) {
1021         this.parentGroup.removeChild(this.parentGroup.firstChild);
1022     }
1025 selectionList.prototype.moveTo = function(moveX,moveY) {
1026     this.xOffset = moveX;
1027     this.yOffset = moveY;
1028     //reposition initial rectangle
1029     var initRect = document.getElementById("selRect_"+this.id);
1030     initRect.setAttributeNS(null,"x",this.xOffset);
1031     initRect.setAttributeNS(null,"y",this.yOffset);
1032     //reposition initial text
1033     this.selectedText.setAttributeNS(null,"x",this.xOffset + this.textPadding);
1034     this.selectedText.setAttributeNS(null,"y",this.yOffset + this.textPaddingVertical);
1035     //reposition small rectangle to the right
1036     var smallRectRight = document.getElementById("selPulldown_"+this.id);
1037     smallRectRight.setAttributeNS(null,"x",this.xOffset + this.width - this.cellHeight);
1038     smallRectRight.setAttributeNS(null,"y",this.yOffset);
1039     //reposition triangle
1040     var triangle = document.getElementById("selTriangle_"+this.id);
1041     var myTrianglePath = "M"+(this.xOffset + this.width - 3 * this.triangleFourth)+" "+(this.yOffset + this.triangleFourth)+" L"+(this.xOffset + this.width - this.triangleFourth)+" "+(this.yOffset + this.triangleFourth)+" L"+(this.xOffset + this.width - 2 * this.triangleFourth)+" "+(this.yOffset + 3 * this.triangleFourth)+" Z";
1042     triangle.setAttributeNS(null,"d",myTrianglePath);    
1043     //change positions of rectbox below and above
1044     this.rectBelowBox.setAttributeNS(null,"x",this.xOffset);
1045     this.rectBelowBox.setAttributeNS(null,"y",this.yOffset + this.cellHeight);
1046     this.rectAboveBox.setAttributeNS(null,"x",this.xOffset);
1047     this.rectAboveBox.setAttributeNS(null,"y",this.yOffset + this.cellHeight);
1050 selectionList.prototype.resize = function(newWidth) {
1051     this.width = newWidth;
1052     //reposition initial rectangle
1053     var initRect = document.getElementById("selRect_"+this.id);
1054     initRect.setAttributeNS(null,"width",this.width);
1055     //reposition small rectangle to the right
1056     var smallRectRight = document.getElementById("selPulldown_"+this.id);
1057     smallRectRight.setAttributeNS(null,"x",this.xOffset + this.width - this.cellHeight);
1058     //reposition triangle
1059     var triangle = document.getElementById("selTriangle_"+this.id);
1060     var myTrianglePath = "M"+(this.xOffset + this.width - 3 * this.triangleFourth)+" "+(this.yOffset + this.triangleFourth)+" L"+(this.xOffset + this.width - this.triangleFourth)+" "+(this.yOffset + this.triangleFourth)+" L"+(this.xOffset + this.width - 2 * this.triangleFourth)+" "+(this.yOffset + 3 * this.triangleFourth)+" Z";
1061     triangle.setAttributeNS(null,"d",myTrianglePath);    
1062     //change sizes of rectbox below and above
1063     this.rectBelowBox.setAttributeNS(null,"width",this.width - this.cellHeight);
1064     this.rectAboveBox.setAttributeNS(null,"width",this.width - this.cellHeight);