This SVG selectionList object should assist authors of SVG webapplications in creating user interfaces.
Why should you create SVG only web applications? Advantages of SVG only applications are flexiblity (you can control every single aspect of a SVG GUI element) and scalability (in SVG your userinterface elements are scalable as well). If you need a pixel-precise, scalable application, HTML is not very well suited, since HTML form elements don't scale well. SVG also potentially allows more sophisticated GUI elements than HTML provides, such as slider, dial knobs, complex colourpickers, etc. Disadvantages include complexity (more complex than using HTML form elements) and a potentially bad user experience, if your SVG GUI elements behave different than native GUI elements of the operating system the user is used to. Some browsers still don't support SVG to HTML or HTML to SVG communication. In that case you are sort of locked into doing everything with SVG in order to reach the broadest audience. Another advantage of creating SVG only applications is, that your applications also work in SVG viewers outside the webbrowser (e.g. Batik, eSVG or SVG embedded applications).
The selectionList is free to use. If you do any substantial improvements, please send back your improvements to the author. The GUI elements of carto.net are licensed under the terms of the LGPL license and you need to distribute the license with your code. Additionally, you should create a link to carto.net in your project's "about page" or impressum. If you plan to use the GUI elements in a commercial product, please check back with the author of the GUI elements to investigate arrangements. The original URL for the selectionList is https://old.carto.net/papers/svg/gui/selectionlist/.
Documentation
Requirements
To use the selectionList, your project needs to meet the following requirements:
- the svg root element needs to have a viewBox attribute set (e.g. viewBox="0 0 1024 768")
- you need to link to the following scripts in your SVG header to use the selectionList: mapApp.js, helper_functions.js, timer.js and selectionList.js; please note, that not all of the functions in these files are needed. The depencies to functions in the file "helper_functions.js" are listed below.
- you need to include the global variable "myMapApp" of type "mapApp" into one of your js files, (e.g. var myMapApp = new mapApp();)
- you need to create an empty svg group element with a unique id in an appropriate position of your document tree to hold the graphics of the selectionList (e.g. <g id="mySelectionList" />)
- it is recommended to place a background rectangle behind your SVG application to receive events on the root element level, e.g. folding the selectionList when clicking outside of the selectionList
- you need to initialize the selectionList as described below
Features
- supports large lists
- supports keyboard input to quickly navigate in longer lists
- click in scrollbar jumps directly to position in the list, no need for scrolling
- list folds automatically if the user clicks outside the selectionlist, given that an element exists in the background, e.g. a background rectangle
- selectionList can open to the top or the bottom of the initial box
- selectionList is completely and individually stylable using arrays of literals containing presentation attributes
Dependencies on external functions
- selectionList.js:
- all of the objects and functions in this file are necessary
- mapApp.js:
- all of the objects and functions in this file are necessary
- timer.js:
- all of the objects and functions in this file are necessary
- helper_functions.js:
- all the global variables at the top of the file
Constructor
The following constructor function creates the selectionList:
var mySelectionList = new selectionList(id,parentNode,elementsArray,width,xOffset,yOffset,cellHeight,textPadding,heightNrElements,textStyles,boxStyles,scrollbarStyles,smallrectStyles,highlightStyles,triangleStyles,preSelect,openAbove,putOnTopOfParent,functionToCall);
Example:
//first a few styling parameters:
var selBoxCellHeight = 16;
var selBoxTextpadding = 3;
var selBoxtextStyles = {"font-family":"Arial,Helvetica","font-size":11,"fill":"dimgray"};
var selBoxStyles = {"stroke":"dimgray","stroke-width":1,"fill":"white"};
var selBoxScrollbarStyles = {"stroke":"dimgray","stroke-width":1,"fill":"whitesmoke"};
var selBoxSmallrectStyles = {"stroke":"dimgray","stroke-width":1,"fill":"lightgray"};
var selBoxHighlightStyles = {"fill":"dimgray","fill-opacity":0.3};
var selBoxTriangleStyles = {"fill":"dimgray"};
//now the creation of the selectionlist
var selFruits = new selectionList("fruits","fruits",fruits,170,50,50,selBoxCellHeight,selBoxTextpadding,7,selBoxtextStyles,selBoxStyles,selBoxScrollbarStyles,selBoxSmallrectStyles,selBoxHighlightStyles,selBoxTriangleStyles,3,false,true,myFruitsResult);
The arguments are the following:
- id (String):
unique id that identifies the selectionList
- parentNode (String or object):
an existing group id or node reference (<g/> or <svg/> element) where the new selectionList object will be appended. This group is preferably empty, but does not have to be. If the group id or node reference does not exist, the script creates a new empty parent group and appends it to the root element.
- elementsArray (Array of Strings):
array of values to be selected in the selectionList
- width (number, in viewBox coordinate system):
overall width of the selectionList
- xOffset (number, in viewBox coordinate system):
left side of the selectionList rectangle
- yOffset (number, in viewBox coordinate system):
top of the selectionList rectangle
- cellHeight (number, in viewBox coordinate system):
the height of the selectionList and a row in the unfolded list
- textPadding (number, in viewBox coordinate system):
the horizontal text padding, offset from the right of the rectangle of the textbox
- heightNrElements (number, integer):
height of unfolded list in number of elements
- textStyles (array of literals with presentation attributes):
an array literal containing the presentation attributes of the selection box texts; could include CSS classes; should at least include a "font-size" attribute; example: var selBoxtextStyles = {"font-family":"Arial,Helvetica","font-size":11,"fill":"dimgray"};
- boxStyles (array of literals with presentation attributes):
an array literal containing the presentation attributes of the selection box; could include CSS classes; should at least include a "fill", "stroke" and "stroke-width" attribute; example: var selBoxStyles = {"stroke":"dimgray","stroke-width":1,"fill":"white"};
- scrollbarStyles (array of literals with presentation attributes):
an array literal containing the presentation attributes of the scrollbar; could include CSS classes; example: var selBoxScrollbarStyles = {"stroke":"dimgray","stroke-width":1,"fill":"whitesmoke"};
- selBoxSmallrectStyles (array of literals with presentation attributes):
an array literal containing the presentation attributes of the small rectangles (the ones containing the triangles); could include CSS classes; example: var selBoxSmallrectStyles = {"stroke":"dimgray","stroke-width":1,"fill":"lightgray"};
- highlightStyles (array of literals with presentation attributes):
an array literal containing the presentation attributes of the highlight rectangles; could include CSS classes; example: var selBoxHighlightStyles = {"fill":"dimgray","fill-opacity":0.3};
- selBoxTriangleStyles (array of literals with presentation attributes):
an array literal containing the presentation attributes of the triangle (where the user clicks for unfolding or scrolling the list); could include CSS classes; example: var selBoxTriangleStyles = {"fill":"dimgray"};
- preSelect (number, integer, zero-based):
index of preselected element, zero based
- openAbove (boolean, true|false):
defines if the box opens to the bottom (false) or the top (true)
- putOnTopOfParent (boolean, true|false):
defines if the box will be appended to the top of it's parent group on activation. This ensures that the selectionList always opens on top of other elements in the same group. Set to true if you want this behaviour, false if you don't.
- functionToCall (function or object or undefined):
callBackFunction: you can pass a function, object or undefined. In the case of function and object the parameters returned are: the groupId of the selectionList (string), the index nr selected (number, integer), the value selected (string). In case of an object, it calls the method .getSelectionListVal(). In case of an undefined value, no callBack function is executed. The callBack function is executed with a slight delay (200ms) to allow the selectionlist to unfold before executing the callback function.
Methods
- .getCurrentSelectionElement():
returns the active selection value (string)
- .getCurrentSelectionIndex():
returns the active selection value (number, integer)
- .elementExists(elementName):
checks if an element exists; returns -1 if it does not exist, or the index where the element exists if the test is positive
- .selectElementByName(elementName,fireFunction):
selects the given element if it exists; parameters are the element name (string) and a boolean value whether we should execute the callBack function or not after selecting the element; returns -1 if it does not exist, or the index where the element exists if the test is positive
- .selectElementByPosition(position,fireFunction):
selects the given element by position if it exists; parameters are the element index (number, integer) and a boolean value whether we should execute the callBack function or not after selecting the element; returns -1 if it does not exist, or the index where the element exists if the test is positive
- .sortList(direction):
sorts the list alphabetically by direction; parameter is the direction ('asc' or 'desc'); the return value is the direction
- .deleteElement(elementName):
deletes the element with the given value; parameter is the element name/value (string); the return value is the position of the element it deleted, or -1 if the element did not exist
- .addElementAtPosition(elementName,position):
adds an element with the given value; parameter are the element name/value (string) and the position index (number, integer); the return value is the position of the element it added
- .resize(width):
resizes the selectionList to a new width, parameter is of type number in viewBox coordinates
- .moveTo(x,y):
moves the selectionList to a new position, both parameters are of type number in viewBox coordinates
- .removeSelectionList():
removes all geometry elements of the selectionList and leaves an empty group; sets the property .exists to false
Useful Properties
- .elementsArray:
the array containing the values of a selectionlist. If you want to exchange the values of a selectionlist, simply state mySelectionList.elementsArray = newArray;. Don't forget to call the method mySelectionList.selectElementByPosition(0,false) to make sure that it displays a valid value of you new array, after you changed the elementsArray() property
- .id:
type string; the id of the selectionlist
- .heightNrElements:
type number (integer); the height of the unfolded selectionlist in number of elements
- .openAbove:
type boolean (true|false); indicates whether the list opens to the bottom (false) or to the top (true), you can set this property to open it to above, next time the user unfolds the list
Version history
- 0.99 (2004-10-26): initial version
- 1.0 (2005-09-15): allow undefined values in callback function for selectionlists that need not react on changes (suggestion by Bruce Rindahl); allow selectionlist to be placed in a transformed group; now also works in MozillaSVG (due to changes in mapApp.js)
- 1.1 (2005-09-15): removed "string" option in functionToCall (not important any more). function and object should be good enough; timer object from https://www.codingforums.com/showthread.php?s=&threadid=10531 is now used; attention: you need to link this script as well! 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
- 1.2 (2005-10-24): removed style attributes and replaced them with individual XML attributes, initial tests on Opera 9, it seems to work except for the scrolling - due to a mouse-move event bug
- 1.2.1 (2006-02-07): upgraded the documentation and fixed documentation errors
- 1.2.2 (2006-02-16): 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; 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; improved background rectangle: these are now two rectangles: one on the bottom for the fill, one on the top for stroking; tested with Opera 9 TP2, works now fine, except keyboard input
- 1.2.3 (2006-02-21): removed dependency on replaceSpecialChars (in file helper_functions.js) as this is not really needed in a true utf8 environment; 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.
- 1.3 (2006-03-11): changed parameters of constructor (styling system): now an array of literals containing presentation attributes. Styling is not hardcoded in selectionList.js anymore. Added check for number of arguments.
- 1.4 (2006-07-18): added additional constructor parameter parentNode, changed constructor parameter groupId to id, added methods .resize(width) and .moveTo(x,y), improved scrolling (now also possible outside of the scrollbar, once the mouse is down)
- 1.4.1 (2007-04-16): corrected a bug where the closing of the selectionList failed if the id had a "_" underscore in its id, due to split error