SVG Textbox, Version 1.1.2, 2006-10-04, (see history at the end of the page)
This SVG textbox 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).
See an example of the SVG textbox object. The scripts had been tested in Adobe SVG viewer version 3, version 6, Opera 9, Firefox/Mozilla SVG and Batik. There are limitations in Firefox 1.5 and 2.0 due to unimplemented DOM methods on text nodes (see below). In Opera 9 there are limitations because some special character keys collide with functional keys (see below)
The textbox 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 textbox is https://old.carto.net/papers/svg/gui/textbox/.
Documentation
Requirements
To use the textbox, your project needs to meet the following requirements:
- the svg root element needs to have a viewBox attribute set (e.g. viewBox="0 0 1100 700")
- you need to link to the following scripts in your SVG header to use the textbox: mapApp.js, helper_functions.js, timer.js and textbox.js; please note, that not all of the functions in these files are needed. The depencies 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 textbox (e.g. <g id="textbox1" />)
- it is recommended to place a background rectangle behind your SVG application to receive events on the root element level, e.g. loosing focus and calling the callback function when clicking outside of the textbox
- you need to initialize the textbox as described below
Features
- text larger than the textbox scrolls
- text is selectable through mouse and keyboard
- a list of valid characters can be specified, e.g. you can restrict a textbox to allow only digits
- the maximum number of characters can be controlled
- textbox is completely and individually stylable using arrays of literals containing presentation attributes
- textbox may be resized (width only) and repositioned
Dependencies on external functions
- textbox.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
- .getTransformToRootElement(node)
Constructor
The following constructor function creates the textbox:
var textbox = new textbox(id,parentNode,defaultVal,maxChars,x,y,boxWidth,boxHeight,textYOffset,textStyles,boxStyles,cursorStyles,selBoxStyles,allowedChars,functionToCall);
Example:
//first a few styling parameters:
var textStyles = {"font-family":"Arial,Helvetica","font-size":15,"fill":"dimgray"};
var boxStyles = {"fill":"white","stroke":"dimgray","stroke-width":1.5};
var cursorStyles = {"stroke":"red","stroke-width":1.5};
var selBoxStyles = {"fill":"blue","opacity":0.5};
textbox1 = new textbox("textbox1","textbox1","Textbox1",25,100,100,200,30,22,textStyles,boxStyles,cursorStyles,selBoxStyles,"[a-zA-Z ]",writeOutTextContent);
The arguments are the following:
- id (String):
unique id for the textbox
- parentNode (String or node reference):
group id or node reference to the parent group that will contain the textbox geometry
- defaultVal (String):
the initial text to be displayed after the textbox is created
- maxChars (integer):
the allowed maximum number of characters to be entered in the textbox
- x (number, in viewBox coordinate system):
left side of the textbox
- y (number, in viewBox coordinate system):
upper side of the textbox
- boxWidth (number, in viewBox coordinate system):
the width of the textbox
- boxHeight (number, in viewBox coordinate system):
the height of the textbox
- textYOffset (number, in viewBox coordinate system):
the offset of the text element in relation to the upper side of the textbox rectangle
- textStyles (array of literals with presentation attributes):
an array literal containing the presentation attributes of the textbox texts; could include CSS classes; should at least include a "font-size" attribute; example: var textStyles = {"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 textbox; could include CSS classes; should at least include a "fill", "stroke" and "stroke-width" attribute; example: var boxStyles = {"fill":"white","stroke":"dimgray","stroke-width":1.5};
- cursorStyles (array of literals with presentation attributes):
an array literal containing the presentation attributes of the textcursor; could include CSS classes; should include a "stroke" and "stroke-width" attribute; example: var cursorStyles = {"stroke":"red","stroke-width":1.5};
- selBoxStyles (array of literals with presentation attributes):
an array literal containing the presentation attributes of the selection rectangle; could include CSS classes; example: var selBoxStyles = {"fill":"blue","opacity":0.5};
- allowedChars (RegExp arguments):
range of allowed characters, this string will be used to create a RegExp object; example: [a-zA-Z ] or [0-9]; note that you can pass undefined or an empty string ("") if you don't want to restrict characters
- 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 texbox (string), the text value (string) and the changetype (string (release|change)). In case of an object, it calls the method .textboxChanged(). In case of an undefined value, no callBack function is executed. The callBack function is executed with a slight delay (200ms) to allow the texbox to first update it's state before calling the callback function. The changetype parameter "change" means that a change in the textbox' textstring occured, either by adding, deleting or modifying a character; "release" means that the textbox lost the focus; "set" means that a new value was just set by the method .setValue()
Methods
- .getValue():
returns the current value of the textbox (string)
- .setValue(value,fireFunction):
sets the current value of the textbox (string), the second parameter (boolean) indicates whether or not the associated callBack function should be fired
- .moveTo(x,y):
repositions the textbox. The reference point is the upper left corner of the textbox. Parameter are x and y values in viewBox coordinates.
- .resize(width):
resizes the width of the textbox. Parameter is the new width in viewBox coordinates
Current Limitations, Known Issues
- There seems to be a bug when using the textbox in Batik and clicking directly from one textbox to the other. We are trying to track down the problem and fix it asap
- MozillaSVG (versions 1.5 and 2.0) don't implement functions to determine geometries of individual characters, e.g. .getCharNumAtPosition(mySVGPoint) or .getEndPositionOfChar(position). Hence, in these browsers, the functionality of the textbox is very limited. One can modify the textbox content, but one cannot use the cursor keys or select parts of the textstring. First tests with Firefox 3 (alias Minefield) showed that the textbox works in FF3.
- Opera 9 only supports evt.keyCode and not evt.charCode or both, like other browsers. As a result one cannot distinguish certain functional keys (like arrow keys, home, end, etc.) from regular character keys when they are combined with the shift key. In this textbox implementation one cannot use certain special characters as a consequence. This affects the following keys: 35 (end key) - collides with "#", 36 (home key) - collides with "$", 37 (left key) - collides with "%", 39 (right key) - collides with "'" sign, 46 (delete key) - collides with "." sign. Currently we don't support these characters, since the codes are reserved for the functionality of the textbox. Once Opera supports evt.charCode or DOM3 keyboard events, this issue will be resolved.
- If you use the textbox in Internet Explorer and Adobe SVG viewer, avoid the use of the <embed /> element. Certain keyboard events don't work in conjunction with embed. We recommend using <iframe /> instead. This is likely a bug in Adobe SVG Viewer or Internet Explorer. Nothing wrong with the code of this textbox object.
Version history
- 1.0 (2006-05-03): initial version
- 1.0.1 (2006-05-04): fixed a bug with the delete key after clicking into the texbox, fixed a bug with text selection
- 1.0.2 (2006-05-18): made object multi-namespace aware (hopefully), this probably needs more testing; it is now allowed to pass numbers in the constructor and .setValue() method
- 1.0.3 (2006-05-22): fixed a bug in internal method .testSupportsChar() when using an initially empty textbox
- 1.0.4 (2006-06-22): added constructor parameter this.parentNode; this.parentNode can be of type String (id) or a node reference (g or svg element)
replaced this.textboxGroup with this.parentGroup to be compatible with other GUI elements; fixed an "out of index" bug that occasionally appeared in Opera 9 when calculating the cursor position
- 1.1 (2006-07-11): fixed a bug with the delete key (ASV only) if cursor was at the end (thanks to David Boyd), fixed another bug with delete key if cursor was at the end it accidentally deleted the first character, fixed a bug in the method .setValue() (thanks to Volker Gersabeck); added constructor parameter textYOffset, added methods .moveTo(x,y) and .resize(width)
- 1.1.1 (2006-07-13): changed the internal structure a bit. An additional group element is now created. This allows several textboxes to be placed in the same parent group. Previously this had failed. No changes in constructor parameters and methods in this release ;-) - constructors will hopefully be stable in future releases ...
- 1.1.2 (2006-10-04): added parameter fireFunction to the setValue() method in order to determine whether the associated callback function should be fired or not; introduced new "changetype" with value "set" which indicates that the textbox value was set by method "setValue"
Credits
- Olaf Schnabel (initial version)
- Volker Gersabeck (providing bugs and fixes (multinamespace issue, setValue() method))
- David Boyd (providing bugs and fixes (delete key))