This SVG combobox 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 combobox 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 combobox is https://old.carto.net/papers/svg/gui/combobox/.
Documentation
Requirements
To use the combobox, 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")
- set the zoomAndPan="disable" attribute in the svg root element; this is a currently known limitation, that it does not work correctly after zooming and panning manually within the plugin
- you need to link to the following scripts in your SVG header: mapApp.js, helper_functions.js, timer.js and combobox.js; please note, that not all of the functions in these files are needed. The depencies to functions in external ecmascript files are listed below.
- you need to include the global variable "myMapApp" of type "mapApp" into one of your js files, (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 combobox (e.g. <g id="myCombobox" />)
- it is recommended to place a background rectangle behind your SVG application to receive events on the root element level, e.g. stopping the mouse events if the user drags outside the combobox
- you need to initialize the combobox 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 a lot of scrolling
- Multiselections can be made using the shift and ctrl/apple key kombinations or by dragging with the pressed mouse button
- methods exist to delete and add elements or reorder the list of elements
- methods exist for "select all", "select none" and "inverse selection"
Dependencies on external functions
- combobox.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 are necessary
Constructor
The following constructor function creates the combobox:
var myCombobox = new combobox(id,parentNode,elementsArray,width,xOffset,yOffset,cellHeight,textPadding,heightNrElements,multiple,offsetValue,textStyles,boxStyles,scrollbarStyles,smallrectStyles,highlightStyles,triangleStyles,functionToCall);
Example:
//first a few styling parameters:
var comboBoxCellHeight = 16;
var comboBoxTextpadding = 3;
var comboBoxtextStyles = {"font-family":"Arial,Helvetica","font-size":11,"fill":"dimgray"};
var comboBoxStyles = {"stroke":"dimgray","stroke-width":1,"fill":"white"};
var comboBoxScrollbarStyles = {"stroke":"dimgray","stroke-width":1,"fill":"whitesmoke"};
var comboBoxSmallrectStyles = {"stroke":"dimgray","stroke-width":1,"fill":"lightgray"};
var comboBoxHighlightStyles = {"fill":"dimgray","fill-opacity":0.3};
var comboBoxTriangleStyles = {"fill":"dimgray"};
//this array contains the values
var roses = new Array({key:"Butterscotch",value:false},{key:"Ci Peace",value:false},{key:"Impatient",value:false},{key:"Lady Hillingdon",value:false},{key:"Lavaglut",value:false},{key:"Mission Bells",value:false},{key:"Sexy Rexy",value:false},{key:"Souvenir de Pierre Notting",value:false},{key:"Sunflare",value:false},{key:"Whisky Mac",value:false},{key:"Whisper Floribunda",value:false});
//now the initialization of the combobox
var comboRoses = new combobox("roses","roses",roses,170,50,300,comboBoxCellHeight,comboBoxTextpadding,5,true,50,comboBoxtextStyles,comboBoxStyles,comboBoxScrollbarStyles,comboBoxSmallrectStyles,comboBoxHighlightStyles,comboBoxTriangleStyles,showRoses);
The arguments are the following:
- id (String):
unique id that identifies the combobox
- parentNode (String or object):
an existing group id or node reference (<g/> or <svg/> element) where the new combobox 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 Literals):
The array containing the element names and corresponding values (true|false); needs to be in the following format: var flowers = new Array({key:"Acacia",value:false},{key:"Acanthus",value:false},{key:"Amaranth",value:false},{key:"Anthericum",value:false}
- width (in viewBox coordinate system):
overall width of the combobox
- xOffset (in viewBox coordinate system):
left side of the combobox rectangle
- yOffset (in viewBox coordinate system):
top of the combobox rectangle
- cellHeight (in viewBox coordinate system):
the height of one cell in the combobox
- textPadding (in viewBox coordinate system):
the offset of the text element in a combobox cell from the left side of the cell
- heightNrElements (number, integer):
height of combobox in number of elements
- multiple (boolean, true|false):
indicates if multiple values or only a single value can be selected
- offsetValue (number, integer):
offset (element index) of the elementsArray. If not zero, the combobox will be initialized with this offset and the scrollbar adjusted accordingly
- textStyles (array of literals with presentation attributes):
an array literal containing the presentation attributes of the combobox texts; could include CSS classes; should at least include a "font-size" attribute; example: var comboBoxtextStyles = {"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 combobox; could include CSS classes; should at least include a "fill", "stroke" and "stroke-width" attribute; example: var comboBoxStyles = {"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 comboBoxScrollbarStyles = {"stroke":"dimgray","stroke-width":1,"fill":"whitesmoke"};
- smallrectStyles (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 comboBoxSmallrectStyles = {"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 comboBoxHighlightStyles = {"fill":"dimgray","fill-opacity":0.3};
- triangleStyles (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 comboBoxTriangleStyles = {"fill":"dimgray"};
- 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 groupName of the combobox (string), an array of strings containing the selected values, an array of integers containing the selected index values. In case of an object, it calls the method .getComboboxVals(). In case of an undefined value, no callBack function is executed. The callBack function is executed with a slight delay (200ms). Naturally, you can adjust this value in the constructor function.
Methods
- .getCurrentSelections():
returns an array of strings containing the currently selected elements - .getCurrentSelectionIndex():
returns an array of integers containing the active selection indizes
- .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
- .selectElementsByName(elementNames,fireFunction):
selects the given element if they exist; parameters are the element names and selection values (array of literals) and a boolean value whether we should execute the callBack function or not; example: var additionalElements = new Array({key:"Boswil",value:true},{key:"Brugg",value:true}); comboCommunitiesAargau.selectElementsByName(additionalElements,false);
- .selectElementsByPosition(positionArray,fireFunction):
selects the given elements by position if they exist; parameters are the element indizes and values (array of literals) and a boolean value whether we should execute the callBack function or not; example: var additionalElements = new Array({index:0,value:true},{index:2,value:true},{index:4,value:true}); comboCommunitiesAargau.selectElementsByPosition(additionalElements,false);
- .selectAll(fireFunction):
selects all elements in the combobox; parameter is a boolean value whether we should execute the callBack function or not; example:comboCommunitiesAargau.selectAll(false)
- .deselectAll(fireFunction):
deselects all elements in the combobox; parameter is a boolean value whether we should execute the callBack function or not; example:comboCommunitiesAargau.deselectAll(false)
- .invertSelection(fireFunction):
inverts the selection in the combobox; parameter is a boolean value whether we should execute the callBack function or not; example:comboCommunitiesAargau.invertSelection(false)
- .sortList(direction):
sorts the list alphabetically by direction; parameter is the direction ('asc' or 'desc')
- .deleteElementsByName(elementNames,fireFunction):
deletes the elements with the given element names; parameters are the element names (array of strings) and a boolean value whether we should execute the callBack function or not; example: var deleteElements = new Array("Boswil","Brugg","Brunegg","Buttwil"); comboCommunitiesAargau.deleteElementsByName(deleteElements,false);
- .deleteElementByPosition(elementPosition,fireFunction):
deletes a single element with the given element index; parameters are the element index (integer) and a boolean value whether we should execute the callBack function or not; example: comboCommunitiesAargau.deleteElementByPosition(1,false);
- .addElementAtPosition(element,position,fireFunction):
adds an element at the given position; parameters are the element (literal), the position (integer) and a boolean value whether we should execute the callBack function or not; example: comboCommunitiesAargau.addElementAtPosition({key:"Zurich",value:true},0,false);
- .addElementsAlphabetically(elementsArr,direction,fireFunction):
adds the given elements and sorts the list alphabetically; parameters are the element array (array of literals), the direction for alphabetic ordering (string: "asc"|"desc") and a boolean value whether we should execute the callBack function or not; example: var addElementsArray = new Array({key:"Zurich",value:true},{key:"Rickenbach (ZH)",value:true},{key:"Innsbruck",value:false}); comboCommunitiesAargau.addElementsAlphabetically(addElementsArray,"desc",false);
- .moveTo(x,y):
moves the combobox to a new position, both parameters are of type number in viewBox coordinates
- .resize(width):
resizes the combobox to a new width, parameter is of type number in viewBox coordinates
- .removeCombobox():
removes all geometry elements of the combobox and leaves an empty group; sets the property .exists to false; note that the combox object is unusable in this state
Look and Feel
You can adapt the look and feel (colors, fonts, sizes, etc.) in the combobox.js script (top section in the constructor function). We simply assign XML attributes to various elements of the combobox.
Current Limitation
Currently, the combobox object may react strange if users zoom in with the plugin. This limitation might be eliminated in a later version. If multiselecting elements by mousedown and dragging, the list does not scroll if the user moves to the top or bottom of the combobox. This feature might be introduced in the future.
Version history
- 1.0 (2006-02-21): initial version
- 1.1 (2006-05-17): decoupled styling from the file combobox.js, fixes event handling so people can scroll outside scroller if mouse is down (events now added to root element)
- 1.2 (2006-10-02): changed internally groupId to id to make it consistent with other GUI elements, introduced parentId as a new constructor parameter for the same reason, introduced new methods .resize() and .moveTo()
- 1.2.1 (2006-10-03): corrected a slight bug regarding DOM hierarchy of created elements