changeset 389:764834d3a461

initial version of svg-edit Revision r448 and action SVG-editor
author Reimar Bauer <rb.proj AT googlemail DOT com>
date Sun, 23 Aug 2009 00:56:18 +0200
parents 9b68e1090065
children 8b7ec5e404c2
files data/plugin/action/InstallLanguage.py data/plugin/action/SVG-editor.py htdocs/svg-edit/AUTHORS htdocs/svg-edit/CHANGES htdocs/svg-edit/LICENSE htdocs/svg-edit/README htdocs/svg-edit/editor/images/align-bottom.png htdocs/svg-edit/editor/images/align-center.png htdocs/svg-edit/editor/images/align-left.png htdocs/svg-edit/editor/images/align-middle.png htdocs/svg-edit/editor/images/align-right.png htdocs/svg-edit/editor/images/align-top.png htdocs/svg-edit/editor/images/bold.png htdocs/svg-edit/editor/images/cancel.png htdocs/svg-edit/editor/images/circle.png htdocs/svg-edit/editor/images/clear.png htdocs/svg-edit/editor/images/clone.png htdocs/svg-edit/editor/images/copy.png htdocs/svg-edit/editor/images/cut.png htdocs/svg-edit/editor/images/delete.png htdocs/svg-edit/editor/images/ellipse.png htdocs/svg-edit/editor/images/flyouth.png htdocs/svg-edit/editor/images/freehand-circle.png htdocs/svg-edit/editor/images/freehand-square.png htdocs/svg-edit/editor/images/italic.png htdocs/svg-edit/editor/images/line.png htdocs/svg-edit/editor/images/logo.png htdocs/svg-edit/editor/images/logo.svg htdocs/svg-edit/editor/images/move_bottom.png htdocs/svg-edit/editor/images/move_top.png htdocs/svg-edit/editor/images/none.png htdocs/svg-edit/editor/images/open.png htdocs/svg-edit/editor/images/paste.png htdocs/svg-edit/editor/images/path.png htdocs/svg-edit/editor/images/polygon.png htdocs/svg-edit/editor/images/rect.png htdocs/svg-edit/editor/images/redo.png htdocs/svg-edit/editor/images/save.png htdocs/svg-edit/editor/images/select.png htdocs/svg-edit/editor/images/sep.png htdocs/svg-edit/editor/images/source.png htdocs/svg-edit/editor/images/square.png htdocs/svg-edit/editor/images/text.png htdocs/svg-edit/editor/images/undo.png htdocs/svg-edit/editor/jgraduate/LICENSE htdocs/svg-edit/editor/jgraduate/README htdocs/svg-edit/editor/jgraduate/css/jGraduate-0.2.0.css htdocs/svg-edit/editor/jgraduate/css/jPicker-1.0.9.css htdocs/svg-edit/editor/jgraduate/images/Bars.png htdocs/svg-edit/editor/jgraduate/images/Maps.png htdocs/svg-edit/editor/jgraduate/images/bar-opacity.png htdocs/svg-edit/editor/jgraduate/images/map-opacity.png htdocs/svg-edit/editor/jgraduate/images/mappoint.gif htdocs/svg-edit/editor/jgraduate/images/picker.gif htdocs/svg-edit/editor/jgraduate/images/preview-opacity.png htdocs/svg-edit/editor/jgraduate/images/rangearrows.gif htdocs/svg-edit/editor/jgraduate/images/rangearrows2.gif htdocs/svg-edit/editor/jgraduate/jpicker-1.0.9.min.js htdocs/svg-edit/editor/jgraduate/jquery.jgraduate.js htdocs/svg-edit/editor/jpicker/css/jPicker-1.0.9.css htdocs/svg-edit/editor/jpicker/images/Bars.png htdocs/svg-edit/editor/jpicker/images/Maps.png htdocs/svg-edit/editor/jpicker/images/bar-opacity.png htdocs/svg-edit/editor/jpicker/images/map-opacity.png htdocs/svg-edit/editor/jpicker/images/mappoint.gif htdocs/svg-edit/editor/jpicker/images/picker.gif htdocs/svg-edit/editor/jpicker/images/preview-opacity.png htdocs/svg-edit/editor/jpicker/images/rangearrows.gif htdocs/svg-edit/editor/jpicker/images/rangearrows2.gif htdocs/svg-edit/editor/jpicker/jpicker-1.0.9.js htdocs/svg-edit/editor/jpicker/jpicker-1.0.9.min.js htdocs/svg-edit/editor/jquery.js htdocs/svg-edit/editor/js-hotkeys/README.md htdocs/svg-edit/editor/js-hotkeys/jquery.hotkeys.min.js htdocs/svg-edit/editor/spinbtn/JQuerySpinBtn.css htdocs/svg-edit/editor/spinbtn/JQuerySpinBtn.js htdocs/svg-edit/editor/spinbtn/spinbtn_updn.png htdocs/svg-edit/editor/svg-editor.css htdocs/svg-edit/editor/svg-editor.html htdocs/svg-edit/editor/svg-editor.js htdocs/svg-edit/editor/svgcanvas.js htdocs/svg-edit/extras/server-save/README htdocs/svg-edit/extras/server-save/svg-editor-save.js htdocs/svg-edit/extras/server-save/svg-editor-save.php htdocs/svg-edit/wave/svg-edit.xml
diffstat 85 files changed, 9043 insertions(+), 91 deletions(-) [+]
line wrap: on
line diff
--- a/data/plugin/action/InstallLanguage.py	Fri Jul 24 19:48:31 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-# -*- coding: iso-8859-1 -*-
-"""
-    MoinMoin - InstallLanguage
-
-    The superuser gets a table of language packs dependent on the selected language
-    for installation.
-
-    @copyright: 2009 MoinMoin:ReimarBauer,
-                     MoinMoin:ThomasWaldmnann
-
-    @license: GNU GPL, see COPYING for details.
-"""
-
-from MoinMoin import i18n, packages
-from MoinMoin.i18n import strings
-i18n.strings = strings
-
-from MoinMoin.action import AttachFile
-from MoinMoin.util.dataset import TupleDataset, Column
-from MoinMoin.widget.browser import DataBrowserWidget
-
-def execute(pagename, request):
-    if not request.user or not request.user.isSuperUser():
-        return ''
-    _ = request.getText
-    fmt = request.html_formatter
-    language_setup_page = 'LanguageSetup'
-    not_translated_system_pages = 'not_translated_system_pages.zip'
-    files = AttachFile._get_files(request, language_setup_page)
-    wiki_languages = list(set([lang_file.split('_')[0] for lang_file in files]) - set(['00']))
-    wiki_languages.sort()
-
-    lang = request.values.get('language') or 'English'
-    target = request.values.get('target') or ''
-    msg = ''
-    # if target is given it tries to install the package.
-    if target:
-        dummy_pagename, dummy_target, targetpath = AttachFile._access_file(language_setup_page, request)
-        package = packages.ZipPackage(request, targetpath)
-        if package.isPackage():
-            if package.installPackage():
-                msg = package.msg
-                if not msg:
-                    msg = _("Attachment '%(filename)s' installed.") % {'filename': target}
-            else:
-                msg = _("Installation of '%(filename)s' failed.") % {'filename': target}
-        else:
-            msg = _('The file %s is not a MoinMoin package file.') % target
-
-
-    data = TupleDataset()
-    data.columns = [
-           Column('page package', label=_('page package')),
-           Column('action', label=_('install')),
-        ]
-
-    label_install = _("install")
-    for pageset_name in i18n.strings.pagesets:
-        attachment = "%s_%s.zip" % (lang, pageset_name)
-        # not_translated_system_pages are in english
-        if attachment.endswith(not_translated_system_pages):
-            attachment = 'English_not_translated_system_pages.zip'
-        install_link = ''
-        querystr = {'action': 'InstallLanguage', 'target': attachment, 'language': lang}
-        if AttachFile.exists(request, language_setup_page, attachment):
-            install_link = request.page.link_to(request, label_install, querystr=querystr)
-        data.addRow((pageset_name, install_link))
-
-    table = DataBrowserWidget(request)
-    table.setData(data)
-    page_table = ''.join(table.format(method='GET'))
-
-    fmt = request.formatter
-    lang_links = [request.page.link_to_raw(request, _lang,
-                                        querystr={'action': 'InstallLanguage',
-                                                  'language': _lang,
-                                                  'pageset': pageset_name, })
-                  for _lang in wiki_languages]
-
-    lang_selector = u''.join([fmt.paragraph(1), _("Choose:"), ' ', ' '.join(lang_links), fmt.paragraph(0)])
-
-    title = _("Install language packs for '%s'") % (lang)
-    request.theme.add_msg(msg, "info")
-    request.theme.send_title(title, page=request.page, pagename=pagename)
-    request.write(request.formatter.startContent("content"))
-    request.write(lang_selector)
-    request.write(page_table)
-    request.write(request.formatter.endContent())
-    request.theme.send_footer(pagename)
-    request.theme.send_closing_html()
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/data/plugin/action/SVG-editor.py	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,291 @@
+# -*- coding: iso-8859-1 -*-
+"""
+    MoinMoin - mathtran
+
+    This macro is used to call the mathtran parser,
+    it is just a thin wrapper around it.
+
+    @copyright: 2008-2009 by MoinMoin:ReimarBauer
+    @license: GNU GPL, see COPYING for details.
+"""
+def execute(pagename, request):
+    url = request.getQualifiedURL()
+    htdocs = "%s%s" % (request.cfg.url_prefix_static, '/svg-edit/editor')
+    
+    meta = """
+<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
+<link rel="icon" type="image/png" href="images/logo.png">
+<link rel="stylesheet" href="%(htdocs)s/jgraduate/css/jPicker-1.0.9.css" type="text/css"/>
+<link rel="stylesheet" href="%(htdocs)s/jgraduate/css/jGraduate-0.2.0.css" type="text/css"/>
+<link rel="stylesheet" href="%(htdocs)s/svg-editor.css" type="text/css"/>
+<link rel="stylesheet" href="%(htdocs)s/spinbtn/JQuerySpinBtn.css" type="text/css"/>
+<script type="text/javascript" src="%(htdocs)s/jquery.js"></script>
+<!--script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script-->
+<script type="text/javascript" src="%(htdocs)s/js-hotkeys/jquery.hotkeys.min.js"></script>
+<!--script type="text/javascript" src="%(htdocs)s/js-hotkeys/jquery.hotkeys-0.7.9.js"></script-->
+<script type="text/javascript" src="%(htdocs)s/jgraduate/jpicker-1.0.9.min.js"></script>
+<script type="text/javascript" src="%(htdocs)s/jgraduate/jquery.jgraduate.js"></script>
+<script type="text/javascript" src="%(htdocs)s/spinbtn/JQuerySpinBtn.js"></script>
+<!--script type="text/javascript" src="%(htdocs)s/spinbtn/JQuerySpinBtn.min.js"></script-->
+<!--script type="text/javascript" src="%(htdocs)s/jgraduate/jquery.jgraduate.min.js"></script-->
+<script type="text/javascript" src="%(htdocs)s/svgcanvas.js"></script>
+<!--script type="text/javascript" src="%(htdocs)s/svgcanvas.min.js"></script-->
+<script type="text/javascript" src="%(htdocs)s/svg-editor.js"></script>
+<!--script type="text/javascript" src="%(htdocs)s/svg-editor.min.js"></script--> 
+""" % {"htdocs": htdocs} 
+
+    html = """
+<div id="svg_editor">
+
+<div id="workarea">
+<style id="styleoverrides" type="text/css"></style>
+<div id="svgcanvas"></div>
+</div>
+
+<div id="logo">
+	<a href="http://svg-edit.googlecode.com/" target="_blank" title="SVG-edit Home Page">
+		<img src="%(htdocs)s/images/logo.png" width="32" height="32"/>
+	</a>
+</div>
+
+<div id="tools_top" class="tools_panel">
+	<!-- File-like buttons: New, Save, Source -->
+	<div>
+		<img class="tool_sep" src="%(htdocs)s/images/sep.png" alt="|"/>
+		<img class="tool_button" id="tool_clear" src="%(htdocs)s/images/clear.png" title="New Image [N]" alt="Clear" />
+		<img class="tool_button" id="tool_save" src="%(htdocs)s/images/save.png" title="Save Image [S]" alt="Save"/>
+		<img class="tool_button" id="tool_source" src="%(htdocs)s/images/source.png" title="Edit Source [U]" alt="Source"/>
+	</div>
+
+    <!-- History buttons -->
+	<div>
+		<img class="tool_sep" src="%(htdocs)s/images/sep.png" alt="|"/>
+		<img class="tool_button tool_button_disabled" id="tool_undo" src="%(htdocs)s/images/undo.png" title="Undo [Z]" alt="Undo" />
+		<img class="tool_button tool_button_disabled" id="tool_redo" src="%(htdocs)s/images/redo.png" title="Redo [Y]" alt="Redo"/>
+	</div>
+
+	<!-- Buttons when something a single element is selected -->
+	<div id="selected_panel">
+		<img class="tool_sep" src="%(htdocs)s/images/sep.png" alt="|"/>
+		<img class="tool_button" id="tool_clone" src="%(htdocs)s/images/copy.png" title="Clone Element [C]" alt="Copy"/>
+		<img class="tool_button" id="tool_delete" src="%(htdocs)s/images/delete.png" title="Delete Element [Delete/Backspace]" alt="Delete"/>
+		<img class="tool_button" id="tool_move_top" src="%(htdocs)s/images/move_top.png" title="Move to Top [Shift+Up]" alt="Top"/>
+		<img class="tool_button" id="tool_move_bottom" src="%(htdocs)s/images/move_bottom.png" title="Move to Bottom [Shift+Down]" alt="Bottom"/>
+		<select id="group_opacity" class="selected_tool" title="Change selected item opacity">
+			<option selected="selected" value="1">100 %%</option>
+			<option value="0.9">90 %%</option>
+			<option value="0.8">80 %%</option>
+			<option value="0.7">70 %%</option>
+			<option value="0.6">60 %%</option>
+			<option value="0.5">50 %%</option>
+			<option value="0.4">40 %%</option>
+			<option value="0.3">30 %%</option>
+			<option value="0.2">20 %%</option>
+			<option value="0.1">10 %%</option>
+		</select>
+		<span class="selected_tool">angle:</span>
+		<input id="angle" class="selected_tool" title="Change rotation angle" alt="Rotation Angle" size="2" value="0" type="text"/>
+	</div>
+
+	<!-- Buttons when something a single element is selected -->
+	<div id="multiselected_panel">
+		<img class="tool_sep" src="%(htdocs)s/images/sep.png" alt="|"/>
+		<img class="tool_button" id="tool_clone_multi" src="%(htdocs)s/images/copy.png" title="Clone Elements [C]" alt="Clone"/>
+		<img class="tool_button" id="tool_delete_multi" src="%(htdocs)s/images/delete.png" title="Delete Selected Elements [Delete/Backspace]" alt="Delete"/>
+	</div>
+
+	<div id="rect_panel">
+		<img class="tool_sep" src="%(htdocs)s/images/sep.png" alt="|"/>
+		<label class="rect_tool">x:</label>
+		<input id="rect_x" class="rect_tool attr_changer" title="Change rectangle X coordinate" alt="x" size="3"/>
+		<label class="rect_tool">y:</label>
+		<input id="rect_y" class="rect_tool attr_changer" title="Change rectangle Y coordinate" alt="y" size="3"/>
+		<label class="rect_tool">width:</label>
+		<input id="rect_w" class="rect_tool attr_changer" title="Change rectangle width" alt="width" size="3"/>
+		<label class="rect_tool">height:</label>
+		<input id="rect_h" class="rect_tool attr_changer" title="Change rectangle height" alt="height" size="3"/>
+		<label class="rect_tool">Corner Radius:</label>
+		<input id="rect_radius" size="3" value="0" class="rect_tool" type="text" title="Change Rectangle Corner Radius" alt="Corner Radius"/>
+	</div>
+
+	<div id="circle_panel">
+		<img class="tool_sep" src="%(htdocs)s/images/sep.png" alt="|"/>
+		<label class="circle_tool">cx:</label>
+		<input id="circle_cx" class="circle_tool attr_changer" title="Change circle's cx coordinate" alt="cx" size="3"/>
+		<label class="circle_tool">cy:</label>
+		<input id="circle_cy" class="circle_tool attr_changer" title="Change circle's cy coordinate" alt="cy" size="3"/>
+		<label class="circle_tool">r:</label>
+		<input id="circle_r" class="circle_tool attr_changer" title="Change circle's radius" alt="r" size="3"/>
+	</div>
+
+	<div id="ellipse_panel">
+		<img class="tool_sep" src="%(htdocs)s/images/sep.png" alt="|"/>
+		<label class="ellipse_tool">cx:</label>
+		<input id="ellipse_cx" class="ellipse_tool attr_changer" title="Change ellipse's cx coordinate" alt="cx" size="3"/>
+		<label class="ellipse_tool">cy:</label>
+		<input id="ellipse_cy" class="ellipse_tool attr_changer" title="Change ellipse's cy coordinate" alt="cy" size="3"/>
+		<label class="ellipse_tool">rx:</label>
+		<input id="ellipse_rx" class="ellipse_tool attr_changer" title="Change ellipse's x radius" alt="rx" size="3"/>
+		<label class="ellipse_tool">ry:</label>
+		<input id="ellipse_ry" class="ellipse_tool attr_changer" title="Change ellipse's y radius" alt="ry" size="3"/>
+	</div>
+
+	<div id="line_panel">
+		<img class="tool_sep" src="%(htdocs)s/images/sep.png" alt="|"/>
+		<label class="line_tool">x1:</label>
+		<input id="line_x1" class="line_tool attr_changer" title="Change line's starting x coordinate" alt="x1" size="3"/>
+		<label class="line_tool">y1:</label>
+		<input id="line_y1" class="line_tool attr_changer" title="Change line's starting y coordinate" alt="y1" size="3"/>
+		<label class="line_tool">x2:</label>
+		<input id="line_x2" class="line_tool attr_changer" title="Change line's ending x coordinate" alt="x2" size="3"/>
+		<label class="line_tool">y2:</label>
+		<input id="line_y2" class="line_tool attr_changer" title="Change line's ending y coordinate" alt="x1" size="3"/>
+	</div>
+
+	<div id="text_panel">
+		<img class="tool_sep" src="%(htdocs)s/images/sep.png" alt="|"/>
+		<label class="text_tool">x:</label>
+		<input id="text_x" class="text_tool attr_changer" title="Change text X coordinate" alt="x" size="3"/>
+		<label class="text_tool">y:</label>
+		<input id="text_y" class="text_tool attr_changer" title="Change text Y coordinate" alt="y" size="3"/>
+		<img class="tool_button" id="tool_bold" src="%(htdocs)s/images/bold.png" title="Bold Text [B]" alt="Bold"/>
+		<img class="tool_button" id="tool_italic" src="%(htdocs)s/images/italic.png" title="Italic Text [I]" alt="Italic"/>
+		<select id="font_family" class="text_tool" title="Change Font Family">
+			<option selected="selected" value="serif">serif</option>
+			<option value="sans-serif">sans-serif</option>
+			<option value="cursive">cursive</option>
+			<option value="fantasy">fantasy</option>
+			<option value="monospace">monospace</option>
+		</select>
+		<select id="font_size" class="text_tool" title="Change Font Size">
+			<option value="6pt">6pt</option>
+			<option value="8pt">8pt</option>
+			<option value="10pt">10pt</option>
+			<option selected="selected" value="12pt">12pt</option>
+			<option value="14pt">14pt</option>
+			<option value="16pt">16pt</option>
+			<option value="20pt">20pt</option>
+			<option value="24pt">24pt</option>
+			<option value="32pt">32pt</option>
+			<option value="48pt">48pt</option>
+			<option value="64pt">64pt</option>
+			<option value="72pt">72pt</option>
+			<option value="80pt">80pt</option>
+			<option value="96pt">96pt</option>
+			<option value="120pt">120pt</option>
+		</select>
+		<input id="text" class="text_tool" type="text" title="Change text contents" size="35"/>
+	</div>
+</div> <!-- tools_top -->
+
+<div id="tools_left" class="tools_panel">
+	<img class="tool_button_current" id="tool_select" src="%(htdocs)s/images/select.png" title="Select Tool [1]" alt="Select"/><br/>
+	<img class="tool_button" id="tool_path" src="%(htdocs)s/images/path.png" title="Pencil Tool [2]" alt="Pencil"/><br/>
+	<img class="tool_button" id="tool_line" src="%(htdocs)s/images/line.png" title="Line Tool [3]" alt="Line"/><br/>
+	<img class="tool_button" id="tools_rect_show" src="%(htdocs)s/images/square.png" title="Square/Rect Tool [4/Shift+4]" alt="Square"/><br/>
+	<img class="tool_button" id="tools_ellipse_show" src="%(htdocs)s/images/circle.png" title="Ellipse/Circle Tool [5/Shift+5]" alt="Circle"/><br/>
+	<img class="tool_button" id="tool_text" src="%(htdocs)s/images/text.png" title="Text Tool [6]" alt="Text"/>
+	<img class="tool_button" id="tool_poly" src="%(htdocs)s/images/polygon.png" title="Poly Tool [7]" alt="Poly"/>
+</div> <!-- tools_left -->
+
+<div id="tools_bottom" class="tools_panel">
+
+	<div id="tools_bottom_1">
+		<select id="resolution">
+			<option selected="selected">640x480</option>
+			<option>800x600</option>
+			<option>1024x768</option>
+			<option>1280x960</option>
+			<option>1600x1200</option>
+		</select>
+	</div>
+
+	<div id="tools_bottom_2">
+		<table>
+		<tr>
+			<td>fill:</td>
+			<td><div id="fill_color" class="color_block"  title="Change fill color"></div></td>
+			<td><div id="fill_opacity">100 %%</div></td>
+		</tr><tr>
+			<td>stroke:</td>
+			<td><div id="stroke_color" class="color_block" title="Change stroke color"></div></td>
+			<td><div id="stroke_opacity">100 %%</div></td>
+			<td>
+				<input id="stroke_width" title="Change stroke width" alt="Stroke Width" size="2" value="5" type="text"/>
+			</td>
+			<td>
+				<select id="stroke_style" title="Change stroke dash style">
+					<option selected="selected" value="none">---</option>
+					<option value="2,2">...</option>
+					<option value="5,5">- -</option>
+					<option value="5,2,2,2">- .</option>
+					<option value="5,2,2,2,2,2">- ..</option>
+				</select>
+			</td>
+		</tr>
+		</table>
+	</div>
+
+	<div id="tools_bottom_3">
+		<div id="palette_holder"><div id="palette" title="Click to change fill color, shift-click to change stroke color"></div></div>
+		<div id="copyright">Powered by <a href="http://svg-edit.googlecode.com/" target="_blank">SVG-edit v2.3-preAlpha</a></div>
+	</div>
+</div>
+
+<!-- hidden divs -->
+<div id="color_picker"></div>
+
+<div id="tools_rect" class="tools_flyout">
+	<div id="tool_square" class="tool_flyout_button" title="Square"></div>
+	<div id="tool_rect" class="tool_flyout_button" title="Rectangle"></div>
+	<div id="tool_fhrect" class="tool_flyout_button" title="Free-Hand Rectangle"></div>
+</div>
+
+<div id="tools_ellipse" class="tools_flyout">
+	<div id="tool_circle" class="tool_flyout_button" title="Circle"></div>
+	<div id="tool_ellipse" class="tool_flyout_button" title="Ellipse"></div>
+	<div id="tool_fhellipse" class="tool_flyout_button" title="Free-Hand Ellipse"></div>
+</div>
+
+<div id="tools_stacking" class="tools_flyout_v">
+	<div id="tool_stacktop" class="tool_flyout_button" title="Move to Top [Shift+Up]"></div>
+	<div id="tool_stackbottom" class="tool_flyout_button" title="Move to Bottom [Shift+Down]"></div>
+</div>
+
+<div id="tools_align" class="tools_flyout_v">
+	<div id="tool_aligntop" class="tool_flyout_button" title="Align to Top"></div>
+	<div id="tool_alignbottom" class="tool_flyout_button" title="Align to Bottom"></div>
+	<div id="tool_alignmiddle" class="tool_flyout_button" title="Align to Middle"></div>
+	<div id="tool_alignleft" class="tool_flyout_button" title="Align to Left"></div>
+	<div id="tool_alignright" class="tool_flyout_button" title="Align to Right"></div>
+	<div id="tool_aligncenter" class="tool_flyout_button" title="Align to Center"></div>
+</div>
+
+</div> <!-- svg_editor -->
+
+<div id="svg_source_editor">
+	<div id="svg_source_overlay"></div>
+	<div id="svg_source_container">
+		<div id="tool_source_back" class="toolbar_button"></div>
+		<form>
+			<textarea id="svg_source_textarea"></textarea>
+		</form>
+	</div>
+</div>
+
+<script type="text/javascript">
+$(document).ready(svg_edit_setup);
+</script>
+
+""" % {"htdocs": htdocs}
+
+    title = "SVG Editor"
+    request.theme.send_title(title, page=request.page, pagename=pagename)
+    request.write(request.formatter.startContent("content"))
+    request.write(request.formatter.rawHTML(meta))
+    
+    request.write(request.formatter.rawHTML(html))
+    request.write(request.formatter.endContent())
+    request.theme.send_footer(pagename)
+    request.theme.send_closing_html()
+    return None,None
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/AUTHORS	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,4 @@
+Narendra Sisodiya <narendra.sisodiya@gmail.com>
+Pavol Rusnak <rusnakp@gmail.com>
+Jeff Schiller <codedread@gmail.com>
+Vidar Hokstad <vidar.hokstad@gmail.com>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/CHANGES	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,29 @@
+2.2 - ???? ??, ????
+-------------------
+* 
+
+2.1 - June 17, 2009
+-------------------
+* tooltips added to all UI elements
+* fix flyout menus
+* ask before clearing the drawing (suggested by martin.vidner)
+* control group, fill and stroke opacity
+* fix flyouts when using color picker
+* change license from GPLv2 to Apache License v2.0
+* replaced Farbtastic with jPicker, because of the license issues
+* removed dependency on svgcanvas.svg, now created in JavaScript
+* added Select tool
+* using jQuery hosted by Google instead of local version
+* allow dragging of elements
+* save SVG file to separate tab
+* create and edit text elements
+* context panel tools
+* change rect radius, font-family, font-size
+* added keystroke shortcuts for all tools
+* move to top/bottom
+
+2.0 - June 03, 2009
+-------------------
+* rewritten SVG-edit, so now it uses OOP
+* draw ellipse, square
+* created HTML interface similar to Inkscape
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/LICENSE	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/README	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,21 @@
+SVG-edit, a web based SVG editor
+
+http://code.google.com/p/svg-edit/
+
+see AUTHORS file for authors
+
+-----
+
+SVG-edit contains code from these projects:
+
+jQuery JavaScript Library v1.3.2
+http://jquery.com/
+Copyright (c) 2009 John Resig
+
+jQuery js-Hotkeys
+http://code.google.com/p/js-hotkeys/
+Copyright (c) 2008 Tzury Bar Yochay
+
+jPicker
+http://www.digitalmagicpro.com/jPicker/
+Copyright (c) 2009 Christopher T. Tillman
Binary file htdocs/svg-edit/editor/images/align-bottom.png has changed
Binary file htdocs/svg-edit/editor/images/align-center.png has changed
Binary file htdocs/svg-edit/editor/images/align-left.png has changed
Binary file htdocs/svg-edit/editor/images/align-middle.png has changed
Binary file htdocs/svg-edit/editor/images/align-right.png has changed
Binary file htdocs/svg-edit/editor/images/align-top.png has changed
Binary file htdocs/svg-edit/editor/images/bold.png has changed
Binary file htdocs/svg-edit/editor/images/cancel.png has changed
Binary file htdocs/svg-edit/editor/images/circle.png has changed
Binary file htdocs/svg-edit/editor/images/clear.png has changed
Binary file htdocs/svg-edit/editor/images/clone.png has changed
Binary file htdocs/svg-edit/editor/images/copy.png has changed
Binary file htdocs/svg-edit/editor/images/cut.png has changed
Binary file htdocs/svg-edit/editor/images/delete.png has changed
Binary file htdocs/svg-edit/editor/images/ellipse.png has changed
Binary file htdocs/svg-edit/editor/images/flyouth.png has changed
Binary file htdocs/svg-edit/editor/images/freehand-circle.png has changed
Binary file htdocs/svg-edit/editor/images/freehand-square.png has changed
Binary file htdocs/svg-edit/editor/images/italic.png has changed
Binary file htdocs/svg-edit/editor/images/line.png has changed
Binary file htdocs/svg-edit/editor/images/logo.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/editor/images/logo.svg	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,291 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   viewBox="0 0 600 600"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   width="48"
+   height="48"
+   sodipodi:docname="logo.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   version="1.0"
+   inkscape:export-filename="logo.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90">
+  <sodipodi:namedview
+     inkscape:window-height="858"
+     inkscape:window-width="911"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     guidetolerance="10.0"
+     gridtolerance="10.0"
+     objecttolerance="10.0"
+     borderopacity="1.0"
+     bordercolor="#666666"
+     pagecolor="#ffffff"
+     id="base"
+     showgrid="false"
+     inkscape:zoom="11.352818"
+     inkscape:cx="27.728302"
+     inkscape:cy="25.018074"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:current-layer="a32" />
+  <defs
+     id="defs14280">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective71" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       id="XMLID_16_"
+       x1="67.8452"
+       x2="144.5898"
+       y1="115.5361"
+       y2="115.5361">
+      <stop
+         id="stop780"
+         offset="0"
+         stop-color="#7D7D99" />
+      <stop
+         id="stop781"
+         offset="0.1798"
+         stop-color="#B1B1C5" />
+      <stop
+         id="stop782"
+         offset="0.3727"
+         stop-color="#BCBCC8" />
+      <stop
+         id="stop783"
+         offset="0.6825"
+         stop-color="#C8C8CB" />
+      <stop
+         id="stop784"
+         offset="1"
+         stop-color="#CCC" />
+    </linearGradient>
+    <linearGradient
+       gradientTransform="matrix(-0.999,4.35e-2,4.35e-2,0.999,-1277.01,-496.517)"
+       gradientUnits="userSpaceOnUse"
+       id="XMLID_15_"
+       x1="-1401.459"
+       x2="-1354.6851"
+       y1="595.63092"
+       y2="699.47632">
+      <stop
+         id="stop770"
+         offset="0"
+         stop-color="#FFA700" />
+      <stop
+         id="stop771"
+         offset="0.7753"
+         stop-color="#FFD700" />
+      <stop
+         id="stop772"
+         offset="1"
+         stop-color="#FF9200" />
+    </linearGradient>
+    <linearGradient
+       gradientTransform="matrix(-0.999,4.35e-2,4.35e-2,0.999,-1277.01,-496.517)"
+       gradientUnits="userSpaceOnUse"
+       id="XMLID_14_"
+       x1="-1336.4497"
+       x2="-1325.3219"
+       y1="635.79492"
+       y2="622.53333">
+      <stop
+         id="stop763"
+         offset="0"
+         stop-color="#FFC957" />
+      <stop
+         id="stop764"
+         offset="1"
+         stop-color="#FF6D00" />
+    </linearGradient>
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       id="XMLID_13_"
+       x1="65.094704"
+       x2="137.6021"
+       y1="-0.79540002"
+       y2="160.1823">
+      <stop
+         id="stop750"
+         offset="0"
+         stop-color="#FFA700" />
+      <stop
+         id="stop751"
+         offset="0.7753"
+         stop-color="#FFD700" />
+      <stop
+         id="stop752"
+         offset="1"
+         stop-color="#FF794B" />
+    </linearGradient>
+    <linearGradient
+       gradientTransform="matrix(-0.999,4.35e-2,4.35e-2,0.999,-1277.01,-496.517)"
+       gradientUnits="userSpaceOnUse"
+       id="XMLID_12_"
+       x1="-1375.9844"
+       x2="-1355.0455"
+       y1="685.38092"
+       y2="706.32172">
+      <stop
+         id="stop743"
+         offset="0"
+         stop-color="#F8F1DC" />
+      <stop
+         id="stop744"
+         offset="1"
+         stop-color="#D6A84A" />
+    </linearGradient>
+    <linearGradient
+       gradientTransform="matrix(0.1991,0.98,-0.98,0.1991,91.6944,573.565)"
+       gradientUnits="userSpaceOnUse"
+       id="XMLID_11_"
+       x1="-481.70071"
+       x2="-360.24561"
+       y1="-94.419403"
+       y2="-164.22141">
+      <stop
+         id="stop736"
+         offset="0"
+         stop-color="#900" />
+      <stop
+         id="stop737"
+         offset="1"
+         stop-color="#7C0000" />
+    </linearGradient>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath4418">
+      <rect
+         height="79.958374"
+         id="rect4420"
+         stroke-miterlimit="4"
+         style="fill:none;stroke:#000000;stroke-width:0.14421287;stroke-miterlimit:4;stroke-dasharray:none"
+         transform="scale(-1,1)"
+         width="73.952118"
+         x="-196.68831"
+         y="126.58712" />
+    </clipPath>
+  </defs>
+  <metadata
+     id="metadata30">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <a
+     xlink:href="http://svg-edit.googlecode.com/"
+     xlink:title="SVG-edit, an in-browser vector graphics editor"
+     target="_blank"
+     id="a32">
+    <path
+       sodipodi:type="star"
+       style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path3216"
+       sodipodi:sides="8"
+       sodipodi:cx="239.79607"
+       sodipodi:cy="346.96844"
+       sodipodi:r1="194.03661"
+       sodipodi:r2="155.59306"
+       sodipodi:arg1="0.78539816"
+       sodipodi:arg2="1.1780972"
+       inkscape:flatsided="false"
+       inkscape:rounded="0"
+       inkscape:randomized="0"
+       d="M 377.00067,484.17304 L 299.33895,490.71769 L 239.79607,541.00505 L 180.25318,490.71769 L 102.59147,484.17305 L 96.04682,406.51133 L 45.75946,346.96845 L 96.046819,287.42556 L 102.59147,209.76385 L 180.25318,203.2192 L 239.79607,152.93184 L 299.33895,203.2192 L 377.00067,209.76384 L 383.54531,287.42556 L 433.83267,346.96844 L 383.54531,406.51133 L 377.00067,484.17304 z"
+       transform="translate(4.1586051,6.9957853)" />
+    <path
+       d="M 257.74,558.2 C 282.68,551.18 299.44,533.03 303.3,508.86 L 304.6,500.74 L 310.09,504.65 C 342.6,527.8 385.95,516.69 401.92,481.11 C 410.74,461.44 406.88,429.74 394.39,419.38 C 389.52,415.34 390.73,414.03 400.54,412.71 C 463.81,404.2 466.02,308.53 403.26,294.99 C 389.53,292.02 390.07,292.74 395.81,285.17 C 435.22,233.14 367.98,163.64 313.59,200.18 L 305.09,205.89 L 302.14,193.86 C 286.67,130.77 193.37,133.52 184.62,197.33 C 183.22,207.55 183.54,207.42 175.45,201.25 C 145.54,178.44 96.024,193.52 84.229,229.04 C 77.621,248.93 81.839,276.52 93.036,286.66 C 98.393,291.5 97.7,292.63 88.496,294.06 C 22.466,304.29 22.003,403.73 87.943,412.77 L 96.572,413.95 L 91.187,421.94 C 63.478,463.02 91.34,516.89 140.25,516.79 C 154.94,516.76 170.97,511.38 177.33,504.36 C 181.99,499.22 183.95,499.74 183.95,506.13 C 183.95,538.55 224.9,567.45 257.74,558.2 L 257.74,558.2 z M 224.97,526.08 C 211.13,516.23 207.03,494.21 216.63,481.24 C 220.49,476.01 220.78,473.32 220.78,442.14 L 220.78,408.66 L 196.55,432.83 C 177.87,451.47 172.32,458.16 172.32,462.07 C 172.32,481.92 139.36,496.53 122.68,484.07 C 99.738,466.94 105.5,432.15 132.4,425.3 C 138.8,423.67 144.87,418.74 163.57,399.95 L 186.8,376.62 L 154.85,376.63 C 124.63,376.64 122.38,376.9 113.36,381.47 C 76.809,400.02 46.091,351.65 78.652,326.81 C 88.187,319.54 106.02,319.02 115.45,325.74 C 121.2,329.85 123.45,330.1 154.18,330.1 L 186.8,330.1 L 163.79,307.04 C 147.4,290.61 139.05,283.62 134.78,282.77 C 106.14,277.04 98.685,240.4 122.56,222.71 C 139.4,210.23 172.44,224.79 172.28,244.63 C 172.25,248.57 177.44,254.67 196.02,272.54 L 219.81,295.41 L 220.34,263.32 C 220.84,233.01 220.64,230.91 216.67,225.55 C 202.3,206.11 216.23,177.52 241.09,175.46 C 267.18,173.29 284.31,199.14 272.29,222.54 C 267.54,231.79 267.31,233.68 267.3,264.18 L 267.29,296.13 L 290.36,273.12 C 306.39,257.14 313.79,248.33 314.59,244.3 C 320.55,214.53 361.13,208.27 375.2,234.95 C 385.62,254.7 375.71,276.27 353.68,281.82 C 346.89,283.53 341.33,288 322.38,307 L 299.33,330.1 L 332.92,330.1 C 363.2,330.1 367.04,329.73 371.86,326.3 C 384.69,317.16 402.12,319.56 413.39,332.03 C 438.43,359.76 402.17,402.01 371.86,380.43 C 367.04,377 363.2,376.62 332.92,376.62 L 299.33,376.62 L 322.38,399.72 C 341.33,418.73 346.89,423.2 353.68,424.91 C 390.29,434.13 386.87,485.55 349.44,488.65 C 332.45,490.06 313.81,474.97 313.81,459.8 C 313.81,458.26 303.34,446.56 290.55,433.8 L 267.29,410.6 L 267.3,442.55 C 267.31,472.77 267.57,475.02 272.15,484.03 C 287.66,514.61 252.66,545.8 224.97,526.08 L 224.97,526.08 z"
+       id="path34"
+       style="fill:#000000" />
+    <g
+       clip-path="url(#clipPath4418)"
+       transform="matrix(-4.6717475,0,0,4.6717475,1143.4575,-562.74962)"
+       id="g36">
+      <path
+         d="M 191.92,195.98 C 180.31,159.86 178.21,153.31 177.06,151.92 C 177.18,152 177.35,152.1 177.35,152.1 L 98.804,64.643 C 94.609,59.993 84.799,64.999 77.449,71.619 C 70.166,78.161 64.129,87.392 68.079,92.183 L 147.02,179.73 L 147.56,179.82 L 185.32,197.42 L 193.01,199.79 L 191.92,195.98 L 191.92,195.98 z"
+         id="path38"
+         style="opacity:0.2" />
+      <path
+         d="M 193.56,193.52 C 181.95,157.39 179.84,150.85 178.7,149.45 C 178.82,149.52 178.99,149.63 178.99,149.63 L 100.44,62.175 C 96.245,57.524 86.429,62.53 79.083,69.15 C 71.802,75.695 65.763,84.923 69.715,89.716 L 148.66,177.26 L 149.19,177.36 L 186.96,194.95 L 194.64,197.32 L 193.56,193.52 L 193.56,193.52 z"
+         id="path40"
+         style="opacity:0.2" />
+      <path
+         d="M 186.77,191.05 C 175.16,154.92 173.06,148.38 171.91,146.98 C 172.03,147.06 172.2,147.16 172.2,147.16 L 93.653,59.704 C 89.461,55.054 79.644,60.063 72.299,66.682 C 65.016,73.224 58.978,82.453 62.93,87.247 L 141.87,174.79 L 142.41,174.88 L 180.18,192.48 L 187.86,194.85 L 186.77,191.05 L 186.77,191.05 z"
+         id="path42"
+         style="opacity:0.2" />
+      <path
+         d="M 186.43,189.36 C 174.82,153.23 172.72,146.69 171.57,145.29 C 171.69,145.37 171.86,145.47 171.86,145.47 L 93.314,58.016 C 89.115,53.365 79.299,58.373 71.955,64.993 C 64.672,71.536 58.633,80.767 62.585,85.559 L 141.53,173.1 L 142.06,173.2 L 179.83,190.8 L 187.52,193.16 L 186.43,189.36 L 186.43,189.36 z"
+         id="path44"
+         style="fill:#ffffff" />
+      <path
+         d="M 186.43,189.36 C 174.82,153.23 172.72,146.69 171.57,145.29 C 171.69,145.37 171.86,145.47 171.86,145.47 L 93.314,58.016 C 89.115,53.365 79.299,58.373 71.955,64.993 C 64.672,71.536 58.633,80.767 62.585,85.559 L 141.53,173.1 L 142.06,173.2 L 179.83,190.8 L 187.52,193.16 L 186.43,189.36 L 186.43,189.36 z"
+         id="path46"
+         style="fill:url(#XMLID_11_)" />
+      <path
+         d="M 166.97,147.76 L 180.69,185.89 L 144.32,167.99 L 144.49,167.84 C 144.24,167.76 143.99,167.66 143.79,167.52 L 143.66,167.64 L 68.36,84.072 L 68.483,83.968 C 66.237,81.478 69.515,74.874 75.791,69.216 C 82.071,63.564 88.971,60.997 91.216,63.483 L 166.51,147.05 L 166.97,147.76 L 166.97,147.76 z"
+         id="path48"
+         style="fill:url(#XMLID_12_)" />
+      <path
+         d="M 148.65,170.12 C 150.73,169.75 153.29,168.64 155.9,166.98 C 157.52,165.96 159.18,164.7 160.8,163.24 C 162.26,161.94 163.54,160.57 164.64,159.23 C 166.72,156.7 167.96,154.02 168.42,151.8 L 166.97,147.76 L 166.5,147.05 L 91.707,64.028 C 92.315,66.268 90.745,69.966 87.644,73.768 C 86.51,75.157 85.203,76.557 83.699,77.909 C 82.125,79.328 80.504,80.561 78.932,81.563 C 74.439,84.434 70.304,85.491 68.384,84.049 L 68.359,84.07 L 143.66,167.64 L 143.79,167.52 C 143.99,167.66 144.24,167.76 144.49,167.84 L 144.32,167.99 L 148.65,170.12 L 148.65,170.12 z"
+         id="path50"
+         style="fill:url(#XMLID_13_)" />
+      <path
+         d="M 68.083,83.41 C 69.815,85.182 74.077,84.186 78.726,81.216 C 80.267,80.234 81.858,79.023 83.403,77.63 C 84.879,76.305 86.162,74.929 87.275,73.567 C 90.853,69.179 92.366,64.925 90.752,62.983 L 90.775,62.959 L 166.59,147.08 C 167.23,149.34 166,153.58 162.84,157.44 C 161.76,158.75 160.5,160.09 159.07,161.37 C 157.48,162.8 155.85,164.04 154.26,165.04 C 149.52,168.05 144.96,169.24 143.24,167.35 C 142.85,166.91 141.15,165.01 141.1,164.94 L 67.845,83.626 L 68.083,83.41 L 68.083,83.41 z"
+         id="path52"
+         style="fill:#ffffff" />
+      <path
+         d="M 75.79,69.215 C 82.07,63.563 88.97,60.996 91.215,63.482 L 108.18,82.31 L 109.33,108.8 L 91.355,109.58 L 68.359,84.071 L 68.482,83.967 C 66.236,81.477 69.514,74.874 75.79,69.215 L 75.79,69.215 z"
+         id="path54"
+         style="fill:#ffffff" />
+      <path
+         d="M 68.083,83.41 C 69.815,85.182 74.077,84.186 78.726,81.216 C 80.267,80.234 81.858,79.023 83.403,77.63 C 84.879,76.305 86.162,74.929 87.275,73.567 C 90.853,69.179 92.366,64.925 90.752,62.983 L 90.775,62.959 L 166.59,147.08 C 167.23,149.34 166,153.58 162.84,157.44 C 161.76,158.75 160.5,160.09 159.07,161.37 C 157.48,162.8 155.85,164.04 154.26,165.04 C 149.52,168.05 144.96,169.24 143.24,167.35 C 142.85,166.91 141.15,165.01 141.1,164.94 L 67.845,83.626 L 68.083,83.41 L 68.083,83.41 z"
+         id="path56"
+         style="fill:#ffffff" />
+      <path
+         d="M 75.79,69.215 C 82.07,63.563 88.97,60.996 91.215,63.482 L 108.18,82.31 L 109.33,108.8 L 91.355,109.58 L 68.359,84.071 L 68.482,83.967 C 66.236,81.477 69.514,74.874 75.79,69.215 L 75.79,69.215 z"
+         id="path58"
+         style="fill:url(#XMLID_14_)" />
+      <path
+         d="M 68.083,83.41 C 69.815,85.182 74.077,84.186 78.726,81.216 C 80.267,80.234 81.858,79.023 83.403,77.63 C 84.879,76.305 86.162,74.929 87.275,73.567 C 90.853,69.179 92.366,64.925 90.752,62.983 L 90.775,62.959 L 166.59,147.08 C 167.23,149.34 166,153.58 162.84,157.44 C 161.76,158.75 160.5,160.09 159.07,161.37 C 157.48,162.8 155.85,164.04 154.26,165.04 C 149.52,168.05 144.96,169.24 143.24,167.35 C 142.85,166.91 141.15,165.01 141.1,164.94 L 67.845,83.626 L 68.083,83.41 L 68.083,83.41 z"
+         id="path60"
+         style="fill:url(#XMLID_15_)" />
+      <path
+         d="M 74.357,90.713 C 74.357,90.713 80.393,90.501 85.042,87.531 C 86.584,86.548 88.174,85.338 89.719,83.945 C 91.196,82.619 92.479,81.244 93.592,79.881 C 96.52,76.292 98.061,72.793 97.641,70.574 L 90.776,62.957 L 90.753,62.981 C 92.367,64.923 90.855,69.177 87.276,73.565 C 86.163,74.927 84.88,76.303 83.404,77.628 C 81.859,79.021 80.268,80.232 78.727,81.214 C 74.079,84.185 69.817,85.181 68.084,83.408 L 67.846,83.625 L 141.1,164.94 C 141.15,165.01 142.85,166.9 143.25,167.34 C 143.59,167.72 144.05,167.97 144.59,168.11 L 74.357,90.713 L 74.357,90.713 z"
+         id="path62"
+         style="fill:url(#XMLID_16_)" />
+      <path
+         d="M 172.04,175.35 C 170.4,176.83 168.73,178.12 167.09,179.19 L 180.69,185.89 L 175.6,171.74 C 174.54,172.95 173.35,174.18 172.04,175.35 z"
+         id="path64"
+         style="fill:#003333" />
+      <path
+         d="M 163.12,157.05 L 86.968,73.93 C 87.068,73.81 87.181,73.688 87.275,73.566 C 88.703,71.814 89.795,70.076 90.5,68.508 L 166.27,151.22 C 165.72,153.04 164.67,155.08 163.12,157.05 L 163.12,157.05 z"
+         id="path66"
+         style="opacity:0.5;fill:#ffffff" />
+      <path
+         d="M 87.275,73.566 C 87.909,72.792 88.464,72.018 88.969,71.266 L 164.98,154.24 C 164.41,155.3 163.7,156.39 162.84,157.43 C 162.09,158.33 161.27,159.24 160.37,160.13 L 84.152,76.932 C 85.316,75.824 86.361,74.692 87.275,73.566 L 87.275,73.566 z"
+         id="path68"
+         style="opacity:0.5;fill:#ffffff" />
+    </g>
+  </a>
+</svg>
Binary file htdocs/svg-edit/editor/images/move_bottom.png has changed
Binary file htdocs/svg-edit/editor/images/move_top.png has changed
Binary file htdocs/svg-edit/editor/images/none.png has changed
Binary file htdocs/svg-edit/editor/images/open.png has changed
Binary file htdocs/svg-edit/editor/images/paste.png has changed
Binary file htdocs/svg-edit/editor/images/path.png has changed
Binary file htdocs/svg-edit/editor/images/polygon.png has changed
Binary file htdocs/svg-edit/editor/images/rect.png has changed
Binary file htdocs/svg-edit/editor/images/redo.png has changed
Binary file htdocs/svg-edit/editor/images/save.png has changed
Binary file htdocs/svg-edit/editor/images/select.png has changed
Binary file htdocs/svg-edit/editor/images/sep.png has changed
Binary file htdocs/svg-edit/editor/images/source.png has changed
Binary file htdocs/svg-edit/editor/images/square.png has changed
Binary file htdocs/svg-edit/editor/images/text.png has changed
Binary file htdocs/svg-edit/editor/images/undo.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/editor/jgraduate/LICENSE	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/editor/jgraduate/README	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,3 @@
+jGraduate - A jQuery plugin for picking gradients
+
+Licensed under the Apache License 2.  See LICENSE for more information.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/editor/jgraduate/css/jGraduate-0.2.0.css	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,171 @@
+/* 
+ * jGraduate Default CSS
+ * 
+ * Copyright (c) 2009 Jeff Schiller
+ *
+ * Licensed under the Apache License Version 2
+ */
+
+h2.jGraduate_Title {
+  font-family: Arial, Helvetica, Sans-Serif;
+  font-size: 11px !important;
+  font-weight: bold;
+  margin: -13px 0px 0px 0px;
+  padding: 0px;
+  text-align: center;
+}
+
+.jGraduate_Picker {
+	font-family: Arial, Helvetica, Sans-Serif;
+	font-size: 12px;
+	border-style: solid;
+	border-color: lightgrey black black lightgrey;
+	border-width: 1px;
+	background-color: #EFEFEF;
+	position: absolute;
+	padding: 10px;
+}
+
+li.jGraduate_tab_color, li.jGraduate_tab_lingrad {
+	background-color: #ccc;
+	display: inline;
+	border: solid 1px grey;
+	padding: 3px;
+	margin: 2px;
+	cursor: pointer;
+}
+
+li.jGraduate_tab_current {
+	background-color: #EFEFEF;
+	display: inline;
+	padding: 3px;
+	margin: 2px;
+	border: solid 1px black;
+	cursor: pointer;
+}
+
+.jGraduate_colPick {
+	display: none;
+}
+
+.jGraduate_lgPick {	
+	display: none;
+	border: outset 1px #666;
+	padding: 10px 7px 5px 5px;
+}
+
+.jGraduate_tabs {
+	position: relative;
+	background-color: #EFEFEF;
+	padding: 0px;
+	margin: 0px;
+	margin-bottom: 5px;
+}
+
+div.jGraduate_Swatch {
+	display: inline-block;
+	margin: 8px;
+}
+div.jGraduate_GradContainer {
+	border: 2px inset #EEE;
+	background-image: url(../images/map-opacity.png); 
+	background-position: 0px 0px;
+	height: 256px;
+}
+
+.jGraduate_AlphaArrows {
+	position: absolute;
+	margin-top: -10px;
+	margin-left: 250.5px;
+}
+
+div.jGraduate_Opacity {
+	border: 2px inset #eee;
+	margin-top: 14px;
+	background-color: black;
+	background-image: url(../images/Maps.png);
+	background-position: 0px -2816px;
+	height: 20px;
+	cursor: ew-resize;
+}
+
+div.jGraduate_OpacityField {
+	margin-top: 110px;
+	margin-left: -10px;
+}
+
+div.jGraduate_Form {
+	display: inline-block;
+	vertical-align: top;
+	width: 140px;
+	margin: -3px 3px 0px 4px;
+}
+
+div.jGraduate_StopSection {
+	width: 120px;
+	text-align: center;
+}
+
+div.jGraduate_OkCancel {
+	display: inline-block;
+	vertical-align: top;	
+	width: 113px;
+}
+
+input.jGraduate_Ok, input.jGraduate_Cancel {
+	display: block;
+	width: 100px;
+	margin-left: -4px;
+	margin-right: -4px;
+}
+input.jGraduate_Ok {
+	margin: 9px -4px 5px -4px;
+}
+
+.colorBox {
+	display: inline-block;
+	height: 16px;
+	width: 16px;
+	border: 1px solid #808080;
+	vertical-align: -7px;
+	cursor: pointer;
+	margin: 4px;
+}
+
+label.jGraduate_Form_Heading {
+	position: relative;
+	top: 10px;
+	background-color: #EFEFEF;
+	padding: 2px;
+	font-weight: bold;
+	font-size: 13px;
+}
+
+div.jGraduate_Form_Section {
+	border-style: solid;
+	border-width: 1px;
+	border-color: grey;
+	-moz-border-radius: 5px;
+	-webkit-border-radius: 5px;
+	padding: 15px 5px 5px 5px;
+	margin: 2px;
+	width: 110px;
+	text-align: center;
+}
+
+div.jGraduate_LightBox {
+	position: fixed;
+	top: 0px;
+	left: 0px;
+	right: 0px;
+	bottom: 0px;
+	background-color: #000;
+	opacity: 0.5;
+	display: none;
+}
+
+div.jGraduate_stopPicker {
+	position: absolute;
+	display: none;
+	background: #E8E8E8;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/editor/jgraduate/css/jPicker-1.0.9.css	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,227 @@
+.jPicker_Picker {
+  display: inline-block;
+  height: 24px; /* change this value if using a different sized color picker icon */
+  position: relative; /* make this element an absolute positioning container */
+  text-align: left; /* make the zero width children position to the left of container */
+  width: 25px; /* change this value if using a different sized color picker icon */
+}
+.jPicker_Color {
+  display: block;
+  height: 100%;
+  left: 0px;
+  position: absolute;
+  top: 0px;
+  width: 100%;
+}
+.jPicker_Icon {
+  background-repeat: no-repeat;
+  cursor: pointer;
+  display: block;
+  height: 100%;
+  left: 0px;
+  position: absolute;
+  top: 0px;
+  width: 100%;
+}
+.jPicker_Container {
+  display: none;
+  z-index: 10; /* make sure container draws above color picker icon in Firefox/Safari/Chrome/Opera/etc. -
+                  IE calculates z-index so this won't work - we will hide all color picker icons placed after the selected one in code when shown in IE */
+}
+.jPicker_table {
+  background-color: #efefef;
+  border: 1px outset #666;
+  font-family: Arial, Helvetica, Sans-Serif;
+  font-size: 12px;
+  height: 330px;
+  margin: 0px;
+  padding: 5px;
+  width: 550px;
+}
+.jPicker_table td {
+  margin: 0px;
+  padding: 0px;
+  vertical-align: top;
+}
+.jPicker_MoveBar {
+  background-color: #dddddd;
+  border: 1px outset #aaa;
+  cursor: move;
+  height: 12px;
+}
+.jPicker_Title {
+  font-size: 11px !important;
+  font-weight: bold;
+  margin: -2px 0px 0px 0px;
+  padding: 0px;
+  text-align: center;
+  width: 100%;
+}
+.jPicker_ColorMap {
+  border: 2px inset #eee;
+  cursor: crosshair;
+  height: 260px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 256px later */
+  margin: 0px 5px 0px 5px;
+  overflow: hidden; /* hide the overdraw of the Color Map icon when at edge of viewing box */
+  padding: 0px;
+  position: relative; /* make this element an absolute positioning container */
+  width: 260px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 256px later */
+}
+div[class="jPicker_ColorMap"] {
+  height: 256px; /* correct to 256px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */
+  width: 256px; /* correct to 256px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */
+}
+.jPicker_ColorMap_l1, .jPicker_ColorMap_l2, .jPicker_ColorMap_l3, .jPicker_ColorBar_l1, .jPicker_ColorBar_l2, .jPicker_ColorBar_l3, .jPicker_ColorBar_l4, .jPicker_ColorBar_l5, .jPicker_AlphaBar_l1, .jPicker_AlphaBar_l2 {
+  background-repeat: no-repeat;
+  display: block;
+  height: 100%;
+  left: 0px;
+  position: absolute;
+  top: 0px;
+  width: 100%;
+}
+.jPicker_ColorMap_l1 {
+  background-color: #000000;
+  background-image: none;
+}
+.jPicker_ColorMap_l2 {
+  background-color: transparent;
+}
+.jPicker_ColorMap_l3 {
+  background-repeat: repeat;
+}
+.jPicker_ColorMap_Arrow {
+  display: block;
+  position: absolute;
+}
+.jPicker_ColorBar {
+  border: 2px inset #eee;
+  cursor: n-resize;
+  height: 260px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 256px later */
+  margin: 12px 10px 0px 5px;
+  padding: 0px;
+  position: relative;
+  width: 24px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 20px later */
+}
+div[class="jPicker_ColorBar"] {
+  height: 256px; /* correct to 256px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */
+  width: 20px; /* correct to 20px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */
+}
+.jPicker_ColorBar_l1, .jPicker_ColorBar_l2, .jPicker_ColorBar_l3 {
+  background-color: transparent;
+  background-image: none;
+  background-repeat: repeat-x;
+}
+.jPicker_ColorBar_l4 {
+  background-color: transparent;
+  background-repeat: repeat-x;
+}
+.jPicker_ColorBar_l5 {
+  background-color: transparent;
+  background-repeat: repeat;
+}
+.jPicker_ColorBar_Arrow {
+  display: block;
+  left: -10px; /* (arrow width / 2) - (element width / 2) - position arrows' center in elements' center */
+  position: absolute;
+}
+.jPicker_AlphaBar {
+  border: 2px inset #eee;
+  cursor: e-resize;
+  display: none;
+  height: 24px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 20px later */
+  margin: 10px 5px 4px 5px;
+  padding: 0px;
+  position: relative;
+  width: 260px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 256px later */
+}
+div[class="jPicker_AlphaBar"] {
+  height: 20px; /* correct to 20px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */
+  width: 256px; /* correct to 256px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */
+}
+.jPicker_AlphaBar_Arrow {
+  display: block;
+  top: -10px; /* (arrow height / 2) - (element height / 2) - position arrows' center in elements' center */
+  position: absolute;
+}
+.jPicker_EnableAlpha {
+  text-align: left;
+}
+.jPicker_Preview {
+  font-size: x-small;
+  text-align: center;
+}
+.jPicker_Preview div {
+  border: 2px inset #eee;
+  height: 62px;
+  margin: 0px auto;
+  padding: 0px;
+  width: 62px;
+}
+.jPicker_Preview div span {
+  border: 1px solid #000;
+  display: block;
+  height: 30px;
+  margin: 0px auto;
+  padding: 0px;
+  width: 60px;
+}
+.jPicker_Preview div span.jPicker_Active {
+  border-bottom-width: 0px;
+}
+.jPicker_Preview div span.jPicker_Current {
+  border-top-width: 0px;
+  cursor: pointer;
+}
+.jPicker_OkCancel {
+  text-align: center;
+  width: 120px;
+}
+.jPicker_OkCancel input {
+  width: 100px;
+}
+.jPicker_OkCancel input.jPicker_Ok {
+  margin: 12px 0px 5px 0px;
+}
+.jPicker_Spacer {
+  height: 10px;
+}
+.jPicker_HueText, .jPicker_SaturationText, .jPicker_BrightnessText, .jPicker_RedText, .jPicker_GreenText, .jPicker_BlueText, .jPicker_AlphaText {
+  background-color: #fff;
+  border: 1px inset #aaa;
+  margin: 0px 0px 0px 5px;
+  width: 30px;
+}
+.jPicker_EnterHex {
+  text-align: right;
+}
+.jPicker_HexText {
+  background-color: #fff;
+  border: 1px inset #aaa;
+  margin: 0px 19px 0px 5px;
+  width: 50px;
+}
+td.jPicker_OpacityCol {
+  padding-top: 12px;
+  text-indent: -8px;
+}
+td.jPicker_OpacityCol * {
+  display: none;
+}
+td.jPicker_HexCol {
+  text-align: left;
+}
+.jPicker_Grid {
+  text-align: center;
+}
+.jPicker_QuickColor {
+  border: 1px inset #aaa;
+  cursor: pointer;
+  display: block;
+  float: left;
+  height: 12px;
+  line-height: 12px;
+  margin: 2px 3px 1px 3px;
+  padding: 0px;
+  width: 12px;
+}
\ No newline at end of file
Binary file htdocs/svg-edit/editor/jgraduate/images/Bars.png has changed
Binary file htdocs/svg-edit/editor/jgraduate/images/Maps.png has changed
Binary file htdocs/svg-edit/editor/jgraduate/images/bar-opacity.png has changed
Binary file htdocs/svg-edit/editor/jgraduate/images/map-opacity.png has changed
Binary file htdocs/svg-edit/editor/jgraduate/images/mappoint.gif has changed
Binary file htdocs/svg-edit/editor/jgraduate/images/picker.gif has changed
Binary file htdocs/svg-edit/editor/jgraduate/images/preview-opacity.png has changed
Binary file htdocs/svg-edit/editor/jgraduate/images/rangearrows.gif has changed
Binary file htdocs/svg-edit/editor/jgraduate/images/rangearrows2.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/editor/jgraduate/jpicker-1.0.9.min.js	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,1 @@
+(function(e,a){var d=function(n,k){var p=this,o=e("img",n),l=function(q){h(q);e(document).bind("mousemove",m).bind("mouseup",j);q.stopPropagation();q.preventDefault();return false;},m=function(q){h(q);q.stopPropagation();q.preventDefault();return false;},j=function(q){e(document).unbind("mouseup",j).unbind("mousemove",m);q.stopPropagation();q.preventDefault();return false;},h=function(u){var w=n.offset(),q=u.pageX-w.left-parseInt(n.css("border-left-width")),z=u.pageY-w.top-parseInt(n.css("border-top-width")),t=n.w,r=n.h,v,s;if(q<0){q=0;}else{if(q>t){q=t;}}if(z<0){z=0;}else{if(z>r){z=r;}}v=Math.floor(q/t*p.mxX);s=Math.floor(z/r*p.mxY);p.x=v;p.y=s;if(p.mxX==p.mnX){q=0;}if(p.mxY==p.mnY){z=0;}p.setArrowPosition(q,z);e.isFunction(p.valuesChanged)&&p.valuesChanged(p);};e.extend(true,p,{settings:k,x:0,y:0,mnX:0,mxX:0,mnY:100,mxY:100,valuesChanged:e.isFunction(arguments[2])&&arguments[2]||null,setPositioningVariables:function(r){var q=p.settings.map;n.w=q&&q.width||n.width();n.h=q&&q.height||n.height();p.MinX=0;p.MinY=0;p.MaxX=n.w;p.MaxY=n.h;},setArrowPositionFromValues:function(t){p.setPositioningVariables();var w=0,v=0,u=p.mnX,r=p.mxX,s=p.mnY,q=p.mxY,A=p.x,z=p.y;if(u!=r){if(A==u){w=0;}else{if(A==r){w=n.w;}else{if(u<1){r+=Math.abs(u)+1;}if(A<1){A+=1;}w=A/r*n.w;if(parseInt(w)==(r-1)){w=r;}else{w=parseInt(w);}if(u<1){w-=Math.abs(u)-1;}}}}if(s!=q){if(z==s){v=0;}else{if(z==q){v=n.h;}else{if(s<1){q+=Math.abs(s)+1;}if(z<1){z+=1;}v=z/q*n.h;if(parseInt(v)==(q-1)){v=q;}else{v=parseInt(v);}if(s<1){v-=Math.abs(s)-1;}}}}p.setArrowPosition(w,v);},setArrowPosition:function(q,v){var u=n.w,s=n.h,t=o.w,r=o.h;if(q<0){q=0;}else{if(q>u){q=u;}}if(v<0){v=0;}else{if(v>s){v=s;}}if(t>u){q=(u>>1)-(t>>1);}else{q-=t>>1;}if(r>s){v=(s>>1)-(r>>1);}else{v-=r>>1;}o.css({left:q+"px",top:v+"px"});},destroy:function(){e(document).unbind("mouseup",j).unbind("mousemove",m);n.unbind("mousedown",l);n=null;o=null;p.valuesChanged=null;}});o.src=p.settings.arrow&&p.settings.arrow.image;o.w=p.settings.arrow&&p.settings.arrow.width||o.width();o.h=p.settings.arrow&&p.settings.arrow.height||o.height();p.setPositioningVariables();n.bind("mousedown",l);p.setArrowPositionFromValues();e.isFunction(p.valuesChanged)&&p.valuesChanged(p);},b=function(n){var m=this,y=function(A){if(A.target.value==""){return;}t(A);m.setValuesFromHsv();e.isFunction(m.valuesChanged)&&m.valuesChanged(m);},s=function(A){if(A.target.value==""){return;}q(A);m.setValuesFromRgb();e.isFunction(m.valuesChanged)&&m.valuesChanged(m);},r=function(A){if(A.target.value==""){return;}l(A);w.a=A.target.value;e.isFunction(m.valuesChanged)&&m.valuesChanged(m);},v=function(A){if(A.target.value==""){m.setValuesFromRgb();}},k=function(A){if(A.target.value==""){m.setValuesFromHsv();}},o=function(A){if(A.target.value==""){u.alpha.val(100);}},z=function(A){if(A.target.value==""){return;}x(A);m.setValuesFromHex();e.isFunction(m.valuesChanged)&&m.valuesChanged(m);},j=function(A){if(A.target.value==""){m.setValuesFromHsv();}},q=function(A){if(!p(A)){return A;}u.red.val(h(u.red.val(),0,255));u.green.val(h(u.green.val(),0,255));u.blue.val(h(u.blue.val(),0,255));},l=function(A){if(!p(A)){return A;}u.alpha.val(h(u.alpha.val(),0,100));},t=function(A){if(!p(A)){return A;}u.hue.val(h(u.hue.val(),0,360));u.saturation.val(h(u.saturation.val(),0,100));u.value.val(h(u.value.val(),0,100));},x=function(A){if(!p(A)){return A;}u.hex.val(u.hex.val().replace(/[^a-fA-F0-9]/g,"0").toLowerCase().substring(0,6));},p=function(A){switch(A.keyCode){case 9:case 16:case 29:case 37:case 38:case 40:return false;case"c".charCodeAt():case"v".charCodeAt():if(A.ctrlKey){return false;}}return true;},h=function(C,B,A){if(C==""||isNaN(C)){return B;}C=parseInt(C);if(C>A){return A;}if(C<B){return B;}return C;};e.extend(true,m,{color:new f(),fields:{hue:e(".jPicker_HueText",n),saturation:e(".jPicker_SaturationText",n),value:e(".jPicker_BrightnessText",n),red:e(".jPicker_RedText",n),green:e(".jPicker_GreenText",n),blue:e(".jPicker_BlueText",n),hex:e(".jPicker_HexText",n),alpha:e(".jPicker_AlphaText",n)},valuesChanged:e.isFunction(arguments[1])&&arguments[1]||null,bindedHexKeyUp:function(A){z(A);},setValuesFromRgb:function(){w.fromRgb(u.red.val(),u.green.val(),u.blue.val());u.hex.val(w.hex);u.hue.val(w.h);u.saturation.val(w.s);u.value.val(w.v);},setValuesFromHsv:function(){w.fromHsv(u.hue.val(),u.saturation.val(),u.value.val());u.hex.val(w.hex);u.red.val(w.r);u.green.val(w.g);u.blue.val(w.b);},setValuesFromHex:function(){w.fromHex(u.hex.val());u.red.val(w.r);u.green.val(w.g);u.blue.val(w.b);u.hue.val(w.h);u.saturation.val(w.s);u.value.val(w.v);},setAlphaFromValue:function(){w.a=u.alpha.val();},destroy:function(){u.hue.add(u.saturation).add(u.value).unbind("keyup",events.hsvKeyUp).unbind("blur",v);u.red.add(u.green).add(u.blue).unbind("keyup",events.rgbKeyUp).unbind("blur",k);u.alpha.unbind("keyup",r).unbind("blur",o);u.hex.unbind("keyup",z);u=null;w=null;m.valuesChanged=null;}});var u=m.fields,w=m.color;u.hue.add(u.saturation).add(u.value).bind("keyup",y).bind("blur",v);u.red.add(u.green).add(u.blue).bind("keyup",s).bind("blur",k);u.alpha.bind("keyup",r).bind("blur",o);u.hex.bind("keyup",z).bind("blur",j);if(u.hex.val()!=""){w.fromHex(u.hex.val());m.setValuesFromHex();}};e.jPicker={List:[],Color:function(j){var h=this;e.extend(true,h,{r:0,g:0,b:0,h:0,s:0,v:0,a:100,hex:"",fromRgb:function(m,l,k){var o=this;o.r=m;o.g=l;o.b=k;var n=g.rgbToHsv(o);o.h=n.h;o.s=n.s;o.v=n.v;o.hex=g.rgbToHex(o);},fromHsv:function(m,l,k){var o=this;o.h=m;o.s=l;o.v=k;var n=g.hsvToRgb(o);o.r=n.r;o.g=n.g;o.b=n.b;o.hex=g.rgbToHex(n);},fromHex:function(k){var n=this;n.hex=k;var m=g.hexToRgb(k);n.r=m.r;n.g=m.g;n.b=m.b;var l=g.rgbToHsv(m);n.h=l.h;n.s=l.s;n.v=l.v;n.hex=g.rgbToHex(m);}});if(j){if(j.hex){h.fromHex(j.hex);}else{if(!isNaN(j.r)){h.fromRgb(j.r,j.g,j.b);}else{if(!isNaN(j.h)){h.fromHsv(j.h,j.s,j.v);}}}if(!isNaN(j.a)){h.a=j.a;}}},ColorMethods:{hexToRgb:function(l){l=this.validateHex(l);var k="00",j="00",h="00";if(l.length==6){k=l.substring(0,2);j=l.substring(2,4);h=l.substring(4,6);}else{if(l.length>4){k=l.substring(4,l.length);l=l.substring(0,4);}if(l.length>2){j=l.substring(2,l.length);l=l.substring(0,2);}if(l.length>0){h=l.substring(0,l.length);}}return{r:this.hexToInt(k),g:this.hexToInt(j),b:this.hexToInt(h)};},validateHex:function(h){h=h.toLowerCase().replace(/[^a-f0-9]/g,"0");if(h.length>6){h=h.substring(0,6);}return h;},rgbToHex:function(h){return this.intToHex(h.r)+this.intToHex(h.g)+this.intToHex(h.b);},intToHex:function(j){var h=parseInt(j).toString(16);if(h.length==1){h=("0"+h);}return h.toLowerCase();},hexToInt:function(h){return parseInt(h,16);},rgbToHsv:function(l){var o=l.r/255,n=l.g/255,j=l.b/255,k={h:0,s:0,v:0},m=0,h=0,p;if(o>=n&&o>=j){h=o;m=n>j?j:n;}else{if(n>=j&&n>=o){h=n;m=o>j?j:o;}else{h=j;m=n>o?o:n;}}k.v=h;k.s=h?(h-m)/h:0;if(!k.s){k.h=0;}else{p=h-m;if(o==h){k.h=(n-j)/p;}else{if(n==h){k.h=2+(j-o)/p;}else{k.h=4+(o-n)/p;}}k.h=parseInt(k.h*60);if(k.h<0){k.h+=360;}}k.s=parseInt(k.s*100);k.v=parseInt(k.v*100);return k;},hsvToRgb:function(n){var r={r:0,g:0,b:0},m=n.h,x=n.s,u=n.v;if(x==0){if(u==0){r.r=r.g=r.b=0;}else{r.r=r.g=r.b=parseInt(u*255/100);}}else{if(m==360){m=0;}m/=60;x=x/100;u=u/100;var l=parseInt(m),o=m-l,k=u*(1-x),j=u*(1-(x*o)),w=u*(1-(x*(1-o)));switch(l){case 0:r.r=u;r.g=w;r.b=k;break;case 1:r.r=j;r.g=u;r.b=k;break;case 2:r.r=k;r.g=u;r.b=w;break;case 3:r.r=k;r.g=j;r.b=u;break;case 4:r.r=w;r.g=k;r.b=u;break;case 5:r.r=u;r.g=k;r.b=j;break;}r.r=parseInt(r.r*255);r.g=parseInt(r.g*255);r.b=parseInt(r.b*255);}return r;}}};var f=e.jPicker.Color,c=e.jPicker.List,g=e.jPicker.ColorMethods;e.fn.jPicker=function(j){var h=arguments;return this.each(function(){var w=e(this),y=e.extend(true,{},e.fn.jPicker.defaults,j);if(w.get(0).nodeName.toLowerCase()=="input"){e.extend(true,y,{window:{bindToInput:true,expandable:true,input:w}});if(g.validateHex(w.val())){y.color.active=new f({hex:w.val(),a:y.color.active.a});y.color.current=new f({hex:w.val(),a:y.color.active.a});}}if(y.window.expandable){w.after('<span class="jPicker_Picker"><span class="jPicker_Color">&nbsp;</span><span class="jPicker_Icon" title="Click To Open Color Picker">&nbsp;</span><span class="jPicker_Container">&nbsp;</span></span>');}else{y.window.liveUpdate=false;}var W=parseFloat(navigator.appVersion.split("MSIE")[1])<7&&document.body.filters,ax=null,aw=null,av=null,U=null,T=null,S=null,R=null,Q=null,aC=null,V=null,au=null,J=null,I=null,X=null,ac=null,az=null,ak=null,am=null,ao=null,K=null,G=null,aa=null,L=null,ay=null,P=null,O=null,at=null,aq=null,A=null,l=null,M=null,ap=null,ad=null,ai=null,n=null,C=null,u=null,an=function(aE){N.active=ay.color;var aF=N.active,aG=p.clientPath,aD=function(aH){ae(aH,100);aH.css({backgroundColor:"",backgroundPosition:"0px 0px",filter:""});};aD(ax);aD(aw);aD(U);aD(T);aD(S);aD(R);ac.add(az).add(ak).add(am).add(ao).add(K).removeAttr("checked");switch(aE){case"h":ac.attr("checked",true);ax.css({backgroundColor:"#"+aF.hex});aw.css({backgroundColor:"transparent"});x(aw,-256);ae(aw,100);x(R,-256);G.mxX=100;G.mxY=100;aa.mxY=360;break;case"s":az.attr("checked",true);x(ax,-512);x(aw,-768);ae(aw,0);z(S,aF.hex);x(R,-512);G.mxX=360;G.mxY=100;aa.mxY=100;break;case"v":ak.attr("checked",true);z(ax,"000");x(aw,-1024);S.css({backgroundColor:"#"+aF.hex});x(R,-768);G.mxX=360;G.mxY=100;aa.mxY=100;break;case"r":am.attr("checked",true);x(aw,-1536);x(ax,-1280);x(R,-1024);x(S,-1280);x(T,-1536);x(U,-1792);break;case"g":ao.attr("checked",true);x(aw,-2048);x(ax,-1792);x(R,-2048);x(S,-2304);x(T,-2560);x(U,-2816);break;case"b":K.attr("checked",true);x(aw,-2560);x(ax,-2304);x(R,-3072);x(S,-3328);x(T,-3584);x(U,-3840);break;default:throw ("Invalid Mode");break;}switch(aE){case"h":case"s":case"v":G.mnX=1;G.mnY=1;aa.mnY=1;break;case"r":case"g":case"b":G.mnX=0;G.mnY=0;aa.mnY=0;G.mxX=255;G.mxY=255;aa.mxY=255;break;}N.mode=aE;v();ar();ab();if(aj.expandable&&aj.liveUpdate){n.css({backgroundColor:"#"+aF.hex});if(aj.bindToInput){aj.input.val(aF.hex).css({backgroundColor:"#"+aF.hex,color:aF.v>75?"#000000":"#ffffff"});}}e.isFunction(w.liveCallback)&&w.liveCallback(aF);},m=function(){v();ah();N.active=ay.color;var aD=N.active;if(aj.expandable&&aj.liveUpdate){n.css({backgroundColor:"#"+aD.hex});if(aj.bindToInput){aj.input.val(ay.fields.hex.val()).css({backgroundColor:"#"+aD.hex,color:aD.v>75?"#000000":"#ffffff"});}}e.isFunction(w.liveCallback)&&w.liveCallback(aD);},B=function(){if(!ay||!G||!aa||!L){return;}N.active=ay.color;var aD=ay.fields,aE=N.active;switch(N.mode){case"h":aD.saturation.val(G.x);aD.value.val(100-G.y);break;case"s":aD.hue.val(G.x);aD.value.val(100-G.y);break;case"v":aD.hue.val(G.x);aD.saturation.val(100-G.y);break;case"r":aD.blue.val(G.x);aD.green.val(255-G.y);break;case"g":aD.blue.val(G.x);aD.red.val(255-G.y);break;case"b":aD.red.val(G.x);aD.green.val(255-G.y);break;}switch(N.mode){case"h":case"s":case"v":ay.setValuesFromHsv();break;case"r":case"g":case"b":ay.setValuesFromRgb();break;}ah();if(aj.expandable&&aj.liveUpdate){n.css({backgroundColor:"#"+aE.hex});if(aj.bindToInput){aj.input.val(aE.hex).css({backgroundColor:"#"+aE.hex,color:aE.v>75?"#000000":"#ffffff"});}}e.isFunction(w.liveCallback)&&w.liveCallback(aE);},al=function(){if(!ay||!G||!aa||!L){return;}N.active=ay.color;var aD=ay.fields,aE=N.active;switch(N.mode){case"h":aD.hue.val(360-aa.y);break;case"s":aD.saturation.val(100-aa.y);break;case"v":aD.value.val(100-aa.y);break;case"r":aD.red.val(255-aa.y);break;case"g":aD.green.val(255-aa.y);break;case"b":aD.blue.val(255-aa.y);break;}switch(N.mode){case"h":case"s":case"v":ay.setValuesFromHsv();break;case"r":case"g":case"b":ay.setValuesFromRgb();break;}ah();if(aj.expandable&&aj.liveUpdate){n.css({backgroundColor:"#"+aE.hex});if(aj.bindToInput){aj.input.val(aE.hex).css({backgroundColor:"#"+aE.hex,color:aE.v>75?"#000000":"#ffffff"});}}e.isFunction(w.liveCallback)&&w.liveCallback(aE);},s=function(){if(!ay||!G||!aa||!L){return;}N.active=ay.color;var aD=ay.fields,aE=N.active;aD.alpha.val(L.x);ay.setAlphaFromValue();ah();e.isFunction(w.liveCallback)&&w.liveCallback(N.active);},v=function(){N.active=ay.color;var aG=0,aF=N.active;switch(w.settings.color.mode){case"h":aG=360-aF.h;break;case"s":aG=100-aF.s;break;case"v":aG=100-aF.v;break;case"r":aG=255-aF.r;break;case"g":aG=255-aF.g;break;case"b":aG=255-aF.b;break;}aa.y=aG;L.x=aF.a;aa.setArrowPositionFromValues();L.setArrowPositionFromValues();var aE=0,aD=0;switch(w.settings.color.mode){case"h":aE=aF.s;aD=100-aF.v;break;case"s":aE=aF.h;aD=100-aF.v;break;case"v":aE=aF.h;aD=100-aF.s;break;case"r":aE=aF.b;aD=256-aF.g;break;case"g":aE=aF.b;aD=256-aF.r;break;case"b":aE=aF.r;aD=256-aF.g;break;}G.x=aE;G.y=aD;G.setArrowPositionFromValues();},ah=function(){aB();ar();ab();aA();},aB=function(){try{A.css({backgroundColor:"#"+ay.color.hex});ae(A,ay.color.a);}catch(aD){}},ar=function(){if(!N||!ay){return;}N.active=ay.color;var aD=N.active;switch(N.mode){case"h":z(ax,new f({h:aD.h,s:100,v:100}).hex);break;case"s":ae(aw,100-aD.s);break;case"v":ae(aw,aD.v);break;case"r":ae(aw,aD.r/256*100);break;case"g":ae(aw,aD.g/256*100);break;case"b":ae(aw,aD.b/256*100);break;}ae(av,100-aD.a);},ab=function(){if(!N||!ay){return;}N.active=ay.color;var aH=N.active,aK=N.mode,aM=ay.fields;switch(aK){case"h":break;case"s":var aI=new f({h:aH.h,s:100,v:aH.v});z(S,aI.hex);break;case"v":var aL=new f({h:aH.h,s:aH.s,v:100});z(S,aL.hex);break;case"r":case"g":case"b":var aJ=0,aN=0;if(aK=="r"){aJ=aM.blue.val();aN=aM.green.val();}else{if(aK=="g"){aJ=aM.blue.val();aN=aM.red.val();}else{if(aK=="b"){aJ=aM.red.val();aN=aM.green.val();}}}var aD=aJ/256*100,aG=aN/256*100,aF=(256-aJ)/256*100,aE=(256-aN)/256*100;ae(R,aG>aF?aF:aG);ae(S,aG>aD?aD:aG);ae(T,aE>aD?aD:aE);ae(U,aE>aF?aF:aE);break;}ae(Q,100-aH.a);},aA=function(){z(J,ay.color.hex);},z=function(aD,aF){try{aD.css({backgroundColor:"#"+aF});}catch(aE){}},t=function(aD,aE){if(aE.indexOf("png")&&this.isLessThanIE7){aD.attr("pngSrc",aE);aD.css({backgroundImage:"none",filter:"progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+aE+"')"});}else{aD.css({backgroundImage:"url("+aE+")"});}},x=function(aD,aE){aD.css({backgroundPosition:"0px "+aE+"px"});},ae=function(aE,aD){if(aD<100){if(this.isLessThanIE7){var aF=aE.attr("pngSrc");if(aF!=null&&aF.indexOf("map-hue")==-1){aE.css({filter:"progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+aF+"') progid:DXImageTransform.Microsoft.Alpha(opacity="+aD+")"});}}else{aE.css({opacity:aD/100});}}else{if(aD==100){if(this.isLessThanIE7){var aF=aE.attr("pngSrc");if(aF!=null&&aF.indexOf("map-hue")==-1){aE.css({filter:"progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+aF+"')"});}}else{aE.css({opacity:""});}}}},E=function(){ay.fields.hex.val(N.current.hex);ay.fields.alpha.val(N.current.a);ay.setValuesFromHex();ay.setAlphaFromValue();e.isFunction(ay.valuesChanged)&&ay.valuesChanged(ay);},D=function(aD){an(aD.target.value);},af=function(){E();},r=function(){E();aj.expandable&&w.hide();e.isFunction(w.cancelCallback)&&w.cancelCallback();},Z=function(){var aD=N.active;N.current=new f({hex:aD.hex});N.current.a=aD.a;l.css({backgroundColor:"#"+aD.hex});ae(l,ay.color.a);if(aj.expandable){n.css({backgroundColor:"#"+aD.hex});if(aj.bindToInput){aj.input.val(aD.hex).css({backgroundColor:"#"+aD.hex,color:aD.v>75?"#000000":"#ffffff"});}}e.isFunction(w.commitCallback)&&w.commitCallback(aD);},o=function(){Z();aj.expandable&&w.hide();},ag=function(){w.show();},Y=function(aF){var aD=aj.element,aE=aj.page;P=parseInt(X.css("left"));O=parseInt(X.css("top"));at=aF.pageX;aq=aF.pageY;e(document).bind("mousemove",k).bind("mouseup",q);aF.stopPropagation();aF.preventDefault();return false;},k=function(aD){X.css({left:P-(at-aD.pageX)+"px",top:O-(aq-aD.pageY)+"px"});aD.stopPropagation();aD.preventDefault();return false;},q=function(aD){e(document).unbind("mousemove",k).unbind("mouseup",q);aD.stopPropagation();aD.preventDefault();return false;},F=function(aD){ay.fields.hex.val(w.settings.window.input.val());ay.bindedHexKeyUp(aD);},H=function(aD){ay.fields.hex.val(N.quickList[aD.data.i].hex);ay.fields.alpha.val(N.quickList[aD.data.i].a);ay.setValuesFromHex();ay.setAlphaFromValue();e.isFunction(ay.valuesChanged)&&ay.valuesChanged(ay);};e.extend(true,w,{id:w.attr("id"),settings:y,color:null,icon:null,commitCallback:e.isFunction(h[1])&&h[1]||null,liveCallback:e.isFunction(h[2])&&h[2]||null,cancelCallback:e.isFunction(h[3])&&h[3]||null,show:function(){if(document.all){var aD=false;for(i=0;i<c.length;i++){if(aD){c[i].color.add(c[i].icon).css({display:"none"});}if(c[i].id==w.id){aD=true;}}}N.current=new f({hex:N.active.hex,a:N.active.a});l.css({backgroundColor:"#"+N.active.hex});ae(l,N.active.a);X.css({display:"block"});G.setPositioningVariables();aa.setPositioningVariables();v();},hide:function(){if(document.all){var aD=false;for(i=0;i<c.length;i++){if(aD){c[i].color.add(c[i].icon).css({display:"block"});}if(c[i].id==w.id){aD=true;}}}X.css({display:"none"});},destroy:function(){if(aj.expandable){C=e(".jPicker_Icon",X).unbind("click",ag);}if(aj.bindToInput){aj.input.unbind("keyup",F).unbind("change",F);}ac.add(az).add(ak).add(am).add(ao).add(K).unbind("click",D);l.unbind("click",af);ad.unbind("click",r);ap.unbind("click",o);if(aj.expandable){u.unbind("mousedown",Y);}e(".jPicker_QuickColor",X).unbind("click",H);ac=null;az=null;ak=null;am=null;ao=null;K=null;ax=null;aw=null;av=null;U=null;T=null;S=null;R=null;Q=null;aC=null;V=null;au=null;J=null;I=null;M=null;A=null;l=null;ap=null;ad=null;ai=null;w.color=null;w.icon=null;G.destroy();G=null;aa.destroy();aa=null;L.destroy();L=null;ay.destroy();ay=null;w.commitCallback=null;w.cancelCallback=null;w.liveCallback=null;X.html("");for(i=0;i<c.length;i++){if(c[i].id==w.id){c.splice(i,1);}}}});var p=w.settings.images,aj=w.settings.window,N=w.settings.color;X=aj.expandable?e(".jPicker_Container",w.next()):w;if(aj.expandable){X.css({left:aj.position.x=="left"?"-526px":aj.position.x=="center"?"-259px":aj.position.x=="right"?"0px":aj.position.x=="screenCenter"?((e(document).width()>>1)-259)-w.next().offset().left+"px":aj.position.x,position:"absolute",top:aj.position.y=="top"?"-340px":aj.position.y=="center"?"-153px":aj.position.y=="bottom"?"25px":aj.position.y});}if((typeof(N.active)).toString().toLowerCase()=="string"){N.active=new f({hex:N.active.substring(1)});}if(!N.alphaSupport){N.active.a=100;}X.html('<table class="jPicker_table"><tbody>'+(aj.expandable?'<tr><td class="jPicker_MoveBar" colspan="6">&nbsp;</td></tr>':"")+'<tr><td rowspan="8"><h2 class="jPicker_Title">'+(aj.title||"Drag Markers To Pick A Color")+'</h2><div class="jPicker_ColorMap"><span class="jPicker_ColorMap_l1">&nbsp;</span><span class="jPicker_ColorMap_l2">&nbsp;</span><span class="jPicker_ColorMap_l3">&nbsp;</span><img src="'+p.clientPath+p.colorMap.arrow.file+'" class="jPicker_ColorMap_Arrow"/></div></td><td rowspan="8"><div class="jPicker_ColorBar"><span class="jPicker_ColorBar_l1">&nbsp;</span><span class="jPicker_ColorBar_l2">&nbsp;</span><span class="jPicker_ColorBar_l3">&nbsp;</span><span class="jPicker_ColorBar_l4">&nbsp;</span><span class="jPicker_ColorBar_l5">&nbsp;</span><img src="'+p.clientPath+p.colorBar.arrow.file+'" class="jPicker_ColorBar_Arrow"/></div></td><td colspan="3" class="jPicker_Preview">new<div class="jPicker_NewCurrent"><span class="jPicker_Active" title="New Color - Press &ldquo;OK&rdquo; To Commit">&nbsp;</span><span class="jPicker_Current" title="Click To Revert To Original Color">&nbsp;</span></div>current</td><td rowspan="9" class="jPicker_OkCancel"><input type="button" class="jPicker_Ok" value="OK" title="Commit To This Color Selection"/><input type="button" class="jPicker_Cancel" value="Cancel" title="Cancel And Revert To Original Color"/><hr/><div class="jPicker_Grid">&nbsp;</div></td></tr><tr><td><input type="radio" class="jPicker_HueRadio" id="jPicker_Hue_'+c.length+'" name="jPicker_Mode_'+c.length+'" value="h" title="Set To &ldquo;Hue&rdquo; Color Mode"/></td><td><label for="jPicker_Hue_'+c.length+'" title="Set To &ldquo;Hue&rdquo; Color Mode">H:</label></td><td><input type="text" class="jPicker_HueText" value="'+N.active.h+'" title="Enter A &ldquo;Hue&rdquo; Value (0-360&deg;)"/> &deg;</td</tr><tr><td><input type="radio" class="jPicker_SaturationRadio" id="jPicker_Saturation_'+c.length+'" name="jPicker_Mode_'+c.length+'" value="s" title="Set To &ldquo;Saturation&rdquo; Color Mode"/></td><td><label for="jPicker_Saturation_'+c.length+'" title="Set To &ldquo;Saturation&rdquo; Color Mode">S:</label></td><td><input type="text" class="jPicker_SaturationText" value="'+N.active.s+'" title="Enter A &ldquo;Saturation&rdquo; Value (0-100%)"/> %</td></tr><tr><td><input type="radio" class="jPicker_BrightnessRadio" id="jPicker_Brightness_'+c.length+'" name="jPicker_Mode_'+c.length+'" value="v" title="Set To &ldquo;Brightness&rdquo; Color Mode"/></td><td><label for="jPicker_Brightness_'+c.length+'" title="Set To &ldquo;Brightness&rdquo; Color Mode">B:</label></td><td><input type="text" class="jPicker_BrightnessText" value="'+N.active.v+'" title="Enter A &ldquo;Brightness&rdquo; Value (0-100%)"/> %</td></tr><tr><td colspan="3" class="jPicker_Spacer">&nbsp;</td></tr><tr><td><input type="radio" class="jPicker_RedRadio" id="jPicker_Red_'+c.length+'" name="jPicker_Mode_'+c.length+'" value="r" title="Set To &ldquo;Red&rdquo; Color Mode"/></td><td><label for="jPicker_Red_'+c.length+'" title="Set To &ldquo;Red&rdquo; Color Mode">R:</label></td><td><input type="text" class="jPicker_RedText" value="'+N.active.r+'" title="Enter A &ldquo;Red&rdquo; Value (0-255)"/></td></tr><tr><td><input type="radio" class="jPicker_GreenRadio" id="jPicker_Green_'+c.length+'" name="jPicker_Mode_'+c.length+'" value="g" title="Set To &ldquo;Green&rdquo; Color Mode"/></td><td><label for="jPicker_Green_'+c.length+'" title="Set To &ldquo;Green&rdquo; Color Mode">G:</label></td><td><input type="text" class="jPicker_GreenText" value="'+N.active.g+'" title="Enter A &ldquo;Green&rdquo; Value (0-255)"/></td></tr><tr><td><input type="radio" class="jPicker_BlueRadio" id="jPicker_Blue_'+c.length+'" name="jPicker_Mode_'+c.length+'" value="b" title="Set To &ldquo;Blue&rdquo; Color Mode"/></td><td><label for="jPicker_Blue_'+c.length+'" title="Set To &ldquo;Blue&rdquo; Color Mode">B:</label></td><td><input type="text" class="jPicker_BlueText" value="'+N.active.b+'" title="Enter A &ldquo;Blue&rdquo; Value (0-255)"/></td></tr><tr><td><div class="jPicker_EnableAlpha"><input type="checkbox" class="jPicker_AlphaCheckbox" id="jPicker_AlphaCheckbox_'+c.length+'" title="Enable Alpha (Transparency) Support"/><label for="jPicker_AlphaCheckbox_'+c.length+'" title="Enabled Alpha (Transparency) Support">Enable Alpha (Transparency) Support</label></div><div class="jPicker_AlphaBar"><span class="jPicker_AlphaBar_l1">&nbsp;</span><span class="jPicker_AlphaBar_l2">&nbsp;</span><img src="'+p.clientPath+p.alphaBar.arrow.file+'" class="jPicker_AlphaBar_Arrow"/></div></td><td colspan="2" class="jPicker_OpacityCol"><label for="jPicker_Alpha_'+c.length+'" title="Enter An &ldquo;Alpha&rdquo; Value (0-100%)">A:</label><input type="text" class="jPicker_AlphaText" id="jPicker_Alpha_'+c.length+'" value="'+N.active.a+'" title="Enter An &ldquo;Alpha&rdquo; Value (0-100%)"/><span>%</span></td><td colspan="3" class="jPicker_HexCol"><label for="jPicker_Hex_'+c.length+'" title="Enter A &ldquo;Hex&rdquo; Color Value (#000000-#ffffff)">#:</label><input type="text" class="jPicker_HexText" id="jPicker_Hex_'+c.length+'" value="'+N.active.hex+'" title="Enter A &ldquo;Hex&rdquo; Color Value (#000000-#ffffff)"/></td><td colspan="2" class="jPicker_EnterHex"></td><td>&nbsp;</td></tr></tbody></table>');ac=e(".jPicker_HueRadio",X);az=e(".jPicker_SaturationRadio",X);ak=e(".jPicker_BrightnessRadio",X);am=e(".jPicker_RedRadio",X);ao=e(".jPicker_GreenRadio",X);K=e(".jPicker_BlueRadio",X);ax=e(".jPicker_ColorMap_l1",X);aw=e(".jPicker_ColorMap_l2",X);av=e(".jPicker_ColorMap_l3",X);U=e(".jPicker_ColorBar_l1",X);T=e(".jPicker_ColorBar_l2",X);S=e(".jPicker_ColorBar_l3",X);R=e(".jPicker_ColorBar_l4",X);Q=e(".jPicker_ColorBar_l5",X);J=e(".jPicker_AlphaBar_l1",X);I=e(".jPicker_AlphaBar_l2",X);aC=e(".jPicker_EnableAlpha",X);V=e(".jPicker_AlphaCheckbox",X);au=e(".jPicker_AlphaBar",X);M=e(".jPicker_NewCurrent",X);A=e(".jPicker_Active",X).css({backgroundColor:"#"+N.active.hex});l=e(".jPicker_Current",X).css({backgroundColor:"#"+N.active.hex});ap=e(".jPicker_Ok",X);ad=e(".jPicker_Cancel",X);ai=e(".jPicker_Grid",X);w.color=e(".Picker_Color");w.icon=e(".jPicker_Icon");ay=new b(X,m);G=new d(e(".jPicker_ColorMap",X),{map:{width:p.colorMap.width,height:p.colorMap.height},arrow:{image:p.clientPath+p.colorMap.arrow.file,width:p.colorMap.arrow.width,height:p.colorMap.arrow.height}},B);aa=new d(e(".jPicker_ColorBar",X),{map:{width:p.colorBar.width,height:p.colorBar.height},arrow:{image:p.clientPath+p.colorBar.arrow.file,width:p.colorBar.arrow.width,height:p.colorBar.arrow.height}},al);L=new d(e(".jPicker_AlphaBar",X),{map:{width:p.alphaBar.width,height:p.alphaBar.height},arrow:{image:p.clientPath+p.alphaBar.arrow.file,width:p.alphaBar.arrow.width,height:p.alphaBar.arrow.height}},s);L.mnX=0;L.mxX=100;t(ax,p.clientPath+"Maps.png");t(aw,p.clientPath+"Maps.png");t(av,p.clientPath+"map-opacity.png");t(U,p.clientPath+"Bars.png");t(T,p.clientPath+"Bars.png");t(S,p.clientPath+"Bars.png");t(R,p.clientPath+"Bars.png");t(Q,p.clientPath+"bar-opacity.png");t(I,p.clientPath+"Maps.png");x(I,-2816);t(M,p.clientPath+"preview-opacity.png");M.css({backgroundPosition:"1px 1px"});if(N.alphaSupport){aC.hide();au.show();e("td.jPicker_OpacityCol *",X).show();}else{V.bind("click",function(){aC.hide();au.show();e("td.jPicker_OpacityCol *",X).show();});}if(aj.expandable){n=e(".jPicker_Color",w.next()).css({backgroundColor:"#"+N.active.hex});C=e(".jPicker_Icon",w.next()).css({backgroundImage:"url("+p.clientPath+p.picker.file+")"}).bind("click",ag);if(aj.bindToInput){aj.input.bind("keyup",F).bind("change",F);}}ac.add(az).add(ak).add(am).add(ao).add(K).bind("click",D);l.bind("click",af);ad.bind("click",r);ap.bind("click",o);if(aj.expandable){u=e(".jPicker_MoveBar",X).bind("mousedown",Y);}if(N.quickList&&N.quickList.length>0){ai.html("");for(i=0;i<N.quickList.length;i++){if((typeof(N.quickList[i])).toString().toLowerCase()=="string"){N.quickList[i]=new f({hex:N.quickList[i].substring(1)});}ai.append('<span class="jPicker_QuickColor" title="#'+N.quickList[i].hex+'">&nbsp;</span>');e(".jPicker_QuickColor",X).eq(i).css({backgroundColor:"#"+N.quickList[i].hex}).bind("click",{i:i},H);}}an(N.mode);ay.fields.hex.val(aa.hex);ay.setValuesFromHex();ay.setAlphaFromValue();v();ah();if(!aj.expandable){w.show();}c.push(w);});};e.fn.jPicker.defaults={window:{title:null,position:{x:"screenCenter",y:"top"},expandable:false,liveUpdate:true},color:{mode:"h",active:new f({hex:"ffc000"}),alphaSupport:false,quickList:[new f({h:360,s:33,v:100}),new f({h:360,s:66,v:100}),new f({h:360,s:100,v:100}),new f({h:360,s:100,v:75}),new f({h:360,s:100,v:50}),new f({h:180,s:0,v:100}),new f({h:30,s:33,v:100}),new f({h:30,s:66,v:100}),new f({h:30,s:100,v:100}),new f({h:30,s:100,v:75}),new f({h:30,s:100,v:50}),new f({h:180,s:0,v:90}),new f({h:60,s:33,v:100}),new f({h:60,s:66,v:100}),new f({h:60,s:100,v:100}),new f({h:60,s:100,v:75}),new f({h:60,s:100,v:50}),new f({h:180,s:0,v:80}),new f({h:90,s:33,v:100}),new f({h:90,s:66,v:100}),new f({h:90,s:100,v:100}),new f({h:90,s:100,v:75}),new f({h:90,s:100,v:50}),new f({h:180,s:0,v:70}),new f({h:120,s:33,v:100}),new f({h:120,s:66,v:100}),new f({h:120,s:100,v:100}),new f({h:120,s:100,v:75}),new f({h:120,s:100,v:50}),new f({h:180,s:0,v:60}),new f({h:150,s:33,v:100}),new f({h:150,s:66,v:100}),new f({h:150,s:100,v:100}),new f({h:150,s:100,v:75}),new f({h:150,s:100,v:50}),new f({h:180,s:0,v:50}),new f({h:180,s:33,v:100}),new f({h:180,s:66,v:100}),new f({h:180,s:100,v:100}),new f({h:180,s:100,v:75}),new f({h:180,s:100,v:50}),new f({h:180,s:0,v:40}),new f({h:210,s:33,v:100}),new f({h:210,s:66,v:100}),new f({h:210,s:100,v:100}),new f({h:210,s:100,v:75}),new f({h:210,s:100,v:50}),new f({h:180,s:0,v:30}),new f({h:240,s:33,v:100}),new f({h:240,s:66,v:100}),new f({h:240,s:100,v:100}),new f({h:240,s:100,v:75}),new f({h:240,s:100,v:50}),new f({h:180,s:0,v:20}),new f({h:270,s:33,v:100}),new f({h:270,s:66,v:100}),new f({h:270,s:100,v:100}),new f({h:270,s:100,v:75}),new f({h:270,s:100,v:50}),new f({h:180,s:0,v:10}),new f({h:300,s:33,v:100}),new f({h:300,s:66,v:100}),new f({h:300,s:100,v:100}),new f({h:300,s:100,v:75}),new f({h:300,s:100,v:50}),new f({h:180,s:0,v:0}),new f({h:330,s:33,v:100}),new f({h:330,s:66,v:100}),new f({h:330,s:100,v:100}),new f({h:330,s:100,v:75}),new f({h:330,s:100,v:50})]},images:{clientPath:"/jPicker/images/",colorMap:{width:256,height:256,arrow:{file:"mappoint.gif",width:15,height:15}},colorBar:{width:20,height:256,arrow:{file:"rangearrows.gif",width:40,height:9}},alphaBar:{width:256,height:20,arrow:{file:"rangearrows2.gif",width:9,height:40}},picker:{file:"picker.gif",width:25,height:24}}};})(jQuery,"1.0.9");
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/editor/jgraduate/jquery.jgraduate.js	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,548 @@
+/*
+ * jGraduate 0.2.x
+ *
+ * jQuery Plugin for a gradient picker
+ *
+ * Copyright (c) 2009 Jeff Schiller
+ * http://blog.codedread.com/
+ *
+ * Apache 2 License
+
+jGraduate( options, okCallback, cancelCallback )
+
+where options is an object literal:
+	{
+		window: { title: "Pick the start color and opacity for the gradient" },
+		images: { clientPath: "images/" },
+		paint: a Paint object
+	}
+ 
+- the Paint object is:
+	Paint {
+		type: String, // one of "none", "solidColor", "linearGradient", "radialGradient"
+		alpha: Number representing opacity (0-100),
+		solidColor: String representing #RRGGBB hex of color,
+		linearGradient: object of interface SVGLinearGradientElement,
+	}
+
+$.jGraduate.Paint() -> constructs a 'none' color
+$.jGraduate.Paint({copy: o}) -> creates a copy of the paint o
+$.jGraduate.Paint({hex: "#rrggbb"}) -> creates a solid color paint with hex = "#rrggbb"
+$.jGraduate.Paint({linearGradient: o, a: 50}) -> creates a linear gradient paint with opacity=0.5
+$.jGraduate.Paint({hex: "#rrggbb", linearGradient: o}) -> throws an exception?
+
+- picker accepts the following object as input:
+	{
+		okCallback: function to call when Ok is pressed
+		cancelCallback: function to call when Cancel is pressed
+		paint: object describing the paint to display initially, if not set, then default to opaque white
+	}
+
+- okCallback receives a Paint object
+
+ *
+ */
+var ns = { svg: 'http://www.w3.org/2000/svg', xlink: 'http://www.w3.org/1999/xlink' };
+if(!window.console) {
+  window.console = new function() {
+    this.log = function(str) {};
+    this.dir = function(str) {};
+  };
+}
+$.jGraduate = { 
+	Paint:
+		function(opt) {
+			var options = opt || {};
+			this.alpha = options.alpha || 100;
+			// copy paint object
+    		if (options.copy) {
+    			this.type = options.copy.type;
+    			this.alpha = options.copy.alpha;
+    			switch(this.type) {
+    				case "none":
+    					this.solidColor = null;
+    					this.linearGradient = null;
+    					break;
+    				case "solidColor":
+    					this.solidColor = options.copy.solidColor;
+    					this.linearGradient = null;
+    					break;
+    				case "linearGradient":
+    					this.solidColor = null;
+    					this.linearGradient = options.copy.linearGradient.cloneNode(true);
+    					break;
+    			}
+    		}
+    		// create linear gradient paint
+    		else if (options.linearGradient) {
+    			this.type = "linearGradient";
+    			this.solidColor = null;
+    			this.linearGradient = options.linearGradient.cloneNode(true);
+    		}
+    		// create solid color paint
+    		else if (options.solidColor) {
+    			this.type = "solidColor";
+    			this.solidColor = options.solidColor;
+    		}
+    		// create empty paint
+	    	else {
+	    		this.type = "none";
+    			this.solidColor = null;
+    			this.linearGradient = null;
+	    	}
+		}
+};
+
+jQuery.fn.jGraduateDefaults = {
+	paint: new $.jGraduate.Paint(),
+	window: {
+		pickerTitle: "Drag markers to pick a paint",
+	},
+	images: {
+		clientPath: "images/",
+	},
+};
+
+jQuery.fn.jGraduate =
+	function(options) {
+	 	var $arguments = arguments;
+		return this.each( function() {
+			var $this = $(this), $settings = $.extend(true, {}, jQuery.fn.jGraduateDefaults, options),
+				id = $this.attr('id'),
+				idref = '#'+$this.attr('id')+' ';
+			
+            if (!idref)
+            {
+              alert('Container element must have an id attribute to maintain unique id strings for sub-elements.');
+              return;
+            }
+            
+            var okClicked = function() {
+            	$.isFunction($this.okCallback) && $this.okCallback($this.paint);
+            	$this.hide();
+            },
+            cancelClicked = function() {
+            	$.isFunction($this.cancelCallback) && $this.cancelCallback();
+            	$this.hide();
+            };
+
+            $.extend(true, $this, // public properties, methods, and callbacks
+              {
+              	// make a copy of the incoming paint
+                paint: new $.jGraduate.Paint({copy: $settings.paint}),
+                okCallback: $.isFunction($arguments[1]) && $arguments[1] || null,
+                cancelCallback: $.isFunction($arguments[2]) && $arguments[2] || null,
+              });
+
+			var pos = $this.position(),
+				color = null;
+
+			if ($this.paint.type == "none") {
+				$this.paint = $.jGraduate.Paint({solidColor: 'ffffff'});
+			}
+
+            $this.addClass('jGraduate_Picker');
+            $this.html('<ul class="jGraduate_tabs">' +
+            				'<li class="jGraduate_tab_color jGraduate_tab_current">Solid Color</li>' +
+            				'<li class="jGraduate_tab_lingrad">Linear Gradient</li>' +
+            			'</ul>' +
+            			'<div class="jGraduate_colPick"></div>' +
+            			'<div class="jGraduate_lgPick"></div>');
+			var colPicker = $(idref + '> .jGraduate_colPick');
+			var lgPicker = $(idref + '> .jGraduate_lgPick');
+			
+            lgPicker.html(
+            	'<div id="' + id + '_jGraduate_Swatch" class="jGraduate_Swatch">' +
+            		'<h2 class="jGraduate_Title">' + $settings.window.pickerTitle + '</h2>' +
+            		'<div id="' + id + '_jGraduate_GradContainer" class="jGraduate_GradContainer"></div>' +
+            		'<div id="' + id + '_jGraduate_Opacity" class="jGraduate_Opacity" title="Click to set overall opacity of the gradient paint">' +
+            			'<img id="' + id + '_jGraduate_AlphaArrows" class="jGraduate_AlphaArrows" src="' + $settings.images.clientPath + 'rangearrows2.gif"></img>' +
+            		'</div>' +
+            	'</div>' + 
+            	'<div class="jGraduate_Form">' +
+            		'<div class="jGraduate_StopSection">' +
+	            		'<label class="jGraduate_Form_Heading">Begin Stop</label>' +
+    	        		'<div class="jGraduate_Form_Section">' +
+        	    			'<label>x:</label>' +
+            				'<input type="text" id="' + id + '_jGraduate_x1" size="3" title="Enter starting x value between 0.0 and 1.0"/>' +
+            				'<label> y:</label>' +
+            				'<input type="text" id="' + id + '_jGraduate_y1" size="3" title="Enter starting y value between 0.0 and 1.0"/>' +
+	        	    		'<div id="' + id + '_jGraduate_colorBoxBegin" class="colorBox"></div>' +
+		            		'<label id="' + id + '_jGraduate_beginOpacity"> 100%</label>' +
+        	   			'</div>' +
+        	   		'</div>' +
+        	   		'<div class="jGraduate_StopSection">' +
+	            		'<label class="jGraduate_Form_Heading">End Stop</label>' +
+    	        		'<div class="jGraduate_Form_Section">' +
+	    	        		'<label>x:</label>' +
+		    	        	'<input type="text" id="' + id + '_jGraduate_x2" size="3" title="Enter ending x value between 0.0 and 1.0"/>' +
+    		    	    	'<label> y:</label>' +
+        		    		'<input type="text" id="' + id + '_jGraduate_y2" size="3" title="Enter ending y value between 0.0 and 1.0"/>' +
+        	    			'<div id="' + id + '_jGraduate_colorBoxEnd" class="colorBox"></div>' +
+			            	'<label id="' + id + '_jGraduate_endOpacity">100%</label>' +
+    	    	    	'</div>' +
+    	    	    '</div>' +
+    	    	    '<div class="jGraduate_OpacityField">' +
+    	    	    	'<label class="jGraduate_OpacityLabel">A: </label>' +
+    	    	    	'<input type="text" id="' + id + '_jGraduate_OpacityInput" class="jGraduate_OpacityInput" size="3" value="100"/>%' +
+    	    	    '</div>' +
+    	       	'</div>' +
+        	    '<div class="jGraduate_OkCancel">' +
+            		'<input type="button" id="' + id + '_jGraduate_Ok" class="jGraduate_Ok" value="OK"/>' +
+            		'<input type="button" id="' + id + '_jGraduate_Cancel" class="jGraduate_Cancel" value="Cancel"/>' +
+            	'</div>' +
+            	'<div class="jGraduate_LightBox"></div>' +
+            	'<div id="' + id + '_jGraduate_stopPicker" class="jGraduate_stopPicker"></div>');
+			
+			// --------------
+            // Set up all the SVG elements (the gradient, stops and rectangle)
+            var MAX = 256, MARGINX = 0, MARGINY = 0, STOP_RADIUS = 15/2,
+            	SIZEX = MAX - 2*MARGINX, SIZEY = MAX - 2*MARGINY;
+//            var container = document.getElementById(id+'_jGraduate_Swatch');
+            var container = document.getElementById(id+'_jGraduate_GradContainer');
+            var svg = container.appendChild(document.createElementNS(ns.svg, 'svg'));
+            svg.id = id+'_jgraduate_svg';            
+            svg.setAttribute('width', MAX);
+            svg.setAttribute('height', MAX);
+			svg.setAttribute("xmlns", ns.svg);
+			
+			// if we are sent a gradient, import it 
+			if ($this.paint.type == "linearGradient") {
+				$this.paint.linearGradient.id = id+'_jgraduate_grad';
+				$this.paint.linearGradient = svg.appendChild(document.importNode($this.paint.linearGradient, true));
+			}
+			else { // we create a gradient
+				var grad = svg.appendChild(document.createElementNS(ns.svg, 'linearGradient'));
+				grad.id = id+'_jgraduate_grad';
+				grad.setAttribute('x1','0.0');
+				grad.setAttribute('y1','0.0');
+				grad.setAttribute('x2','1.0');
+				grad.setAttribute('y2','1.0');
+				
+				var begin = grad.appendChild(document.createElementNS(ns.svg, 'stop'));
+				begin.setAttribute('offset', '0.0');
+				begin.setAttribute('stop-color', '#ff0000');
+
+				var end = grad.appendChild(document.createElementNS(ns.svg, 'stop'));
+				end.setAttribute('offset', '1.0');
+				end.setAttribute('stop-color', '#ffff00');
+			
+				$this.paint.linearGradient = grad;
+			}
+
+			var gradalpha = $this.paint.alpha;
+            $('#' + id + '_jGraduate_OpacityInput').val(gradalpha);
+			var posx = parseInt(255*(gradalpha/100)) - 4.5;
+            $('#' + id + '_jGraduate_AlphaArrows').css({'margin-left':posx});
+            $('#' + id + '_jgraduate_rect').attr('fill-opacity', gradalpha/100);
+			
+			var x1 = parseFloat($this.paint.linearGradient.getAttribute('x1')||0.0);
+			var y1 = parseFloat($this.paint.linearGradient.getAttribute('y1')||0.0);
+			var x2 = parseFloat($this.paint.linearGradient.getAttribute('x2')||1.0);
+			var y2 = parseFloat($this.paint.linearGradient.getAttribute('y2')||0.0);
+			
+            var rect = document.createElementNS(ns.svg, 'rect');
+            rect.id = id + '_jgraduate_rect';
+            rect.setAttribute('x', MARGINX);
+            rect.setAttribute('y', MARGINY);
+            rect.setAttribute('width', SIZEY);
+            rect.setAttribute('height', SIZEY);
+            rect.setAttribute('fill', 'url(#'+id+'_jgraduate_grad)');
+            rect.setAttribute('fill-opacity', '1.0');
+            rect = svg.appendChild(rect);
+            
+            // stop visuals created here
+            var beginStop = document.createElementNS(ns.svg, 'image');
+            beginStop.id = id + "_stop1";
+            beginStop.setAttribute('class', 'stop');
+            beginStop.setAttributeNS(ns.xlink, 'href', $settings.images.clientPath + 'mappoint.gif');
+            beginStop.setAttributeNS(ns.xlink, "title", "Begin Stop");
+            beginStop.appendChild(document.createElementNS(ns.svg, 'title')).appendChild(
+            	document.createTextNode("Begin Stop"));
+            beginStop.setAttribute('width', 18);
+            beginStop.setAttribute('height', 18);
+            beginStop.setAttribute('x', MARGINX + SIZEX*x1 - STOP_RADIUS);
+            beginStop.setAttribute('y', MARGINY + SIZEY*y1 - STOP_RADIUS);
+            beginStop.setAttribute('cursor', 'move');
+            // must append only after setting all attributes due to Webkit Bug 27952
+            // https://bugs.webkit.org/show_bug.cgi?id=27592
+            beginStop = svg.appendChild(beginStop);
+            
+            var endStop = document.createElementNS(ns.svg, 'image');
+            endStop.id = id + "_stop2";
+            endStop.setAttribute('class', 'stop');
+            endStop.setAttributeNS(ns.xlink, 'href', $settings.images.clientPath + 'mappoint.gif');
+            endStop.setAttributeNS(ns.xlink, "title", "End Stop");
+            endStop.appendChild(document.createElementNS(ns.svg, 'title')).appendChild(
+            	document.createTextNode("End Stop"));
+            endStop.setAttribute('width', 18);
+            endStop.setAttribute('height', 18);
+            endStop.setAttribute('x', MARGINX + SIZEX*x2 - STOP_RADIUS);
+            endStop.setAttribute('y', MARGINY + SIZEY*y2 - STOP_RADIUS);
+            endStop.setAttribute('cursor', 'move');
+            endStop = svg.appendChild(endStop);
+            
+            // bind GUI elements
+            $('#'+id+'_jGraduate_Ok').bind('click', function() {
+            	$this.paint.type = "linearGradient";
+				$this.paint.solidColor = null;
+            	okClicked();
+            });
+            $('#'+id+'_jGraduate_Cancel').bind('click', function(paint) {
+            	cancelClicked();
+            });
+            
+            var x1 = $this.paint.linearGradient.getAttribute('x1');
+            if(!x1) x1 = "0.0";
+            x1Input = $('#'+id+'_jGraduate_x1');
+            x1Input.val(x1);
+            x1Input.change( function() {
+            	if (isNaN(parseFloat(this.value)) || this.value < 0.0 || this.value > 1.0) { 
+            		this.value = 0.0; 
+            	}
+            	$this.paint.linearGradient.setAttribute('x1', this.value);
+            	beginStop.setAttribute('x', MARGINX + SIZEX*this.value - STOP_RADIUS);
+            });
+
+            var y1 = $this.paint.linearGradient.getAttribute('y1');
+            if(!y1) y1 = "0.0";
+            y1Input = $('#'+id+'_jGraduate_y1');
+            y1Input.val(y1);
+            y1Input.change( function() {
+            	if (isNaN(parseFloat(this.value)) || this.value < 0.0 || this.value > 1.0) { 
+            		this.value = 0.0; 
+            	}
+            	$this.paint.linearGradient.setAttribute('y1', this.value);
+            	beginStop.setAttribute('y', MARGINY + SIZEY*this.value - STOP_RADIUS);
+            });
+            
+            var x2 = $this.paint.linearGradient.getAttribute('x2');
+            if(!x2) x2 = "1.0";
+            x2Input = $('#'+id+'_jGraduate_x2');
+            x2Input.val(x2);
+            x2Input.change( function() {
+            	if (isNaN(parseFloat(this.value)) || this.value < 0.0 || this.value > 1.0) { 
+            		this.value = 1.0;
+            	}
+            	$this.paint.linearGradient.setAttribute('x2', this.value);
+            	endStop.setAttribute('x', MARGINX + SIZEX*this.value - STOP_RADIUS);
+            });
+            
+            var y2 = $this.paint.linearGradient.getAttribute('y2');
+            if(!y2) y2 = "0.0";
+            y2Input = $('#'+id+'_jGraduate_y2');
+            y2Input.val(y2);
+            y2Input.change( function() {
+            	if (isNaN(parseFloat(this.value)) || this.value < 0.0 || this.value > 1.0) { 
+            		this.value = 0.0;
+            	}
+            	$this.paint.linearGradient.setAttribute('y2', this.value);
+            	endStop.setAttribute('y', MARGINY + SIZEY*this.value - STOP_RADIUS);
+            });            
+            
+            var stops = $this.paint.linearGradient.getElementsByTagNameNS(ns.svg, 'stop');
+            var numstops = stops.length;
+            // if there are not at least two stops, then 
+            if (numstops < 2) {
+	            while (numstops < 2) {
+    	        	$this.paint.linearGradient.appendChild( document.createElementNS(ns.svg, 'stop') );
+        	    	++numstops;
+            	}
+            	stops = $this.paint.linearGradient.getElementsByTagNameNS(ns.svg, 'stop');
+            }
+            
+            var setOpacitySlider = function(e, div) {
+            	var offset = div.offset();
+            	var x = (e.pageX - offset.left - parseInt(div.css('border-left-width')));
+            	if (x > 255) x = 255;
+            	if (x < 0) x = 0;
+            	var posx = x - 4.5;
+            	x /= 255;
+            	$('#' + id + '_jGraduate_AlphaArrows').css({'margin-left':posx});
+            	$('#' + id + '_jgraduate_rect').attr('fill-opacity', x);
+            	x = parseInt(x*100);
+            	$('#' + id + '_jGraduate_OpacityInput').val(x);
+            	$this.paint.alpha = x;
+            };
+            
+            // handle dragging on the opacity slider
+            var bSlidingOpacity = false;
+            $('.jGraduate_Opacity').mousedown(function(evt) {
+            	setOpacitySlider(evt, $(this));
+            	bSlidingOpacity = true;
+            	evt.preventDefault();
+            });
+            $('.jGraduate_Opacity').mousemove(function(evt) {
+            	if (bSlidingOpacity) {
+            		setOpacitySlider(evt, $(this));
+            		evt.preventDefault();
+            	}
+            });
+            $('.jGraduate_Opacity').mouseup(function(evt) {
+            	setOpacitySlider(evt, $(this));
+            	bSlidingOpacity = false;
+            	evt.preventDefault();
+            });
+            
+			// handle dragging the stop around the swatch
+            var draggingStop = null;
+            var startx = -1, starty = -1;
+            // for whatever reason, Opera does not allow $('image.stop') here
+            $('.stop').mousedown(function(evt) {
+            	draggingStop = this;
+            	startx = evt.clientX;
+            	starty = evt.clientY;
+            	evt.preventDefault();
+            });
+            $('#'+id+'_jgraduate_svg').mousemove(function(evt) {
+            	if (null != draggingStop) {
+            		var dx = evt.clientX - startx;
+            		var dy = evt.clientY - starty;
+            		startx += dx;
+            		starty += dy;
+            		var x = parseFloat(draggingStop.getAttribute('x')) + dx;
+            		var y = parseFloat(draggingStop.getAttribute('y')) + dy;
+
+					// clamp stop to the swatch
+            		if (x < MARGINX - STOP_RADIUS) x = MARGINX - STOP_RADIUS;
+            		if (y < MARGINY - STOP_RADIUS) y = MARGINY - STOP_RADIUS;
+            		if (x > MARGINX + SIZEX - STOP_RADIUS) x = MARGINX + SIZEX - STOP_RADIUS;
+            		if (y > MARGINY + SIZEY - STOP_RADIUS) y = MARGINY + SIZEY - STOP_RADIUS;
+            		            		
+            		draggingStop.setAttribute('x', x);
+            		draggingStop.setAttribute('y', y);
+
+					// calculate stop offset            		
+            		var fracx = (x - MARGINX + STOP_RADIUS)/SIZEX;
+            		var fracy = (y - MARGINY + STOP_RADIUS)/SIZEY;
+            		
+            		if (draggingStop.id == (id+'_stop1')) {
+            			x1Input.val(fracx);
+            			y1Input.val(fracy);
+            			$this.paint.linearGradient.setAttribute('x1', fracx);
+            			$this.paint.linearGradient.setAttribute('y1', fracy);
+            		}
+            		else {
+            			x2Input.val(fracx);
+            			y2Input.val(fracy);
+            			$this.paint.linearGradient.setAttribute('x2', fracx);
+            			$this.paint.linearGradient.setAttribute('y2', fracy);
+            		}
+            		
+            		evt.preventDefault();
+            	}
+            });
+            $('#'+id+'_jgraduate_svg').mouseup(function(evt) {
+            	draggingStop = null;
+            });
+            
+            var beginColor = stops[0].getAttribute('stop-color');
+            if(!beginColor) beginColor = '#000';
+            beginColorBox = $('#'+id+'_jGraduate_colorBoxBegin');
+            beginColorBox.css({'background-color':beginColor});
+
+            var beginOpacity = stops[0].getAttribute('stop-opacity');
+            if(!beginOpacity) beginOpacity = '1.0';
+            $('#'+id+'jGraduate_beginOpacity').html( (beginOpacity*100)+'%' );
+
+            var endColor = stops[stops.length-1].getAttribute('stop-color');
+            if(!endColor) endColor = '#000';
+            endColorBox = $('#'+id+'_jGraduate_colorBoxEnd');
+            endColorBox.css({'background-color':endColor});
+
+            var endOpacity = stops[stops.length-1].getAttribute('stop-opacity');
+            if(!endOpacity) endOpacity = '1.0';
+            $('#'+id+'jGraduate_endOpacity').html( (endOpacity*100)+'%' );
+            
+			$('#'+id+'_jGraduate_colorBoxBegin').click(function() {
+				$('div.jGraduate_LightBox').show();			
+				var colorbox = $(this);
+				color = new $.jPicker.Color({ hex: beginColor.substr(1), a:(parseFloat(beginOpacity)*100) });
+				$('#'+id+'_jGraduate_stopPicker').css({'left': 100, 'bottom': 15}).jPicker({
+						window: { title: "Pick the start color and opacity for the gradient" },
+						images: { clientPath: $settings.images.clientPath },
+						color: { active: color, alphaSupport: true }
+					}, function(color){
+						beginColor = '#' + this.settings.color.active.hex;
+						beginOpacity = this.settings.color.active.a/100;
+						colorbox.css('background', beginColor);
+						$('#'+id+'_jGraduate_beginOpacity').html(parseInt(beginOpacity*100)+'%');
+            			stops[0].setAttribute('stop-color', beginColor);
+						stops[0].setAttribute('stop-opacity', beginOpacity);
+						$('div.jGraduate_LightBox').hide();
+						$('#'+id+'_jGraduate_stopPicker').hide();
+					}, null, function() {
+						$('div.jGraduate_LightBox').hide();
+						$('#'+id+'_jGraduate_stopPicker').hide();
+					});
+			});
+			$('#'+id+'_jGraduate_colorBoxEnd').click(function() {
+				$('div.jGraduate_LightBox').show();
+				var colorbox = $(this);
+				color = new $.jPicker.Color({ hex: endColor.substr(1), a:(parseFloat(endOpacity)*100) });
+				$('#'+id+'_jGraduate_stopPicker').css({'left': 100, 'top': 15}).jPicker({
+						window: { title: "Pick the end color and opacity for the gradient" },
+						images: { clientPath: $settings.images.clientPath },
+						color: { active: color, alphaSupport: true }
+					}, function(color){
+						endColor = '#' + this.settings.color.active.hex;
+						endOpacity = this.settings.color.active.a/100;
+						colorbox.css('background', endColor);
+						$('#'+id+'_jGraduate_endOpacity').html(parseInt(endOpacity*100)+'%');
+            			stops[1].setAttribute('stop-color', endColor);
+						stops[1].setAttribute('stop-opacity', endOpacity);
+						$('div.jGraduate_LightBox').hide();
+						$('#'+id+'_jGraduate_stopPicker').hide();
+					}, null, function() {
+						$('div.jGraduate_LightBox').hide();
+						$('#'+id+'_jGraduate_stopPicker').hide();
+					});
+			});            
+            
+			// --------------
+			colPicker.jPicker(
+				{
+					window: { title: $settings.window.pickerTitle },
+					images: { clientPath: $settings.images.clientPath },
+					color: { active: new $.jPicker.Color({hex:$this.paint.solidColor, a:$this.paint.alpha}), alphaSupport: true }
+				},
+				function(color) {
+					$this.paint.type = "solidColor";
+					$this.paint.alpha = color.a;
+					$this.paint.solidColor = color.hex;
+					$this.paint.linearGradient = null;
+					okClicked(); 
+				},
+				null,
+				function(){ cancelClicked(); }
+				);
+				
+			$(idref + ' .jGraduate_tab_color').click( function(){
+				$(idref + ' .jGraduate_tab_lingrad').removeClass('jGraduate_tab_current');
+				$(idref + ' .jGraduate_tab_color').addClass('jGraduate_tab_current');
+				lgPicker.hide();
+				colPicker.show();
+			});
+			$(idref + ' .jGraduate_tab_lingrad').click( function(){
+				$(idref + ' .jGraduate_tab_color').removeClass('jGraduate_tab_current');
+				$(idref + ' .jGraduate_tab_lingrad').addClass('jGraduate_tab_current');
+				colPicker.hide();
+				lgPicker.show();
+			});
+			
+			if ($this.paint.type == "linearGradient") {
+				lgPicker.show();
+				colPicker.hide();
+				$(idref + ' .jGraduate_tab_color').removeClass('jGraduate_tab_current');
+				$(idref + ' .jGraduate_tab_lingrad').addClass('jGraduate_tab_current');				
+			}
+			else {
+				colPicker.show();
+				lgPicker.hide();
+				$(idref + ' .jGraduate_tab_color').addClass('jGraduate_tab_current');
+				$(idref + ' .jGraduate_tab_lingrad').removeClass('jGraduate_tab_current');				
+			}
+
+			$this.show();
+		});
+	};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/editor/jpicker/css/jPicker-1.0.9.css	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,227 @@
+.jPicker_Picker {
+  display: inline-block;
+  height: 24px; /* change this value if using a different sized color picker icon */
+  position: relative; /* make this element an absolute positioning container */
+  text-align: left; /* make the zero width children position to the left of container */
+  width: 25px; /* change this value if using a different sized color picker icon */
+}
+.jPicker_Color {
+  display: block;
+  height: 100%;
+  left: 0px;
+  position: absolute;
+  top: 0px;
+  width: 100%;
+}
+.jPicker_Icon {
+  background-repeat: no-repeat;
+  cursor: pointer;
+  display: block;
+  height: 100%;
+  left: 0px;
+  position: absolute;
+  top: 0px;
+  width: 100%;
+}
+.jPicker_Container {
+  display: none;
+  z-index: 10; /* make sure container draws above color picker icon in Firefox/Safari/Chrome/Opera/etc. -
+                  IE calculates z-index so this won't work - we will hide all color picker icons placed after the selected one in code when shown in IE */
+}
+.jPicker_table {
+  background-color: #efefef;
+  border: 1px outset #666;
+  font-family: Arial, Helvetica, Sans-Serif;
+  font-size: 12px;
+  height: 330px;
+  margin: 0px;
+  padding: 5px;
+  width: 550px;
+}
+.jPicker_table td {
+  margin: 0px;
+  padding: 0px;
+  vertical-align: top;
+}
+.jPicker_MoveBar {
+  background-color: #dddddd;
+  border: 1px outset #aaa;
+  cursor: move;
+  height: 12px;
+}
+.jPicker_Title {
+  font-size: 11px !important;
+  font-weight: bold;
+  margin: -2px 0px 0px 0px;
+  padding: 0px;
+  text-align: center;
+  width: 100%;
+}
+.jPicker_ColorMap {
+  border: 2px inset #eee;
+  cursor: crosshair;
+  height: 260px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 256px later */
+  margin: 0px 5px 0px 5px;
+  overflow: hidden; /* hide the overdraw of the Color Map icon when at edge of viewing box */
+  padding: 0px;
+  position: relative; /* make this element an absolute positioning container */
+  width: 260px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 256px later */
+}
+div[class="jPicker_ColorMap"] {
+  height: 256px; /* correct to 256px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */
+  width: 256px; /* correct to 256px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */
+}
+.jPicker_ColorMap_l1, .jPicker_ColorMap_l2, .jPicker_ColorMap_l3, .jPicker_ColorBar_l1, .jPicker_ColorBar_l2, .jPicker_ColorBar_l3, .jPicker_ColorBar_l4, .jPicker_ColorBar_l5, .jPicker_AlphaBar_l1, .jPicker_AlphaBar_l2 {
+  background-repeat: no-repeat;
+  display: block;
+  height: 100%;
+  left: 0px;
+  position: absolute;
+  top: 0px;
+  width: 100%;
+}
+.jPicker_ColorMap_l1 {
+  background-color: #000000;
+  background-image: none;
+}
+.jPicker_ColorMap_l2 {
+  background-color: transparent;
+}
+.jPicker_ColorMap_l3 {
+  background-repeat: repeat;
+}
+.jPicker_ColorMap_Arrow {
+  display: block;
+  position: absolute;
+}
+.jPicker_ColorBar {
+  border: 2px inset #eee;
+  cursor: n-resize;
+  height: 260px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 256px later */
+  margin: 12px 10px 0px 5px;
+  padding: 0px;
+  position: relative;
+  width: 24px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 20px later */
+}
+div[class="jPicker_ColorBar"] {
+  height: 256px; /* correct to 256px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */
+  width: 20px; /* correct to 20px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */
+}
+.jPicker_ColorBar_l1, .jPicker_ColorBar_l2, .jPicker_ColorBar_l3 {
+  background-color: transparent;
+  background-image: none;
+  background-repeat: repeat-x;
+}
+.jPicker_ColorBar_l4 {
+  background-color: transparent;
+  background-repeat: repeat-x;
+}
+.jPicker_ColorBar_l5 {
+  background-color: transparent;
+  background-repeat: repeat;
+}
+.jPicker_ColorBar_Arrow {
+  display: block;
+  left: -10px; /* (arrow width / 2) - (element width / 2) - position arrows' center in elements' center */
+  position: absolute;
+}
+.jPicker_AlphaBar {
+  border: 2px inset #eee;
+  cursor: e-resize;
+  display: none;
+  height: 24px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 20px later */
+  margin: 10px 5px 4px 5px;
+  padding: 0px;
+  position: relative;
+  width: 260px; /* IE 6 incorrectly draws border inside the width and height instead of outside - We will fix this to 256px later */
+}
+div[class="jPicker_AlphaBar"] {
+  height: 20px; /* correct to 20px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */
+  width: 256px; /* correct to 256px for browsers that support the "[class="xxx"]" selector (IE7+,Firefox,Safari,Chrome,Opera,etc.) */
+}
+.jPicker_AlphaBar_Arrow {
+  display: block;
+  top: -10px; /* (arrow height / 2) - (element height / 2) - position arrows' center in elements' center */
+  position: absolute;
+}
+.jPicker_EnableAlpha {
+  text-align: left;
+}
+.jPicker_Preview {
+  font-size: x-small;
+  text-align: center;
+}
+.jPicker_Preview div {
+  border: 2px inset #eee;
+  height: 62px;
+  margin: 0px auto;
+  padding: 0px;
+  width: 62px;
+}
+.jPicker_Preview div span {
+  border: 1px solid #000;
+  display: block;
+  height: 30px;
+  margin: 0px auto;
+  padding: 0px;
+  width: 60px;
+}
+.jPicker_Preview div span.jPicker_Active {
+  border-bottom-width: 0px;
+}
+.jPicker_Preview div span.jPicker_Current {
+  border-top-width: 0px;
+  cursor: pointer;
+}
+.jPicker_OkCancel {
+  text-align: center;
+  width: 120px;
+}
+.jPicker_OkCancel input {
+  width: 100px;
+}
+.jPicker_OkCancel input.jPicker_Ok {
+  margin: 12px 0px 5px 0px;
+}
+.jPicker_Spacer {
+  height: 10px;
+}
+.jPicker_HueText, .jPicker_SaturationText, .jPicker_BrightnessText, .jPicker_RedText, .jPicker_GreenText, .jPicker_BlueText, .jPicker_AlphaText {
+  background-color: #fff;
+  border: 1px inset #aaa;
+  margin: 0px 0px 0px 5px;
+  width: 30px;
+}
+.jPicker_EnterHex {
+  text-align: right;
+}
+.jPicker_HexText {
+  background-color: #fff;
+  border: 1px inset #aaa;
+  margin: 0px 19px 0px 5px;
+  width: 50px;
+}
+td.jPicker_OpacityCol {
+  padding-top: 12px;
+  text-indent: -8px;
+}
+td.jPicker_OpacityCol * {
+  display: none;
+}
+td.jPicker_HexCol {
+  text-align: left;
+}
+.jPicker_Grid {
+  text-align: center;
+}
+.jPicker_QuickColor {
+  border: 1px inset #aaa;
+  cursor: pointer;
+  display: block;
+  float: left;
+  height: 12px;
+  line-height: 12px;
+  margin: 2px 3px 1px 3px;
+  padding: 0px;
+  width: 12px;
+}
\ No newline at end of file
Binary file htdocs/svg-edit/editor/jpicker/images/Bars.png has changed
Binary file htdocs/svg-edit/editor/jpicker/images/Maps.png has changed
Binary file htdocs/svg-edit/editor/jpicker/images/bar-opacity.png has changed
Binary file htdocs/svg-edit/editor/jpicker/images/map-opacity.png has changed
Binary file htdocs/svg-edit/editor/jpicker/images/mappoint.gif has changed
Binary file htdocs/svg-edit/editor/jpicker/images/picker.gif has changed
Binary file htdocs/svg-edit/editor/jpicker/images/preview-opacity.png has changed
Binary file htdocs/svg-edit/editor/jpicker/images/rangearrows.gif has changed
Binary file htdocs/svg-edit/editor/jpicker/images/rangearrows2.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/editor/jpicker/jpicker-1.0.9.js	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,1675 @@
+/*
+ * jPicker 1.0.9
+ *
+ * jQuery Plugin for Photoshop style color picker
+ *
+ * Copyright (c) 2009 Christopher T. Tillman
+ * Digital Magic Productions, Inc. (http://www.digitalmagicpro.com/)
+ * MIT style license, FREE to use, alter, copy, sell, and especially ENHANCE
+ *
+ * Painstakingly ported from John Dyers' excellent work on his own color picker based on the Prototype framework.
+ *
+ * John Dyers' website: (http://johndyer.name)
+ * Color Picker page:   (http://johndyer.name/post/2007/09/PhotoShop-like-JavaScript-Color-Picker.aspx)
+ *
+ * Change Log
+ * ______________
+ * 1.0.9
+ *   Added optional title variable for each jPicker window.
+ *
+ * 1.0.8
+ *   Moved all images into a few sprites - now using backgroundPosition to change color maps and bars instead of changing the image - this should be faster to download and run.
+ *   
+ * 1.0.7
+ *   RENAMED CSS FILE TO INCLUDE VERSION NUMBER!!! YOU MUST USE THIS VERSIONED CSS FILE!!! There will be no need to do your own CSS version number increments from now on.
+ *   Added opacity feedback to color preview boxes.
+ *   Removed reliance on "id" value of containing object. Subobjects are now found by class and container instead of id's. This drastically reduces injected code.
+ *   Removed (jQuery).jPicker.getListElementById(id) function since "id" is no longer incorporated or required.
+ *
+ * 1.0.6
+ *   Corrected picker bugs introduced with 1.0.5.
+ *   Removed alpha slider bar until activated - default behavior for alpha is now OFF.
+ *   Corrected Color constructor bug not allowing values of 0 for initial value (it was evaluating false and missing the init code - Thanks Pavol).
+ *   Removed title tags (tooltips) from color maps and bars - They get in the way in some browsers (e.g. IE - dragging marker does NOT prevent or hide the tooltip).
+ *   THERE WERE CSS FILE CHANGES WITH THIS UPDATE!!! IF YOU USE NEVER-EXPIRE HEADERS, YOU WILL NEED TO INCREMENT YOUR CSS FILE VERSION NUMBER!!!
+ *
+ * 1.0.5
+ *   Added opacity support to picker and color/callback methods. New property "a" (alpha - range from 0-100) in all color objects now - defaults to 100% opaque. (Thank you Pavol)
+ *   Added title attributes to input elements - gives short tooltip directions on what button or field does.
+ *   Commit callback used to fire on control initialization (twice actually) - This has been corrected, it does not fire on initialization.
+ *   THERE WERE CSS FILE CHANGES WITH THIS UPDATE!!! IF YOU USE NEVER-EXPIRE HEADERS, YOU WILL NEED TO INCREMENT YOUR CSS FILE VERSION NUMBER!!!
+ *
+ * 1.0.4
+ *   Added ability for smaller picker icon with expandable window on any DOM element (not just input).
+ *   "draggable" property renamed to "expandable" and its scope increased to create small picker icon or large static picker.
+ *
+ * 1.0.3
+ *   Added cancelCallback function for registering an external function when user clicks cancel button. (Thank you Jeff and Pavol)
+ *
+ * 1.0.2
+ *   Random bug fixes - speed concerns.
+ *
+ * 1.0.1
+ *   Corrected closure based memeory leak - there may be others?
+ *
+ * 1.0.0
+ *   First Release.
+ *
+ */
+(function($, version)
+{
+  var Slider = // encapsulate slider functionality for the ColorMap and ColorBar - could be useful to use a jQuery UI draggable for this with certain extensions
+      function(bar, options)
+      {
+        var $this = this, // private properties, methods, and events - keep these variables and classes invisible to outside code
+          arrow = $('img', bar), // the arrow image image to drag
+          barMouseDown = // bind the mousedown to the bar not the arrow for quick snapping to the clicked location
+            function(e)
+            {
+              setValuesFromMousePosition(e);
+              // Bind mousemove and mouseup event to the document so it responds when dragged of of the bar - we will unbind these when on mouseup to save processing
+              $(document).bind('mousemove', docMouseMove).bind('mouseup', docMouseUp);
+              e.stopPropagation();
+              e.preventDefault(); // don't try to select anything or drag the image to the desktop
+              return false;
+            },
+          docMouseMove = // set the values as the mouse moves
+            function(e)
+            {
+              setValuesFromMousePosition(e);
+              e.stopPropagation();
+              e.preventDefault();
+              return false;
+            },
+          docMouseUp = // unbind the document events - they aren't needed when not dragging
+            function(e)
+            {
+              $(document).unbind('mouseup', docMouseUp).unbind('mousemove', docMouseMove);
+              e.stopPropagation();
+              e.preventDefault();
+              return false;
+            },
+          setValuesFromMousePosition = // calculate mouse position and set value within the current range
+            function(e)
+            {
+              var offset = bar.offset(), // lets not calculate this more than once
+                  x = e.pageX - offset.left - parseInt(bar.css('border-left-width')),
+                  y = e.pageY - offset.top - parseInt(bar.css('border-top-width')),
+                  barW = bar.w, // local copies for YUI compressor
+                  barH = bar.h,
+                  newX,
+                  newY;
+              // keep the arrow within the bounds of the bar
+              if (x < 0) x = 0;
+              else if (x > barW) x = barW;
+              if (y < 0) y = 0;
+              else if (y > barH) y = barH;
+              // we will use Math.floor for ALL conversion to pixel lengths - parseInt takes a string as input so it boxes the number into a string THEN converts it
+              // number.toFixed(0) spends time processing rounding which when dealing with imprecise pixels is unnecessary
+              newX = Math.floor(x / barW * $this.mxX);
+              newY = Math.floor(y / barH * $this.mxY);
+              $this.x = newX;
+              $this.y = newY;
+              // if x or y have no range, set it to 1D dragging
+              if ($this.mxX == $this.mnX) x = 0;
+              if ($this.mxY == $this.mnY) y = 0;
+              // set the arrow position
+              $this.setArrowPosition(x, y);
+              // check if this.valuesChanged is a function and execute it if it is
+              $.isFunction($this.valuesChanged) && $this.valuesChanged($this);
+            };
+        $.extend(true, $this, // public properties, methods, and event - these we need to access from other controls
+          {
+            settings: options, // we'll set map and arrow dimensions and image sources
+            x: 0, // this is the calculated x value based on the x range and mouse position
+            y: 0, // this is the calculated y value based on the y range and mouse position
+            mnX: 0, // set the min x value
+            mxX: 0, // set the max x value
+            mnY: 100, // set the min y value
+            mxY: 100, // set the max y value
+            valuesChanged: $.isFunction(arguments[2]) && arguments[2] || null, // pass this argument or assign the variable to register for callbacks
+            setPositioningVariables:
+              function(e)
+              {
+                var map = $this.settings.map; // local copy for YUI compressor
+                bar.w = map && map.width || bar.width();
+                bar.h = map && map.height || bar.height();
+                $this.MinX = 0;
+                $this.MinY = 0;
+                $this.MaxX = bar.w;
+                $this.MaxY = bar.h;
+              },
+            setArrowPositionFromValues:
+              function(e)
+              {
+                $this.setPositioningVariables();
+                var arrowOffsetX = 0,
+                    arrowOffsetY = 0,
+                    // local copies for YUI compressor
+                    mnX = $this.mnX,
+                    mxX = $this.mxX,
+                    mnY = $this.mnY,
+                    mxY = $this.mxY,
+                    x = $this.x,
+                    y = $this.y;
+                if (mnX != mxX) // range is greater than zero
+                {
+                  // constrain to bounds
+                  if (x == mnX) arrowOffsetX = 0;
+                  else if (x == mxX) arrowOffsetX = bar.w;
+                  else // set arrow x position
+                  {
+                    if (mnX < 1) mxX += Math.abs(mnX) + 1;
+                    if (x < 1) x += 1;
+                    arrowOffsetX = x / mxX * bar.w;
+                    if (parseInt(arrowOffsetX) == (mxX - 1)) arrowOffsetX = mxX;
+                    else arrowOffsetX = parseInt(arrowOffsetX);
+                    if (mnX < 1) arrowOffsetX -= Math.abs(mnX) - 1;
+                  }
+                }
+                if (mnY != mxY) // range is greater than zero
+                {
+                  // constrain to bounds
+                  if (y == mnY) arrowOffsetY = 0;
+                  else if (y == mxY) arrowOffsetY = bar.h;
+                  else // set arrow y position
+                  {
+                    if (mnY < 1) mxY += Math.abs(mnY) + 1;
+                    if (y < 1) y += 1;
+                    arrowOffsetY = y / mxY * bar.h;
+                    if (parseInt(arrowOffsetY) == (mxY - 1)) arrowOffsetY = mxY;
+                    else arrowOffsetY = parseInt(arrowOffsetY);
+                    if (mnY < 1) arrowOffsetY -= Math.abs(mnY) - 1;
+                  }
+                }
+                // set the arrow position based on these offsets
+                $this.setArrowPosition(arrowOffsetX, arrowOffsetY);
+              },
+            setArrowPosition:
+              function(offsetX, offsetY)
+              {
+                var barW = bar.w, // local copies for YUI compressor
+                    barH = bar.h,
+                    arrowW = arrow.w,
+                    arrowH = arrow.h;
+                // constrain arrow to bar x
+                if (offsetX < 0) offsetX = 0;
+                else if (offsetX > barW) offsetX = barW;
+                // constrain arrow to bar y
+                if (offsetY < 0) offsetY = 0;
+                else if (offsetY > barH) offsetY = barH;
+                // if arrow width is greater than bar width, center arrow and prevent horizontal dragging
+                if (arrowW > barW) offsetX = (barW >> 1) - (arrowW >> 1); // number >> 1 - superfast bitwise divide by two and truncate (move bits over one bit discarding lowest)
+                else offsetX -= arrowW >> 1;
+                // if arrow height is greater than bar height, center arrow and prevent vertical dragging
+                if (arrowH > barH) offsetY = (barH >> 1) - (arrowH >> 1);
+                else offsetY -= arrowH >> 1;
+                // set the elements offsets
+                arrow.css({ left: offsetX + 'px', top: offsetY + 'px' });
+              },
+            destroy:
+              function()
+              {
+                // unbind all possible events and null objects
+                $(document).unbind('mouseup', docMouseUp).unbind('mousemove', docMouseMove);
+                bar.unbind('mousedown', barMouseDown);
+                bar = null;
+                arrow = null;
+                $this.valuesChanged = null;
+              }
+          });
+        // initialize this control
+        arrow.src = $this.settings.arrow && $this.settings.arrow.image;
+        arrow.w = $this.settings.arrow && $this.settings.arrow.width || arrow.width();
+        arrow.h = $this.settings.arrow && $this.settings.arrow.height || arrow.height();
+        $this.setPositioningVariables();
+        // bind mousedown event
+        bar.bind('mousedown', barMouseDown);
+        $this.setArrowPositionFromValues();
+        // first callback to set initial values
+        $.isFunction($this.valuesChanged) && $this.valuesChanged($this);
+      },
+    ColorValuePicker = // controls for all the input elements for the typing in color values
+      function(picker)
+      {
+        var $this = this, // private properties and methods 
+          hsvKeyUp = // hue, saturation, or brightness input box key up - validate value and set color
+            function(e)
+            {
+              if (e.target.value == '') return;
+              validateHsv(e);
+              $this.setValuesFromHsv();
+              $.isFunction($this.valuesChanged) && $this.valuesChanged($this);
+            },
+          rgbKeyUp = // red, green, or blue input box key up - validate and set color
+            function(e)
+            {
+              if (e.target.value == '') return;
+              validateRgb(e);
+              $this.setValuesFromRgb();
+              $.isFunction($this.valuesChanged) && $this.valuesChanged($this);
+            },
+          alphaKeyUp = // alpha input box blur - validate and set color
+            function(e)
+            {
+              if (e.target.value == '') return;
+              validateAlpha(e);
+              color.a = e.target.value;
+              $.isFunction($this.valuesChanged) && $this.valuesChanged($this);
+            },
+          hsvBlur = // hue, saturation, or brightness input box blur - reset to original if value empty
+            function(e)
+            {
+              if (e.target.value == '') $this.setValuesFromRgb();
+            },
+          rgbBlur = // red, green, or blue input box blur - reset to original value if empty
+            function(e)
+            {
+              if (e.target.value == '') $this.setValuesFromHsv();
+            },
+          alphaBlur = // alpha input box blur - reset to 100 if empty
+            function(e)
+            {
+              if (e.target.value == '') fields.alpha.val(100);
+            },
+          hexKeyUp = // hex input box key up - validate and set color
+            function(e)
+            {
+              if (e.target.value == '') return;
+              validateHex(e);
+              $this.setValuesFromHex();
+              $.isFunction($this.valuesChanged) && $this.valuesChanged($this);
+            },
+          hexBlur = // hex input box blur - reset to original value if empty
+            function(e)
+            {
+              if (e.target.value == '') $this.setValuesFromHsv();
+            },
+          validateRgb = // validate rgb values
+            function(e)
+            {
+              if (!validateKey(e)) return e;
+              fields.red.val(setValueInRange(fields.red.val(), 0, 255));
+              fields.green.val(setValueInRange(fields.green.val(), 0, 255));
+              fields.blue.val(setValueInRange(fields.blue.val(), 0, 255));
+            },
+          validateAlpha = // validate alpha value
+            function(e)
+            {
+              if (!validateKey(e)) return e;
+              fields.alpha.val(setValueInRange(fields.alpha.val(), 0, 100));
+            },
+          validateHsv = // validate hsv values
+            function(e)
+            {
+              if (!validateKey(e)) return e;
+              fields.hue.val(setValueInRange(fields.hue.val(), 0, 360));
+              fields.saturation.val(setValueInRange(fields.saturation.val(), 0, 100));
+              fields.value.val(setValueInRange(fields.value.val(), 0, 100));
+            },
+          validateHex = // validate hex value
+            function(e)
+            {
+              if (!validateKey(e)) return e;
+              fields.hex.val(fields.hex.val().replace(/[^a-fA-F0-9]/g, '0').toLowerCase().substring(0, 6));
+            },
+          validateKey = // validate key
+            function(e)
+            {
+              switch(e.keyCode)
+              {
+                case 9:
+                case 16:
+                case 29:
+                case 37:
+                case 38:
+                case 40:
+                  return false;
+                case 'c'.charCodeAt():
+                case 'v'.charCodeAt():
+                  if (e.ctrlKey) return false;
+              }
+              return true;
+            },
+          setValueInRange = // constrain value within range
+            function(value, min, max)
+            {
+              if (value == '' || isNaN(value)) return min;
+              value = parseInt(value);
+              if (value > max) return max;
+              if (value < min) return min;
+              return value;
+            };
+        $.extend(true, $this, // public properties and methods
+          {
+          color: new Color(),
+          fields:
+            {
+              hue: $('.jPicker_HueText', picker),
+              saturation: $('.jPicker_SaturationText', picker),
+              value: $('.jPicker_BrightnessText', picker),
+              red: $('.jPicker_RedText', picker),
+              green: $('.jPicker_GreenText', picker),
+              blue: $('.jPicker_BlueText', picker),
+              hex: $('.jPicker_HexText', picker),
+              alpha: $('.jPicker_AlphaText', picker)
+            },
+          valuesChanged: $.isFunction(arguments[1]) && arguments[1] || null,
+          bindedHexKeyUp: // binded input element key up
+              function(e)
+              {
+                hexKeyUp(e);
+              },
+          setValuesFromRgb: // set values when rgb changes
+              function()
+              {
+                color.fromRgb(fields.red.val(), fields.green.val(), fields.blue.val());
+                fields.hex.val(color.hex);
+                fields.hue.val(color.h);
+                fields.saturation.val(color.s);
+                fields.value.val(color.v);
+              },
+          setValuesFromHsv: // set values when hsv changes
+              function()
+              {
+                color.fromHsv(fields.hue.val(), fields.saturation.val(), fields.value.val());
+                fields.hex.val(color.hex);
+                fields.red.val(color.r);
+                fields.green.val(color.g);
+                fields.blue.val(color.b);
+              },
+          setValuesFromHex: // set values when hex changes
+              function()
+              {
+                color.fromHex(fields.hex.val());
+                fields.red.val(color.r);
+                fields.green.val(color.g);
+                fields.blue.val(color.b);
+                fields.hue.val(color.h);
+                fields.saturation.val(color.s);
+                fields.value.val(color.v);
+              },
+          setAlphaFromValue: // set alpha value when bar changes
+              function()
+              {
+                color.a=fields.alpha.val();
+              },
+          destroy:
+              function()
+              {
+                // unbind all events and null objects
+                fields.hue.add(fields.saturation).add(fields.value).unbind('keyup', events.hsvKeyUp).unbind('blur', hsvBlur);
+                fields.red.add(fields.green).add(fields.blue).unbind('keyup', events.rgbKeyUp).unbind('blur', rgbBlur);
+                fields.alpha.unbind('keyup', alphaKeyUp).unbind('blur', alphaBlur);
+                fields.hex.unbind('keyup', hexKeyUp);
+                fields = null;
+                color = null;
+                $this.valuesChanged = null;
+              }
+        });
+        var fields = $this.fields, color = $this.color; // local copies for YUI compressor
+        fields.hue.add(fields.saturation).add(fields.value).bind('keyup', hsvKeyUp).bind('blur', hsvBlur);
+        fields.red.add(fields.green).add(fields.blue).bind('keyup', rgbKeyUp).bind('blur', rgbBlur);
+        fields.alpha.bind('keyup', alphaKeyUp).bind('blur', alphaBlur);
+        fields.hex.bind('keyup', hexKeyUp).bind('blur', hexBlur);
+        if (fields.hex.val() != '')
+        {
+          color.fromHex(fields.hex.val());
+          $this.setValuesFromHex();
+        }
+      };
+  $.jPicker =
+    {
+      List: [], // array holding references to each active instance of the control
+      Color: // color object - we will be able to assign by any color space type or retrieve any color space info
+             // we want this public so we can optionally assign new color objects to initial values using inputs other than a string hex value (also supported)
+        function(init)
+        {
+          var $this = this;
+          $.extend(true, $this, // public properties and methods
+            {
+            r: 0, // Red
+            g: 0, // Green
+            b: 0, // Blue
+            h: 0, // Hue
+            s: 0, // Saturation
+            v: 0, // Brightness
+            a: 100, // Alpha
+            hex: '', // Hex
+            fromRgb:
+              function(r, g, b)
+              {
+                var $this = this;
+                $this.r = r;
+                $this.g = g;
+                $this.b = b;
+                var newHsv = ColorMethods.rgbToHsv($this);
+                $this.h = newHsv.h;
+                $this.s = newHsv.s;
+                $this.v = newHsv.v;
+                $this.hex = ColorMethods.rgbToHex($this);
+              },
+            fromHsv:
+              function(h, s, v)
+              {
+                var $this = this;
+                $this.h = h;
+                $this.s = s;
+                $this.v = v;
+                var newRgb = ColorMethods.hsvToRgb($this);
+                $this.r = newRgb.r;
+                $this.g = newRgb.g;
+                $this.b = newRgb.b;
+                $this.hex = ColorMethods.rgbToHex(newRgb);
+              },
+            fromHex:
+              function(hex)
+              {
+                var $this = this;
+                $this.hex = hex;
+                var newRgb = ColorMethods.hexToRgb(hex);
+                $this.r = newRgb.r;
+                $this.g = newRgb.g;
+                $this.b = newRgb.b;
+                var newHsv = ColorMethods.rgbToHsv(newRgb);
+                $this.h = newHsv.h;
+                $this.s = newHsv.s;
+                $this.v = newHsv.v;
+                $this.hex = ColorMethods.rgbToHex(newRgb);
+              }
+          });
+          if (init)
+          {
+            if (init.hex) $this.fromHex(init.hex);
+            else if (!isNaN(init.r)) $this.fromRgb(init.r, init.g, init.b);
+            else if (!isNaN(init.h)) $this.fromHsv(init.h, init.s, init.v);
+            if (!isNaN(init.a)) $this.a = init.a;
+          }
+        },
+      ColorMethods: // color conversion methods  - make public to give use to external scripts
+      {
+      hexToRgb:
+          function(hex)
+          {
+            hex = this.validateHex(hex);
+            var r = '00', g = '00', b = '00';
+            if (hex.length == 6)
+            {
+              r = hex.substring(0, 2);
+              g = hex.substring(2, 4);
+              b = hex.substring(4, 6);
+            }
+            else
+            {
+              if (hex.length > 4)
+              {
+                r = hex.substring(4, hex.length);
+                hex = hex.substring(0, 4);
+              }
+              if (hex.length > 2)
+              {
+                g = hex.substring(2, hex.length);
+                hex = hex.substring(0, 2);
+              }
+              if (hex.length > 0) b = hex.substring(0, hex.length);
+            }
+            return { r: this.hexToInt(r), g: this.hexToInt(g), b: this.hexToInt(b) };
+          },
+      validateHex:
+          function(hex)
+          {
+            hex = hex.toLowerCase().replace(/[^a-f0-9]/g, '0');
+            if (hex.length > 6) hex = hex.substring(0, 6);
+            return hex;
+          },
+      rgbToHex:
+          function(rgb)
+          {
+            return this.intToHex(rgb.r) + this.intToHex(rgb.g) + this.intToHex(rgb.b);
+          },
+      intToHex:
+          function(dec)
+          {
+            var result = parseInt(dec).toString(16);
+            if (result.length == 1) result = ('0' + result);
+            return result.toLowerCase();
+          },
+      hexToInt:
+          function(hex)
+          {
+            return parseInt(hex, 16);
+          },
+      rgbToHsv:
+          function(rgb)
+          {
+            var r = rgb.r / 255, g = rgb.g / 255, b = rgb.b / 255, hsv = { h: 0, s: 0, v: 0 }, min = 0, max = 0, delta;
+            if (r >= g && r >= b)
+            {
+              max = r;
+              min = g > b ? b : g;
+            }
+            else if (g >= b && g >= r)
+            {
+              max = g;
+              min = r > b ? b : r;
+            }
+            else
+            {
+              max = b;
+              min = g > r ? r : g;
+            }
+            hsv.v = max;
+            hsv.s = max ? (max - min) / max : 0;
+            if (!hsv.s) hsv.h = 0;
+            else
+            {
+              delta = max - min;
+              if (r == max) hsv.h = (g - b) / delta;
+              else if (g == max) hsv.h = 2 + (b - r) / delta;
+              else hsv.h = 4 + (r - g) / delta;
+              hsv.h = parseInt(hsv.h * 60);
+              if (hsv.h < 0) hsv.h += 360;
+            }
+            hsv.s = parseInt(hsv.s * 100);
+            hsv.v = parseInt(hsv.v * 100);
+            return hsv;
+          },
+      hsvToRgb:
+          function(hsv)
+          {
+            var rgb = { r: 0, g: 0, b: 0 }, h = hsv.h, s = hsv.s, v = hsv.v;
+            if (s == 0)
+            {
+              if (v == 0) rgb.r = rgb.g = rgb.b = 0;
+              else rgb.r = rgb.g = rgb.b = parseInt(v * 255 / 100);
+            }
+            else
+            {
+              if (h == 360) h = 0;
+              h /= 60;
+              s = s / 100;
+              v = v / 100;
+              var i = parseInt(h),
+                  f = h - i,
+                  p = v * (1 - s),
+                  q = v * (1 - (s * f)),
+                  t = v * (1 - (s * (1 - f)));
+              switch (i)
+              {
+                case 0:
+                  rgb.r = v;
+                  rgb.g = t;
+                  rgb.b = p;
+                  break;
+                case 1:
+                  rgb.r = q;
+                  rgb.g = v;
+                  rgb.b = p;
+                  break;
+                case 2:
+                  rgb.r = p;
+                  rgb.g = v;
+                  rgb.b = t;
+                  break;
+                case 3:
+                  rgb.r = p;
+                  rgb.g = q;
+                  rgb.b = v;
+                  break;
+                case 4:
+                  rgb.r = t;
+                  rgb.g = p;
+                  rgb.b = v;
+                  break;
+                case 5:
+                  rgb.r = v;
+                  rgb.g = p;
+                  rgb.b = q;
+                  break;
+              }
+              rgb.r = parseInt(rgb.r * 255);
+              rgb.g = parseInt(rgb.g * 255);
+              rgb.b = parseInt(rgb.b * 255);
+            }
+            return rgb;
+          }
+    }
+  };
+  var Color = $.jPicker.Color, List = $.jPicker.List, ColorMethods = $.jPicker.ColorMethods; // local copies for YUI compressor
+  $.fn.jPicker =
+      function(options)
+      {
+        var $arguments = arguments;
+        return this.each(
+          function()
+          {
+            var $this = $(this), $settings = $.extend(true, {}, $.fn.jPicker.defaults, options); // local copies for YUI compressor
+            if ($this.get(0).nodeName.toLowerCase() == 'input') // Add color picker icon if binding to an input element and bind the events to the input
+            {
+              $.extend(true, $settings,
+                {
+                  window:
+                  {
+                    bindToInput: true,
+                    expandable: true,
+                    input: $this
+                  }
+                });
+              if (ColorMethods.validateHex($this.val()))
+              {
+                $settings.color.active = new Color({ hex: $this.val(), a: $settings.color.active.a });
+                $settings.color.current = new Color({ hex: $this.val(), a: $settings.color.active.a });
+              }
+            }
+            if ($settings.window.expandable)
+              $this.after('<span class="jPicker_Picker"><span class="jPicker_Color">&nbsp;</span><span class="jPicker_Icon" title="Click To Open Color Picker">&nbsp;</span><span class="jPicker_Container">&nbsp;</span></span>');
+            else $settings.window.liveUpdate = false; // Basic control binding for inline use - You will need to override the liveCallback or commitCallback function to retrieve results
+            var isLessThanIE7 = parseFloat(navigator.appVersion.split('MSIE')[1]) < 7 && document.body.filters, // needed to run the AlphaImageLoader function for IE6
+              colorMapL1 = null, // different layers of colorMap and colorBar
+              colorMapL2 = null,
+              colorMapL3 = null,
+              colorBarL1 = null,
+              colorBarL2 = null,
+              colorBarL3 = null,
+              colorBarL4 = null,
+              colorBarL5 = null,
+              enableAlpha = null,
+              alphaCheckbox = null,
+              alphaBarDiv = null,
+              alphaBarL1 = null,
+              alphaBarL2 = null,
+              container = null,
+              hue = null, // radio buttons
+              saturation = null,
+              value = null,
+              red = null,
+              green = null,
+              blue = null,
+              colorMap = null, // color maps
+              colorBar = null,
+              alphaBar = null,
+              colorPicker = null,
+              elementStartX = null, // Used to record the starting css positions for dragging the control
+              elementStartY = null,
+              pageStartX = null, // Used to record the mousedown coordinates for dragging the control
+              pageStartY = null,
+              activeColor = null, // color boxes above the radio buttons
+              currentColor = null,
+              currentActiveBG = null,
+              okButton = null,
+              cancelButton = null,
+              grid = null, // preset colors grid
+              colorBox = null, // colorBox for popup button
+              colorIcon = null, // colorIcon popup icon
+              moveBar = null, // drag bar
+              setColorMode = // set color mode and update visuals for the new color mode
+                function(colorMode)
+                {
+                  color.active = colorPicker.color;
+                  var active = color.active, // local copies for YUI compressor
+                      clientPath = images.clientPath,
+                      resetImage =
+                        function(img)
+                        {
+                          setAlpha(img, 100);
+                          img.css({ backgroundColor: '', backgroundPosition: '0px 0px', filter: '' });
+                        };
+                  resetImage(colorMapL1); // reset images
+                  resetImage(colorMapL2);
+                  resetImage(colorBarL1);
+                  resetImage(colorBarL2);
+                  resetImage(colorBarL3);
+                  resetImage(colorBarL4);
+                  hue.add(saturation).add(value).add(red).add(green).add(blue).removeAttr('checked');
+                  switch (colorMode)
+                  {
+                    case 'h':
+                      hue.attr('checked', true);
+                      colorMapL1.css({ backgroundColor: '#' + active.hex });
+                      colorMapL2.css({ backgroundColor: 'transparent' });
+                      setImgLoc(colorMapL2, -256);
+                      setAlpha(colorMapL2, 100);
+                      setImgLoc(colorBarL4, -256);
+                      colorMap.mxX = 100;
+                      colorMap.mxY = 100;
+                      colorBar.mxY = 360;
+                      break;
+                    case 's':
+                      saturation.attr('checked', true);
+                      setImgLoc(colorMapL1, -512);
+                      setImgLoc(colorMapL2, -768);
+                      setAlpha(colorMapL2, 0);
+                      setBG(colorBarL3, active.hex);
+                      setImgLoc(colorBarL4, -512);
+                      colorMap.mxX = 360;
+                      colorMap.mxY = 100;
+                      colorBar.mxY = 100;
+                      break;
+                    case 'v':
+                      value.attr('checked', true);
+                      setBG(colorMapL1, '000');
+                      setImgLoc(colorMapL2, -1024);
+                      colorBarL3.css({ backgroundColor: '#' + active.hex });
+                      setImgLoc(colorBarL4, -768);
+                      colorMap.mxX = 360;
+                      colorMap.mxY = 100;
+                      colorBar.mxY = 100;
+                      break;
+                    case 'r':
+                      red.attr('checked', true);
+                      setImgLoc(colorMapL2, -1536);
+                      setImgLoc(colorMapL1, -1280);
+                      setImgLoc(colorBarL4, -1024);
+                      setImgLoc(colorBarL3, -1280);
+                      setImgLoc(colorBarL2, -1536);
+                      setImgLoc(colorBarL1, -1792);
+                      break;
+                    case 'g':
+                      green.attr('checked', true);
+                      setImgLoc(colorMapL2, -2048);
+                      setImgLoc(colorMapL1, -1792);
+                      setImgLoc(colorBarL4, -2048);
+                      setImgLoc(colorBarL3, -2304);
+                      setImgLoc(colorBarL2, -2560);
+                      setImgLoc(colorBarL1, -2816);
+                      break;
+                    case 'b':
+                      blue.attr('checked', true);
+                      setImgLoc(colorMapL2, -2560);
+                      setImgLoc(colorMapL1, -2304);
+                      setImgLoc(colorBarL4, -3072);
+                      setImgLoc(colorBarL3, -3328);
+                      setImgLoc(colorBarL2, -3584);
+                      setImgLoc(colorBarL1, -3840);
+                      break;
+                    default:
+                      throw ('Invalid Mode');
+                      break;
+                  }
+                  switch (colorMode)
+                  {
+                    case 'h':
+                    case 's':
+                    case 'v':
+                      colorMap.mnX = 1;
+                      colorMap.mnY = 1;
+                      colorBar.mnY = 1;
+                      break;
+                    case 'r':
+                    case 'g':
+                    case 'b':
+                      colorMap.mnX = 0;
+                      colorMap.mnY = 0;
+                      colorBar.mnY = 0;
+                      colorMap.mxX = 255;
+                      colorMap.mxY = 255;
+                      colorBar.mxY = 255;
+                      break;
+                  }
+                  color.mode = colorMode;
+                  positionMapAndBarArrows();
+                  updateMapVisuals();
+                  updateBarVisuals();
+                  if (window.expandable && window.liveUpdate)
+                  {
+                    colorBox.css({ backgroundColor: '#' + active.hex });
+                    if (window.bindToInput)
+                      window.input.val(active.hex).css(
+                        {
+                          backgroundColor: '#' + active.hex,
+                          color: active.v > 75 ? '#000000' : '#ffffff'
+                        });
+                  }
+                  $.isFunction($this.liveCallback) && $this.liveCallback(active);
+                },
+              textValuesChanged = // Update color when user changes text values
+                function()
+                {
+                  positionMapAndBarArrows();
+                  updateVisuals();
+                  color.active = colorPicker.color;
+                  var active = color.active; // local copy for YUI compressor
+                  if (window.expandable && window.liveUpdate)
+                  {
+                    colorBox.css({ backgroundColor: '#' + active.hex });
+                    if (window.bindToInput)
+                      window.input.val(colorPicker.fields.hex.val()).css(
+                        {
+                          backgroundColor: '#' + active.hex,
+                          color: active.v > 75 ? '#000000' : '#ffffff'
+                        });
+                  }
+                  $.isFunction($this.liveCallback) && $this.liveCallback(active);
+                },
+              mapValueChanged = // user has dragged the ColorMap pointer
+                function()
+                {
+                  if (!colorPicker || !colorMap || !colorBar || !alphaBar) return;
+                  color.active = colorPicker.color;
+                  var fields = colorPicker.fields, // local copies for YUI compressor
+                      active = color.active;
+                  switch (color.mode)
+                  {
+                    case 'h':
+                      fields.saturation.val(colorMap.x);
+                      fields.value.val(100 - colorMap.y);
+                      break;
+                    case 's':
+                      fields.hue.val(colorMap.x);
+                      fields.value.val(100 - colorMap.y);
+                      break;
+                    case 'v':
+                      fields.hue.val(colorMap.x);
+                      fields.saturation.val(100 - colorMap.y);
+                      break;
+                    case 'r':
+                      fields.blue.val(colorMap.x);
+                      fields.green.val(255 - colorMap.y);
+                      break;
+                    case 'g':
+                      fields.blue.val(colorMap.x);
+                      fields.red.val(255 - colorMap.y);
+                      break;
+                    case 'b':
+                      fields.red.val(colorMap.x);
+                      fields.green.val(255 - colorMap.y);
+                      break;
+                  }
+                  switch (color.mode)
+                  {
+                    case 'h':
+                    case 's':
+                    case 'v':
+                      colorPicker.setValuesFromHsv();
+                      break;
+                    case 'r':
+                    case 'g':
+                    case 'b':
+                      colorPicker.setValuesFromRgb();
+                      break;
+                  }
+                  updateVisuals();
+                  if (window.expandable && window.liveUpdate)
+                  {
+                    colorBox.css({ backgroundColor: '#' + active.hex });
+                    if (window.bindToInput)
+                      window.input.val(active.hex).css(
+                        {
+                          backgroundColor: '#' + active.hex,
+                          color: active.v > 75 ? '#000000' : '#ffffff'
+                        });
+                  }
+                  $.isFunction($this.liveCallback) && $this.liveCallback(active);
+                },
+              colorBarValueChanged = // user has dragged the ColorBar slider
+                function()
+                {
+                  if (!colorPicker || !colorMap || !colorBar || !alphaBar) return;
+                  color.active = colorPicker.color;
+                  var fields = colorPicker.fields, // local copies for YUI compressor
+                      active = color.active;
+                  switch (color.mode)
+                  {
+                    case 'h':
+                      fields.hue.val(360 - colorBar.y);
+                      break;
+                    case 's':
+                      fields.saturation.val(100 - colorBar.y);
+                      break;
+                    case 'v':
+                      fields.value.val(100 - colorBar.y);
+                      break;
+                    case 'r':
+                      fields.red.val(255 - colorBar.y);
+                      break;
+                    case 'g':
+                      fields.green.val(255 - colorBar.y);
+                      break;
+                    case 'b':
+                      fields.blue.val(255 - colorBar.y);
+                      break;
+                  }
+                  switch (color.mode)
+                  {
+                    case 'h':
+                    case 's':
+                    case 'v':
+                      colorPicker.setValuesFromHsv();
+                      break;
+                    case 'r':
+                    case 'g':
+                    case 'b':
+                      colorPicker.setValuesFromRgb();
+                      break;
+                  }
+                  updateVisuals();
+                  if (window.expandable && window.liveUpdate)
+                  {
+                    colorBox.css({ backgroundColor: '#' + active.hex });
+                    if (window.bindToInput)
+                      window.input.val(active.hex).css(
+                        {
+                          backgroundColor: '#' + active.hex,
+                          color: active.v > 75 ? '#000000' : '#ffffff'
+                        });
+                  }
+                  $.isFunction($this.liveCallback) && $this.liveCallback(active);
+                },
+              alphaBarValueChanged =
+                function()
+                {
+                  if (!colorPicker || !colorMap || !colorBar || !alphaBar) return;
+                  color.active = colorPicker.color;
+                  var fields = colorPicker.fields, // local copies for YUI compressor
+                      active = color.active;
+                  fields.alpha.val(alphaBar.x);
+                  colorPicker.setAlphaFromValue();
+                  updateVisuals();
+                  $.isFunction($this.liveCallback) && $this.liveCallback(color.active);
+                },
+              positionMapAndBarArrows = // position map and bar arrows to match current color
+                function()
+                {
+                  color.active = colorPicker.color;
+                  var sliderValue = 0,
+                      active = color.active; // local copy for YUI compressor
+                  switch ($this.settings.color.mode)
+                  {
+                    case 'h':
+                      sliderValue = 360 - active.h;
+                      break;
+                    case 's':
+                      sliderValue = 100 - active.s;
+                      break;
+                    case 'v':
+                      sliderValue = 100 - active.v;
+                      break;
+                    case 'r':
+                      sliderValue = 255 - active.r;
+                      break;
+                    case 'g':
+                      sliderValue = 255 - active.g;
+                      break;
+                    case 'b':
+                      sliderValue = 255 - active.b;
+                      break;
+                  }
+                  colorBar.y = sliderValue;
+                  alphaBar.x = active.a;
+                  colorBar.setArrowPositionFromValues();
+                  alphaBar.setArrowPositionFromValues();
+                  var mapX = 0, mapY = 0;
+                  switch ($this.settings.color.mode)
+                  {
+                    case 'h':
+                      mapX = active.s;
+                      mapY = 100 - active.v;
+                      break;
+                    case 's':
+                      mapX = active.h;
+                      mapY = 100 - active.v;
+                      break;
+                    case 'v':
+                      mapX = active.h;
+                      mapY = 100 - active.s;
+                      break;
+                    case 'r':
+                      mapX = active.b;
+                      mapY = 256 - active.g;
+                      break;
+                    case 'g':
+                      mapX = active.b;
+                      mapY = 256 - active.r;
+                      break;
+                    case 'b':
+                      mapX = active.r;
+                      mapY = 256 - active.g;
+                      break;
+                  }
+                  colorMap.x = mapX;
+                  colorMap.y = mapY;
+                  colorMap.setArrowPositionFromValues();
+                },
+              updateVisuals =
+                function()
+                {
+                  updatePreview();
+                  updateMapVisuals();
+                  updateBarVisuals();
+                  updateAlphaVisuals();
+                },
+              updatePreview =
+                function()
+                {
+                  try
+                  {
+                    activeColor.css({ backgroundColor: '#' + colorPicker.color.hex });
+                    setAlpha(activeColor, colorPicker.color.a);
+                  }
+                  catch (e) { }
+                },
+              updateMapVisuals =
+                function()
+                {
+                  if (!color || !colorPicker) return;
+                  color.active = colorPicker.color;
+                  var active = color.active; // local copy for YUI compressor
+                  switch (color.mode)
+                  {
+                    case 'h':
+                      setBG(colorMapL1, new Color({ h: active.h, s: 100, v: 100 }).hex);
+                      break;
+                    case 's':
+                      setAlpha(colorMapL2, 100 - active.s);
+                      break;
+                    case 'v':
+                      setAlpha(colorMapL2, active.v);
+                      break;
+                    case 'r':
+                      setAlpha(colorMapL2, active.r / 256 * 100);
+                      break;
+                    case 'g':
+                      setAlpha(colorMapL2, active.g / 256 * 100);
+                      break;
+                    case 'b':
+                      setAlpha(colorMapL2, active.b / 256 * 100);
+                      break;
+                  }
+                  setAlpha(colorMapL3, 100 - active.a);
+                },
+              updateBarVisuals =
+                function()
+                {
+                  if (!color || !colorPicker) return;
+                  color.active = colorPicker.color;
+                  var active = color.active, // local copy for YUI compressor
+                      mode = color.mode,
+                      fields = colorPicker.fields;
+                  switch (mode)
+                  {
+                    case 'h':
+                      break;
+                    case 's':
+                      var saturatedColor = new Color({ h: active.h, s: 100, v: active.v });
+                      setBG(colorBarL3, saturatedColor.hex);
+                      break;
+                    case 'v':
+                      var valueColor = new Color({ h: active.h, s: active.s, v: 100 });
+                      setBG(colorBarL3, valueColor.hex);
+                      break;
+                    case 'r':
+                    case 'g':
+                    case 'b':
+                      var hValue = 0, vValue = 0;
+                      if (mode == 'r')
+                      {
+                        hValue = fields.blue.val();
+                        vValue = fields.green.val();
+                      }
+                      else if (mode == 'g')
+                      {
+                        hValue = fields.blue.val();
+                        vValue = fields.red.val();
+                      }
+                      else if (mode == 'b')
+                      {
+                        hValue = fields.red.val();
+                        vValue = fields.green.val();
+                      }
+                      var horzPer = hValue / 256 * 100, vertPer = vValue / 256 * 100, horzPerRev = (256 - hValue) / 256 * 100, vertPerRev = (256 - vValue) / 256 * 100;
+                      setAlpha(colorBarL4, vertPer > horzPerRev ? horzPerRev : vertPer);
+                      setAlpha(colorBarL3, vertPer > horzPer ? horzPer : vertPer);
+                      setAlpha(colorBarL2, vertPerRev > horzPer ? horzPer : vertPerRev);
+                      setAlpha(colorBarL1, vertPerRev > horzPerRev ? horzPerRev : vertPerRev);
+                      break;
+                  }
+                  setAlpha(colorBarL5, 100 - active.a);
+                },
+              updateAlphaVisuals =
+                function()
+                {
+                  setBG(alphaBarL1, colorPicker.color.hex);
+                },
+              setBG =
+                function(el, c)
+                {
+                  try
+                  {
+                    el.css({ backgroundColor: '#' + c });
+                  }
+                  catch (e) { }
+                },
+              setImg =
+                function(img, src)
+                {
+                  if (src.indexOf('png') && this.isLessThanIE7)
+                  {
+                    img.attr('pngSrc', src);
+                    img.css({ backgroundImage: 'none', filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + src + '\')' });
+                  }
+                  else img.css({ backgroundImage: 'url(' + src + ')' });
+                },
+              setImgLoc =
+                function(img, y)
+                {
+                  img.css({ backgroundPosition: '0px ' + y + 'px' });
+                },
+              setAlpha =
+                function(obj, alpha)
+                {
+                  if (alpha < 100)
+                  {
+                    if (this.isLessThanIE7)
+                    {
+                      var src = obj.attr('pngSrc');
+                      if (src != null && src.indexOf('map-hue') == -1)
+                        obj.css({ filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + src + '\') progid:DXImageTransform.Microsoft.Alpha(opacity=' + alpha + ')' });
+                    }
+                    else obj.css({ opacity: alpha / 100 });
+                  }
+                  else if (alpha == 100) // IE7 still will not combine 8-bit PNG translucency AND element opacity without drawing errors
+                                         // Even opacity:1.0 (or filter:Alpha(opacity=100)) causes issues, so remove it if opaque
+                  {
+                    if (this.isLessThanIE7)
+                    {
+                      var src = obj.attr('pngSrc');
+                      if (src != null && src.indexOf('map-hue') == -1) obj.css({ filter: 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + src + '\')' });
+                    }
+                    else obj.css({ opacity: '' });
+                  }
+                },
+              revertColor = // revert color to original color when opened
+                function()
+                {
+                  colorPicker.fields.hex.val(color.current.hex);
+                  colorPicker.fields.alpha.val(color.current.a);
+                  colorPicker.setValuesFromHex();
+                  colorPicker.setAlphaFromValue();
+                  $.isFunction(colorPicker.valuesChanged) && colorPicker.valuesChanged(colorPicker);
+                },
+              radioClicked =
+                function(e)
+                {
+                  setColorMode(e.target.value);
+                },
+              currentClicked =
+                function()
+                {
+                  revertColor();
+                },
+              cancelClicked =
+                function()
+                {
+                  revertColor();
+                  window.expandable && $this.hide();
+                  $.isFunction($this.cancelCallback) && $this.cancelCallback();
+                },
+              commitColor = // commit the color changes
+                function()
+                {
+                  var active = color.active; // local copies for YUI compressor
+                  color.current = new Color({ hex: active.hex });
+                  color.current.a = active.a;
+                  currentColor.css({ backgroundColor: '#' + active.hex });
+                  setAlpha(currentColor, colorPicker.color.a);
+                  if (window.expandable)
+                  {
+                    colorBox.css({ backgroundColor: '#' + active.hex });
+                    if (window.bindToInput)
+                      window.input.val(active.hex).css(
+                        {
+                          backgroundColor: '#' + active.hex,
+                          color: active.v > 75 ? '#000000' : '#ffffff'
+                        });
+                  }
+                  $.isFunction($this.commitCallback) && $this.commitCallback(active);
+                },
+              okClicked =
+                function()
+                {
+                  commitColor();
+                  window.expandable && $this.hide();
+                },
+              colorIconClicked =
+                function()
+                {
+                  $this.show();
+                },
+              moveBarMouseDown =
+                function(e)
+                {
+                  var element = window.element, // local copies for YUI compressor
+                      page = window.page;
+                  elementStartX = parseInt(container.css('left'));
+                  elementStartY = parseInt(container.css('top'));
+                  pageStartX = e.pageX;
+                  pageStartY = e.pageY;
+                  // bind events to document to move window - we will unbind these on mouseup
+                  $(document).bind('mousemove', documentMouseMove).bind('mouseup', documentMouseUp);
+                  e.stopPropagation();
+                  e.preventDefault(); // prevent attempted dragging of the column
+                  return false;
+                },
+              documentMouseMove =
+                function(e)
+                {
+                  container.css({ left: elementStartX - (pageStartX - e.pageX) + 'px', top: elementStartY - (pageStartY - e.pageY) + 'px' });
+                  e.stopPropagation();
+                  e.preventDefault();
+                  return false;
+                },
+              documentMouseUp =
+                function(e)
+                {
+                  $(document).unbind('mousemove', documentMouseMove).unbind('mouseup', documentMouseUp);
+                  e.stopPropagation();
+                  e.preventDefault();
+                  return false;
+                },
+              bindedHexKeyUp =
+                function(e)
+                {
+                  colorPicker.fields.hex.val($this.settings.window.input.val());
+                  colorPicker.bindedHexKeyUp(e);
+                },
+              quickPickClicked =
+                function(e)
+                {
+                  colorPicker.fields.hex.val(color.quickList[e.data.i].hex);
+                  colorPicker.fields.alpha.val(color.quickList[e.data.i].a);
+                  colorPicker.setValuesFromHex();
+                  colorPicker.setAlphaFromValue();
+                  $.isFunction(colorPicker.valuesChanged) && colorPicker.valuesChanged(colorPicker);
+                };
+            $.extend(true, $this, // public properties, methods, and callbacks
+              {
+                id: $this.attr('id'),
+                settings: $settings,
+                color: null,
+                icon: null,
+                commitCallback: $.isFunction($arguments[1]) && $arguments[1] || null, // commitCallback function can be overridden to return the selected color to a method you specify when the user clicks "OK"
+                liveCallback: $.isFunction($arguments[2]) && $arguments[2] || null, // liveCallback function can be overridden to return the selected color to a method you specify in live mode (continuous update)
+                cancelCallback: $.isFunction($arguments[3]) && $arguments[3] || null, // cancelCallback function can be overridden to a method you specify when the user clicks "Cancel"
+                show:
+                  function()
+                  {
+                    if (document.all) // In IE, due to calculated z-index values, we need to hide all color picker icons that appear later in the source code than this one
+                    {
+                      var foundthis = false;
+                      for (i = 0; i < List.length; i++)
+                      {
+                        if (foundthis) List[i].color.add(List[i].icon).css({ display: 'none' });
+                        if (List[i].id == $this.id) foundthis = true;
+                      }
+                    }
+                    color.current = new Color({ hex: color.active.hex, a: color.active.a });
+                    currentColor.css({ backgroundColor: '#' + color.active.hex });
+                    setAlpha(currentColor, color.active.a);
+                    container.css({ display: 'block' });
+                    colorMap.setPositioningVariables();
+                    colorBar.setPositioningVariables();
+                    positionMapAndBarArrows();
+                  },
+                hide:
+                  function()
+                  {
+                    if (document.all) // In IE, show the previously hidden color picker icons again
+                    {
+                      var foundthis = false;
+                      for (i = 0; i < List.length; i++)
+                      {
+                        if (foundthis) List[i].color.add(List[i].icon).css({ display: 'block' });
+                        if (List[i].id == $this.id) foundthis = true;
+                      }
+                    }
+                    container.css({ display: 'none' });
+                  },
+                destroy: // destroys this control entirely, removing all events and objects, and removing itself from the List
+                  function()
+                  {
+                    if (window.expandable) colorIcon = $('.jPicker_Icon', container).unbind('click', colorIconClicked);
+                    if (window.bindToInput) window.input.unbind('keyup', bindedHexKeyUp).unbind('change', bindedHexKeyUp);
+                    hue.add(saturation).add(value).add(red).add(green).add(blue).unbind('click', radioClicked);
+                    currentColor.unbind('click', currentClicked);
+                    cancelButton.unbind('click', cancelClicked);
+                    okButton.unbind('click', okClicked);
+                    if (window.expandable) moveBar.unbind('mousedown', moveBarMouseDown);
+                    $('.jPicker_QuickColor', container).unbind('click', quickPickClicked);
+                    hue = null;
+                    saturation = null;
+                    value = null;
+                    red = null;
+                    green = null;
+                    blue = null;
+                    colorMapL1 = null;
+                    colorMapL2 = null;
+                    colorMapL3 = null;
+                    colorBarL1 = null;
+                    colorBarL2 = null;
+                    colorBarL3 = null;
+                    colorBarL4 = null;
+                    colorBarL5 = null;
+                    enableAlpha = null;
+                    alphaCheckbox = null;
+                    alphaBarDiv = null;
+                    alphaBarL1 = null;
+                    alphaBarL2 = null;
+                    currentActiveBG = null;
+                    activeColor = null;
+                    currentColor = null;
+                    okButton = null;
+                    cancelButton = null;
+                    grid = null;
+                    $this.color = null;
+                    $this.icon = null;
+                    colorMap.destroy();
+                    colorMap = null;
+                    colorBar.destroy();
+                    colorBar = null;
+                    alphaBar.destroy();
+                    alphaBar = null;
+                    colorPicker.destroy();
+                    colorPicker = null;
+                    $this.commitCallback = null;
+                    $this.cancelCallback = null;
+                    $this.liveCallback = null;
+                    container.html('');
+                    for (i = 0; i < List.length; i++) if (List[i].id == $this.id) List.splice(i, 1);
+                  }
+              });
+            var images = $this.settings.images, // local copies for YUI compressor
+                window = $this.settings.window,
+                color = $this.settings.color;
+            container = window.expandable ? $('.jPicker_Container', $this.next()) : $this;
+            if (window.expandable)
+              container.css( // positions must be set and display set to absolute before source code injection or IE will size the container to fit the window
+                {
+                  left: window.position.x == 'left' ? '-526px' : window.position.x == 'center' ? '-259px' : window.position.x == 'right' ? '0px' : window.position.x == 'screenCenter' ?
+                    (($(document).width() >> 1) - 259) - $this.next().offset().left + 'px' : window.position.x,
+                  position: 'absolute',
+                  top: window.position.y == 'top' ? '-340px' : window.position.y == 'center' ? '-153px' : window.position.y == 'bottom' ? '25px' : window.position.y
+                });
+            // if default colors are hex strings, change them to color objects
+            if ((typeof (color.active)).toString().toLowerCase() == 'string') color.active = new Color({ hex: color.active.substring(1) });
+            // inject html source code - we are using a single table for this control - I know tables are considered bad, but it takes care of equal height columns and
+            // this control really is tabular data, so I believe it is the right move
+            if (!color.alphaSupport) color.active.a = 100;
+            container.html('<table class="jPicker_table"><tbody>' + (window.expandable ? '<tr><td class="jPicker_MoveBar" colspan="6">&nbsp;</td></tr>' : '') + '<tr><td rowspan="8"><h2 class="jPicker_Title">' + (window.title || 'Drag Markers To Pick A Color') + '</h2><div class="jPicker_ColorMap"><span class="jPicker_ColorMap_l1">&nbsp;</span><span class="jPicker_ColorMap_l2">&nbsp;</span><span class="jPicker_ColorMap_l3">&nbsp;</span><img src="' + images.clientPath + images.colorMap.arrow.file + '" class="jPicker_ColorMap_Arrow"/></div></td><td rowspan="8"><div class="jPicker_ColorBar"><span class="jPicker_ColorBar_l1">&nbsp;</span><span class="jPicker_ColorBar_l2">&nbsp;</span><span class="jPicker_ColorBar_l3">&nbsp;</span><span class="jPicker_ColorBar_l4">&nbsp;</span><span class="jPicker_ColorBar_l5">&nbsp;</span><img src="' + images.clientPath + images.colorBar.arrow.file + '" class="jPicker_ColorBar_Arrow"/></div></td><td colspan="3" class="jPicker_Preview">new<div class="jPicker_NewCurrent"><span class="jPicker_Active" title="New Color - Press &ldquo;OK&rdquo; To Commit">&nbsp;</span><span class="jPicker_Current" title="Click To Revert To Original Color">&nbsp;</span></div>current</td><td rowspan="9" class="jPicker_OkCancel"><input type="button" class="jPicker_Ok" value="OK" title="Commit To This Color Selection"/><input type="button" class="jPicker_Cancel" value="Cancel" title="Cancel And Revert To Original Color"/><hr/><div class="jPicker_Grid">&nbsp;</div></td></tr><tr><td><input type="radio" class="jPicker_HueRadio" id="jPicker_Hue_'+List.length+'" name="jPicker_Mode_'+List.length+'" value="h" title="Set To &ldquo;Hue&rdquo; Color Mode"/></td><td><label for="jPicker_Hue_'+List.length+'" title="Set To &ldquo;Hue&rdquo; Color Mode">H:</label></td><td><input type="text" class="jPicker_HueText" value="' + color.active.h + '" title="Enter A &ldquo;Hue&rdquo; Value (0-360&deg;)"/> &deg;</td</tr><tr><td><input type="radio" class="jPicker_SaturationRadio" id="jPicker_Saturation_'+List.length+'" name="jPicker_Mode_'+List.length+'" value="s" title="Set To &ldquo;Saturation&rdquo; Color Mode"/></td><td><label for="jPicker_Saturation_'+List.length+'" title="Set To &ldquo;Saturation&rdquo; Color Mode">S:</label></td><td><input type="text" class="jPicker_SaturationText" value="' + color.active.s + '" title="Enter A &ldquo;Saturation&rdquo; Value (0-100%)"/> %</td></tr><tr><td><input type="radio" class="jPicker_BrightnessRadio" id="jPicker_Brightness_'+List.length+'" name="jPicker_Mode_'+List.length+'" value="v" title="Set To &ldquo;Brightness&rdquo; Color Mode"/></td><td><label for="jPicker_Brightness_'+List.length+'" title="Set To &ldquo;Brightness&rdquo; Color Mode">B:</label></td><td><input type="text" class="jPicker_BrightnessText" value="' + color.active.v + '" title="Enter A &ldquo;Brightness&rdquo; Value (0-100%)"/> %</td></tr><tr><td colspan="3" class="jPicker_Spacer">&nbsp;</td></tr><tr><td><input type="radio" class="jPicker_RedRadio" id="jPicker_Red_'+List.length+'" name="jPicker_Mode_'+List.length+'" value="r" title="Set To &ldquo;Red&rdquo; Color Mode"/></td><td><label for="jPicker_Red_'+List.length+'" title="Set To &ldquo;Red&rdquo; Color Mode">R:</label></td><td><input type="text" class="jPicker_RedText" value="' + color.active.r + '" title="Enter A &ldquo;Red&rdquo; Value (0-255)"/></td></tr><tr><td><input type="radio" class="jPicker_GreenRadio" id="jPicker_Green_'+List.length+'" name="jPicker_Mode_'+List.length+'" value="g" title="Set To &ldquo;Green&rdquo; Color Mode"/></td><td><label for="jPicker_Green_'+List.length+'" title="Set To &ldquo;Green&rdquo; Color Mode">G:</label></td><td><input type="text" class="jPicker_GreenText" value="' + color.active.g + '" title="Enter A &ldquo;Green&rdquo; Value (0-255)"/></td></tr><tr><td><input type="radio" class="jPicker_BlueRadio" id="jPicker_Blue_'+List.length+'" name="jPicker_Mode_'+List.length+'" value="b" title="Set To &ldquo;Blue&rdquo; Color Mode"/></td><td><label for="jPicker_Blue_'+List.length+'" title="Set To &ldquo;Blue&rdquo; Color Mode">B:</label></td><td><input type="text" class="jPicker_BlueText" value="' + color.active.b + '" title="Enter A &ldquo;Blue&rdquo; Value (0-255)"/></td></tr><tr><td><div class="jPicker_EnableAlpha"><input type="checkbox" class="jPicker_AlphaCheckbox" id="jPicker_AlphaCheckbox_'+List.length+'" title="Enable Alpha (Transparency) Support"/><label for="jPicker_AlphaCheckbox_'+List.length+'" title="Enabled Alpha (Transparency) Support">Enable Alpha (Transparency) Support</label></div><div class="jPicker_AlphaBar"><span class="jPicker_AlphaBar_l1">&nbsp;</span><span class="jPicker_AlphaBar_l2">&nbsp;</span><img src="' + images.clientPath + images.alphaBar.arrow.file + '" class="jPicker_AlphaBar_Arrow"/></div></td><td colspan="2" class="jPicker_OpacityCol"><label for="jPicker_Alpha_'+List.length+'" title="Enter An &ldquo;Alpha&rdquo; Value (0-100%)">A:</label><input type="text" class="jPicker_AlphaText" id="jPicker_Alpha_'+List.length+'" value="' + color.active.a + '" title="Enter An &ldquo;Alpha&rdquo; Value (0-100%)"/><span>%</span></td><td colspan="3" class="jPicker_HexCol"><label for="jPicker_Hex_'+List.length+'" title="Enter A &ldquo;Hex&rdquo; Color Value (#000000-#ffffff)">#:</label><input type="text" class="jPicker_HexText" id="jPicker_Hex_'+List.length+'" value="' + color.active.hex + '" title="Enter A &ldquo;Hex&rdquo; Color Value (#000000-#ffffff)"/></td><td colspan="2" class="jPicker_EnterHex"></td><td>&nbsp;</td></tr></tbody></table>');
+            // initialize the objects to the source code just injected
+            hue = $('.jPicker_HueRadio', container);
+            saturation = $('.jPicker_SaturationRadio', container);
+            value = $('.jPicker_BrightnessRadio', container);
+            red = $('.jPicker_RedRadio', container);
+            green = $('.jPicker_GreenRadio', container);
+            blue = $('.jPicker_BlueRadio', container);
+            colorMapL1 = $('.jPicker_ColorMap_l1', container);
+            colorMapL2 = $('.jPicker_ColorMap_l2', container);
+            colorMapL3 = $('.jPicker_ColorMap_l3', container);
+            colorBarL1 = $('.jPicker_ColorBar_l1', container);
+            colorBarL2 = $('.jPicker_ColorBar_l2', container);
+            colorBarL3 = $('.jPicker_ColorBar_l3', container);
+            colorBarL4 = $('.jPicker_ColorBar_l4', container);
+            colorBarL5 = $('.jPicker_ColorBar_l5', container);
+            alphaBarL1 = $('.jPicker_AlphaBar_l1', container);
+            alphaBarL2 = $('.jPicker_AlphaBar_l2', container);
+            enableAlpha = $('.jPicker_EnableAlpha', container);
+            alphaCheckbox = $('.jPicker_AlphaCheckbox', container);
+            alphaBarDiv = $('.jPicker_AlphaBar', container);
+            currentActiveBG = $('.jPicker_NewCurrent', container);
+            activeColor = $('.jPicker_Active', container).css({ backgroundColor: '#' + color.active.hex });
+            currentColor = $('.jPicker_Current', container).css({ backgroundColor: '#' + color.active.hex });
+            okButton = $('.jPicker_Ok', container);
+            cancelButton = $('.jPicker_Cancel', container);
+            grid = $('.jPicker_Grid', container);
+            $this.color = $('.Picker_Color');
+            $this.icon = $('.jPicker_Icon');
+            // create color pickers and maps
+            colorPicker = new ColorValuePicker(container, textValuesChanged);
+            colorMap = new Slider($('.jPicker_ColorMap', container),
+              {
+                map:
+                {
+                  width: images.colorMap.width,
+                  height: images.colorMap.height
+                },
+                arrow:
+                {
+                  image: images.clientPath + images.colorMap.arrow.file,
+                  width: images.colorMap.arrow.width,
+                  height: images.colorMap.arrow.height
+                }
+              },
+              mapValueChanged);
+            colorBar = new Slider($('.jPicker_ColorBar', container),
+              {
+                map:
+                {
+                  width: images.colorBar.width,
+                  height: images.colorBar.height
+                },
+                arrow:
+                {
+                  image: images.clientPath + images.colorBar.arrow.file,
+                  width: images.colorBar.arrow.width,
+                  height: images.colorBar.arrow.height
+                }
+              },
+              colorBarValueChanged);
+            alphaBar = new Slider($('.jPicker_AlphaBar', container),
+              {
+                map:
+                {
+                  width: images.alphaBar.width,
+                  height: images.alphaBar.height
+                },
+                arrow:
+                {
+                  image: images.clientPath + images.alphaBar.arrow.file,
+                  width: images.alphaBar.arrow.width,
+                  height: images.alphaBar.arrow.height
+                }
+              },
+              alphaBarValueChanged);
+            alphaBar.mnX = 0;
+            alphaBar.mxX = 100;
+            setImg(colorMapL1, images.clientPath + 'Maps.png');
+            setImg(colorMapL2, images.clientPath + 'Maps.png');
+            setImg(colorMapL3, images.clientPath + 'map-opacity.png');
+            setImg(colorBarL1, images.clientPath + 'Bars.png');
+            setImg(colorBarL2, images.clientPath + 'Bars.png');
+            setImg(colorBarL3, images.clientPath + 'Bars.png');
+            setImg(colorBarL4, images.clientPath + 'Bars.png');
+            setImg(colorBarL5, images.clientPath + 'bar-opacity.png');
+            setImg(alphaBarL2, images.clientPath + 'Maps.png');
+            setImgLoc(alphaBarL2, -2816);
+            setImg(currentActiveBG, images.clientPath + 'preview-opacity.png');
+            currentActiveBG.css({ backgroundPosition: '1px 1px' });
+            if (color.alphaSupport)
+            {
+              enableAlpha.hide();
+              alphaBarDiv.show();
+              $('td.jPicker_OpacityCol *', container).show();
+            }
+            else
+              alphaCheckbox.bind('click',
+                function()
+                {
+                  enableAlpha.hide();
+                  alphaBarDiv.show();
+                  $('td.jPicker_OpacityCol *', container).show();
+                });
+            // bind to input
+            if (window.expandable)
+            {
+              colorBox = $('.jPicker_Color', $this.next()).css({ backgroundColor: '#' + color.active.hex });
+              colorIcon = $('.jPicker_Icon', $this.next()).css(
+                {
+                  backgroundImage: 'url(' + images.clientPath + images.picker.file + ')'
+                }).bind('click', colorIconClicked);
+              if (window.bindToInput) window.input.bind('keyup', bindedHexKeyUp).bind('change', bindedHexKeyUp);
+            }
+            hue.add(saturation).add(value).add(red).add(green).add(blue).bind('click', radioClicked);
+            currentColor.bind('click', currentClicked);
+            cancelButton.bind('click', cancelClicked);
+            okButton.bind('click', okClicked);
+            if (window.expandable) moveBar = $('.jPicker_MoveBar', container).bind('mousedown', moveBarMouseDown);
+            // initialize quick list
+            if (color.quickList && color.quickList.length > 0)
+            {
+              grid.html('');
+              for (i = 0; i < color.quickList.length; i++)
+              {
+                /* if default colors are hex strings, change them to color objects */
+                if ((typeof (color.quickList[i])).toString().toLowerCase() == 'string') color.quickList[i] = new Color({ hex: color.quickList[i].substring(1) });
+                grid.append('<span class="jPicker_QuickColor" title="#' + color.quickList[i].hex + '">&nbsp;</span>');
+                $('.jPicker_QuickColor', container).eq(i).css({ backgroundColor: '#' + color.quickList[i].hex }).bind('click', { i: i }, quickPickClicked);
+              }
+            }
+            setColorMode(color.mode);
+            colorPicker.fields.hex.val(colorBar.hex);
+            colorPicker.setValuesFromHex();
+            colorPicker.setAlphaFromValue();
+            positionMapAndBarArrows();
+            updateVisuals();
+            if (!window.expandable) $this.show();
+            List.push($this);
+          });
+      };
+  $.fn.jPicker.defaults = /* jPicker defaults - you can change anything in this section (such as the clientPath to your images) without fear of breaking the program */
+      {
+      window:
+        {
+          title: null, /* any title for the jPicker window itself - displays "Drag Markers To Pick A Color" if left null */
+          position:
+          {
+            x: 'screenCenter', /* acceptable values "left", "center", "right", "screenCenter", or relative px value */
+            y: 'top' /* acceptable values "top", "bottom", "center", or relative px value */
+          },
+          expandable: false, /* default to large static picker - set to true to make an expandable picker (small icon with popup) - set automatically when binded to input element */
+          liveUpdate: true /* set false if you want the user to have to click "OK" before the binded input box updates values */
+        },
+      color:
+        {
+          mode: 'h', /* acceptabled values "h" (hue), "s" (saturation), "v" (brightness), "r" (red), "g" (green), "b" (blue) */
+          active: new Color({ hex: 'ffc000' }), /* acceptable values are any declared $.jPicker.Color object or string HEX value (e.g. #ffc000) INCLUDING the "#" prefix */
+          alphaSupport: false, /* change to true to enable alpha editing support (without this, alpha will always be 100) */
+          quickList: /* the quick pick color list */
+            [
+              new Color({ h: 360, s: 33, v: 100 }), /* acceptable values are any declared $.jPicker.Color object or string HEX value (e.g. #ffc000) INCLUDING the "#" prefix */
+              new Color({ h: 360, s: 66, v: 100 }),
+              new Color({ h: 360, s: 100, v: 100 }),
+              new Color({ h: 360, s: 100, v: 75 }),
+              new Color({ h: 360, s: 100, v: 50 }),
+              new Color({ h: 180, s: 0, v: 100 }),
+              new Color({ h: 30, s: 33, v: 100 }),
+              new Color({ h: 30, s: 66, v: 100 }),
+              new Color({ h: 30, s: 100, v: 100 }),
+              new Color({ h: 30, s: 100, v: 75 }),
+              new Color({ h: 30, s: 100, v: 50 }),
+              new Color({ h: 180, s: 0, v: 90 }),
+              new Color({ h: 60, s: 33, v: 100 }),
+              new Color({ h: 60, s: 66, v: 100 }),
+              new Color({ h: 60, s: 100, v: 100 }),
+              new Color({ h: 60, s: 100, v: 75 }),
+              new Color({ h: 60, s: 100, v: 50 }),
+              new Color({ h: 180, s: 0, v: 80 }),
+              new Color({ h: 90, s: 33, v: 100 }),
+              new Color({ h: 90, s: 66, v: 100 }),
+              new Color({ h: 90, s: 100, v: 100 }),
+              new Color({ h: 90, s: 100, v: 75 }),
+              new Color({ h: 90, s: 100, v: 50 }),
+              new Color({ h: 180, s: 0, v: 70 }),
+              new Color({ h: 120, s: 33, v: 100 }),
+              new Color({ h: 120, s: 66, v: 100 }),
+              new Color({ h: 120, s: 100, v: 100 }),
+              new Color({ h: 120, s: 100, v: 75 }),
+              new Color({ h: 120, s: 100, v: 50 }),
+              new Color({ h: 180, s: 0, v: 60 }),
+              new Color({ h: 150, s: 33, v: 100 }),
+              new Color({ h: 150, s: 66, v: 100 }),
+              new Color({ h: 150, s: 100, v: 100 }),
+              new Color({ h: 150, s: 100, v: 75 }),
+              new Color({ h: 150, s: 100, v: 50 }),
+              new Color({ h: 180, s: 0, v: 50 }),
+              new Color({ h: 180, s: 33, v: 100 }),
+              new Color({ h: 180, s: 66, v: 100 }),
+              new Color({ h: 180, s: 100, v: 100 }),
+              new Color({ h: 180, s: 100, v: 75 }),
+              new Color({ h: 180, s: 100, v: 50 }),
+              new Color({ h: 180, s: 0, v: 40 }),
+              new Color({ h: 210, s: 33, v: 100 }),
+              new Color({ h: 210, s: 66, v: 100 }),
+              new Color({ h: 210, s: 100, v: 100 }),
+              new Color({ h: 210, s: 100, v: 75 }),
+              new Color({ h: 210, s: 100, v: 50 }),
+              new Color({ h: 180, s: 0, v: 30 }),
+              new Color({ h: 240, s: 33, v: 100 }),
+              new Color({ h: 240, s: 66, v: 100 }),
+              new Color({ h: 240, s: 100, v: 100 }),
+              new Color({ h: 240, s: 100, v: 75 }),
+              new Color({ h: 240, s: 100, v: 50 }),
+              new Color({ h: 180, s: 0, v: 20 }),
+              new Color({ h: 270, s: 33, v: 100 }),
+              new Color({ h: 270, s: 66, v: 100 }),
+              new Color({ h: 270, s: 100, v: 100 }),
+              new Color({ h: 270, s: 100, v: 75 }),
+              new Color({ h: 270, s: 100, v: 50 }),
+              new Color({ h: 180, s: 0, v: 10 }),
+              new Color({ h: 300, s: 33, v: 100 }),
+              new Color({ h: 300, s: 66, v: 100 }),
+              new Color({ h: 300, s: 100, v: 100 }),
+              new Color({ h: 300, s: 100, v: 75 }),
+              new Color({ h: 300, s: 100, v: 50 }),
+              new Color({ h: 180, s: 0, v: 0 }),
+              new Color({ h: 330, s: 33, v: 100 }),
+              new Color({ h: 330, s: 66, v: 100 }),
+              new Color({ h: 330, s: 100, v: 100 }),
+              new Color({ h: 330, s: 100, v: 75 }),
+              new Color({ h: 330, s: 100, v: 50 })
+            ]
+        },
+      images:
+        {
+          clientPath: '/jPicker/images/', /* Path to image files */
+          colorMap:
+          {
+            width: 256,
+            height: 256,
+            arrow:
+            {
+              file: 'mappoint.gif', /* ColorMap arrow icon */
+              width: 15,
+              height: 15
+            }
+          },
+          colorBar:
+          {
+            width: 20,
+            height: 256,
+            arrow:
+            {
+              file: 'rangearrows.gif', /* ColorBar arrow icon */
+              width: 40,
+              height: 9
+            }
+          },
+          alphaBar:
+          {
+            width: 256,
+            height: 20,
+            arrow:
+            {
+              file: 'rangearrows2.gif', /* AlphaBar arrow icon */
+              width: 9,
+              height: 40
+            }
+          },
+          picker:
+          {
+            file: 'picker.gif', /* Color Picker icon */
+            width: 25,
+            height: 24
+          }
+        }
+    };
+})(jQuery, '1.0.9');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/editor/jpicker/jpicker-1.0.9.min.js	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,1 @@
+(function(e,a){var d=function(n,k){var p=this,o=e("img",n),l=function(q){h(q);e(document).bind("mousemove",m).bind("mouseup",j);q.stopPropagation();q.preventDefault();return false;},m=function(q){h(q);q.stopPropagation();q.preventDefault();return false;},j=function(q){e(document).unbind("mouseup",j).unbind("mousemove",m);q.stopPropagation();q.preventDefault();return false;},h=function(u){var w=n.offset(),q=u.pageX-w.left-parseInt(n.css("border-left-width")),z=u.pageY-w.top-parseInt(n.css("border-top-width")),t=n.w,r=n.h,v,s;if(q<0){q=0;}else{if(q>t){q=t;}}if(z<0){z=0;}else{if(z>r){z=r;}}v=Math.floor(q/t*p.mxX);s=Math.floor(z/r*p.mxY);p.x=v;p.y=s;if(p.mxX==p.mnX){q=0;}if(p.mxY==p.mnY){z=0;}p.setArrowPosition(q,z);e.isFunction(p.valuesChanged)&&p.valuesChanged(p);};e.extend(true,p,{settings:k,x:0,y:0,mnX:0,mxX:0,mnY:100,mxY:100,valuesChanged:e.isFunction(arguments[2])&&arguments[2]||null,setPositioningVariables:function(r){var q=p.settings.map;n.w=q&&q.width||n.width();n.h=q&&q.height||n.height();p.MinX=0;p.MinY=0;p.MaxX=n.w;p.MaxY=n.h;},setArrowPositionFromValues:function(t){p.setPositioningVariables();var w=0,v=0,u=p.mnX,r=p.mxX,s=p.mnY,q=p.mxY,A=p.x,z=p.y;if(u!=r){if(A==u){w=0;}else{if(A==r){w=n.w;}else{if(u<1){r+=Math.abs(u)+1;}if(A<1){A+=1;}w=A/r*n.w;if(parseInt(w)==(r-1)){w=r;}else{w=parseInt(w);}if(u<1){w-=Math.abs(u)-1;}}}}if(s!=q){if(z==s){v=0;}else{if(z==q){v=n.h;}else{if(s<1){q+=Math.abs(s)+1;}if(z<1){z+=1;}v=z/q*n.h;if(parseInt(v)==(q-1)){v=q;}else{v=parseInt(v);}if(s<1){v-=Math.abs(s)-1;}}}}p.setArrowPosition(w,v);},setArrowPosition:function(q,v){var u=n.w,s=n.h,t=o.w,r=o.h;if(q<0){q=0;}else{if(q>u){q=u;}}if(v<0){v=0;}else{if(v>s){v=s;}}if(t>u){q=(u>>1)-(t>>1);}else{q-=t>>1;}if(r>s){v=(s>>1)-(r>>1);}else{v-=r>>1;}o.css({left:q+"px",top:v+"px"});},destroy:function(){e(document).unbind("mouseup",j).unbind("mousemove",m);n.unbind("mousedown",l);n=null;o=null;p.valuesChanged=null;}});o.src=p.settings.arrow&&p.settings.arrow.image;o.w=p.settings.arrow&&p.settings.arrow.width||o.width();o.h=p.settings.arrow&&p.settings.arrow.height||o.height();p.setPositioningVariables();n.bind("mousedown",l);p.setArrowPositionFromValues();e.isFunction(p.valuesChanged)&&p.valuesChanged(p);},b=function(n){var m=this,y=function(A){if(A.target.value==""){return;}t(A);m.setValuesFromHsv();e.isFunction(m.valuesChanged)&&m.valuesChanged(m);},s=function(A){if(A.target.value==""){return;}q(A);m.setValuesFromRgb();e.isFunction(m.valuesChanged)&&m.valuesChanged(m);},r=function(A){if(A.target.value==""){return;}l(A);w.a=A.target.value;e.isFunction(m.valuesChanged)&&m.valuesChanged(m);},v=function(A){if(A.target.value==""){m.setValuesFromRgb();}},k=function(A){if(A.target.value==""){m.setValuesFromHsv();}},o=function(A){if(A.target.value==""){u.alpha.val(100);}},z=function(A){if(A.target.value==""){return;}x(A);m.setValuesFromHex();e.isFunction(m.valuesChanged)&&m.valuesChanged(m);},j=function(A){if(A.target.value==""){m.setValuesFromHsv();}},q=function(A){if(!p(A)){return A;}u.red.val(h(u.red.val(),0,255));u.green.val(h(u.green.val(),0,255));u.blue.val(h(u.blue.val(),0,255));},l=function(A){if(!p(A)){return A;}u.alpha.val(h(u.alpha.val(),0,100));},t=function(A){if(!p(A)){return A;}u.hue.val(h(u.hue.val(),0,360));u.saturation.val(h(u.saturation.val(),0,100));u.value.val(h(u.value.val(),0,100));},x=function(A){if(!p(A)){return A;}u.hex.val(u.hex.val().replace(/[^a-fA-F0-9]/g,"0").toLowerCase().substring(0,6));},p=function(A){switch(A.keyCode){case 9:case 16:case 29:case 37:case 38:case 40:return false;case"c".charCodeAt():case"v".charCodeAt():if(A.ctrlKey){return false;}}return true;},h=function(C,B,A){if(C==""||isNaN(C)){return B;}C=parseInt(C);if(C>A){return A;}if(C<B){return B;}return C;};e.extend(true,m,{color:new f(),fields:{hue:e(".jPicker_HueText",n),saturation:e(".jPicker_SaturationText",n),value:e(".jPicker_BrightnessText",n),red:e(".jPicker_RedText",n),green:e(".jPicker_GreenText",n),blue:e(".jPicker_BlueText",n),hex:e(".jPicker_HexText",n),alpha:e(".jPicker_AlphaText",n)},valuesChanged:e.isFunction(arguments[1])&&arguments[1]||null,bindedHexKeyUp:function(A){z(A);},setValuesFromRgb:function(){w.fromRgb(u.red.val(),u.green.val(),u.blue.val());u.hex.val(w.hex);u.hue.val(w.h);u.saturation.val(w.s);u.value.val(w.v);},setValuesFromHsv:function(){w.fromHsv(u.hue.val(),u.saturation.val(),u.value.val());u.hex.val(w.hex);u.red.val(w.r);u.green.val(w.g);u.blue.val(w.b);},setValuesFromHex:function(){w.fromHex(u.hex.val());u.red.val(w.r);u.green.val(w.g);u.blue.val(w.b);u.hue.val(w.h);u.saturation.val(w.s);u.value.val(w.v);},setAlphaFromValue:function(){w.a=u.alpha.val();},destroy:function(){u.hue.add(u.saturation).add(u.value).unbind("keyup",events.hsvKeyUp).unbind("blur",v);u.red.add(u.green).add(u.blue).unbind("keyup",events.rgbKeyUp).unbind("blur",k);u.alpha.unbind("keyup",r).unbind("blur",o);u.hex.unbind("keyup",z);u=null;w=null;m.valuesChanged=null;}});var u=m.fields,w=m.color;u.hue.add(u.saturation).add(u.value).bind("keyup",y).bind("blur",v);u.red.add(u.green).add(u.blue).bind("keyup",s).bind("blur",k);u.alpha.bind("keyup",r).bind("blur",o);u.hex.bind("keyup",z).bind("blur",j);if(u.hex.val()!=""){w.fromHex(u.hex.val());m.setValuesFromHex();}};e.jPicker={List:[],Color:function(j){var h=this;e.extend(true,h,{r:0,g:0,b:0,h:0,s:0,v:0,a:100,hex:"",fromRgb:function(m,l,k){var o=this;o.r=m;o.g=l;o.b=k;var n=g.rgbToHsv(o);o.h=n.h;o.s=n.s;o.v=n.v;o.hex=g.rgbToHex(o);},fromHsv:function(m,l,k){var o=this;o.h=m;o.s=l;o.v=k;var n=g.hsvToRgb(o);o.r=n.r;o.g=n.g;o.b=n.b;o.hex=g.rgbToHex(n);},fromHex:function(k){var n=this;n.hex=k;var m=g.hexToRgb(k);n.r=m.r;n.g=m.g;n.b=m.b;var l=g.rgbToHsv(m);n.h=l.h;n.s=l.s;n.v=l.v;n.hex=g.rgbToHex(m);}});if(j){if(j.hex){h.fromHex(j.hex);}else{if(!isNaN(j.r)){h.fromRgb(j.r,j.g,j.b);}else{if(!isNaN(j.h)){h.fromHsv(j.h,j.s,j.v);}}}if(!isNaN(j.a)){h.a=j.a;}}},ColorMethods:{hexToRgb:function(l){l=this.validateHex(l);var k="00",j="00",h="00";if(l.length==6){k=l.substring(0,2);j=l.substring(2,4);h=l.substring(4,6);}else{if(l.length>4){k=l.substring(4,l.length);l=l.substring(0,4);}if(l.length>2){j=l.substring(2,l.length);l=l.substring(0,2);}if(l.length>0){h=l.substring(0,l.length);}}return{r:this.hexToInt(k),g:this.hexToInt(j),b:this.hexToInt(h)};},validateHex:function(h){h=h.toLowerCase().replace(/[^a-f0-9]/g,"0");if(h.length>6){h=h.substring(0,6);}return h;},rgbToHex:function(h){return this.intToHex(h.r)+this.intToHex(h.g)+this.intToHex(h.b);},intToHex:function(j){var h=parseInt(j).toString(16);if(h.length==1){h=("0"+h);}return h.toLowerCase();},hexToInt:function(h){return parseInt(h,16);},rgbToHsv:function(l){var o=l.r/255,n=l.g/255,j=l.b/255,k={h:0,s:0,v:0},m=0,h=0,p;if(o>=n&&o>=j){h=o;m=n>j?j:n;}else{if(n>=j&&n>=o){h=n;m=o>j?j:o;}else{h=j;m=n>o?o:n;}}k.v=h;k.s=h?(h-m)/h:0;if(!k.s){k.h=0;}else{p=h-m;if(o==h){k.h=(n-j)/p;}else{if(n==h){k.h=2+(j-o)/p;}else{k.h=4+(o-n)/p;}}k.h=parseInt(k.h*60);if(k.h<0){k.h+=360;}}k.s=parseInt(k.s*100);k.v=parseInt(k.v*100);return k;},hsvToRgb:function(n){var r={r:0,g:0,b:0},m=n.h,x=n.s,u=n.v;if(x==0){if(u==0){r.r=r.g=r.b=0;}else{r.r=r.g=r.b=parseInt(u*255/100);}}else{if(m==360){m=0;}m/=60;x=x/100;u=u/100;var l=parseInt(m),o=m-l,k=u*(1-x),j=u*(1-(x*o)),w=u*(1-(x*(1-o)));switch(l){case 0:r.r=u;r.g=w;r.b=k;break;case 1:r.r=j;r.g=u;r.b=k;break;case 2:r.r=k;r.g=u;r.b=w;break;case 3:r.r=k;r.g=j;r.b=u;break;case 4:r.r=w;r.g=k;r.b=u;break;case 5:r.r=u;r.g=k;r.b=j;break;}r.r=parseInt(r.r*255);r.g=parseInt(r.g*255);r.b=parseInt(r.b*255);}return r;}}};var f=e.jPicker.Color,c=e.jPicker.List,g=e.jPicker.ColorMethods;e.fn.jPicker=function(j){var h=arguments;return this.each(function(){var w=e(this),y=e.extend(true,{},e.fn.jPicker.defaults,j);if(w.get(0).nodeName.toLowerCase()=="input"){e.extend(true,y,{window:{bindToInput:true,expandable:true,input:w}});if(g.validateHex(w.val())){y.color.active=new f({hex:w.val(),a:y.color.active.a});y.color.current=new f({hex:w.val(),a:y.color.active.a});}}if(y.window.expandable){w.after('<span class="jPicker_Picker"><span class="jPicker_Color">&nbsp;</span><span class="jPicker_Icon" title="Click To Open Color Picker">&nbsp;</span><span class="jPicker_Container">&nbsp;</span></span>');}else{y.window.liveUpdate=false;}var W=parseFloat(navigator.appVersion.split("MSIE")[1])<7&&document.body.filters,ax=null,aw=null,av=null,U=null,T=null,S=null,R=null,Q=null,aC=null,V=null,au=null,J=null,I=null,X=null,ac=null,az=null,ak=null,am=null,ao=null,K=null,G=null,aa=null,L=null,ay=null,P=null,O=null,at=null,aq=null,A=null,l=null,M=null,ap=null,ad=null,ai=null,n=null,C=null,u=null,an=function(aE){N.active=ay.color;var aF=N.active,aG=p.clientPath,aD=function(aH){ae(aH,100);aH.css({backgroundColor:"",backgroundPosition:"0px 0px",filter:""});};aD(ax);aD(aw);aD(U);aD(T);aD(S);aD(R);ac.add(az).add(ak).add(am).add(ao).add(K).removeAttr("checked");switch(aE){case"h":ac.attr("checked",true);ax.css({backgroundColor:"#"+aF.hex});aw.css({backgroundColor:"transparent"});x(aw,-256);ae(aw,100);x(R,-256);G.mxX=100;G.mxY=100;aa.mxY=360;break;case"s":az.attr("checked",true);x(ax,-512);x(aw,-768);ae(aw,0);z(S,aF.hex);x(R,-512);G.mxX=360;G.mxY=100;aa.mxY=100;break;case"v":ak.attr("checked",true);z(ax,"000");x(aw,-1024);S.css({backgroundColor:"#"+aF.hex});x(R,-768);G.mxX=360;G.mxY=100;aa.mxY=100;break;case"r":am.attr("checked",true);x(aw,-1536);x(ax,-1280);x(R,-1024);x(S,-1280);x(T,-1536);x(U,-1792);break;case"g":ao.attr("checked",true);x(aw,-2048);x(ax,-1792);x(R,-2048);x(S,-2304);x(T,-2560);x(U,-2816);break;case"b":K.attr("checked",true);x(aw,-2560);x(ax,-2304);x(R,-3072);x(S,-3328);x(T,-3584);x(U,-3840);break;default:throw ("Invalid Mode");break;}switch(aE){case"h":case"s":case"v":G.mnX=1;G.mnY=1;aa.mnY=1;break;case"r":case"g":case"b":G.mnX=0;G.mnY=0;aa.mnY=0;G.mxX=255;G.mxY=255;aa.mxY=255;break;}N.mode=aE;v();ar();ab();if(aj.expandable&&aj.liveUpdate){n.css({backgroundColor:"#"+aF.hex});if(aj.bindToInput){aj.input.val(aF.hex).css({backgroundColor:"#"+aF.hex,color:aF.v>75?"#000000":"#ffffff"});}}e.isFunction(w.liveCallback)&&w.liveCallback(aF);},m=function(){v();ah();N.active=ay.color;var aD=N.active;if(aj.expandable&&aj.liveUpdate){n.css({backgroundColor:"#"+aD.hex});if(aj.bindToInput){aj.input.val(ay.fields.hex.val()).css({backgroundColor:"#"+aD.hex,color:aD.v>75?"#000000":"#ffffff"});}}e.isFunction(w.liveCallback)&&w.liveCallback(aD);},B=function(){if(!ay||!G||!aa||!L){return;}N.active=ay.color;var aD=ay.fields,aE=N.active;switch(N.mode){case"h":aD.saturation.val(G.x);aD.value.val(100-G.y);break;case"s":aD.hue.val(G.x);aD.value.val(100-G.y);break;case"v":aD.hue.val(G.x);aD.saturation.val(100-G.y);break;case"r":aD.blue.val(G.x);aD.green.val(255-G.y);break;case"g":aD.blue.val(G.x);aD.red.val(255-G.y);break;case"b":aD.red.val(G.x);aD.green.val(255-G.y);break;}switch(N.mode){case"h":case"s":case"v":ay.setValuesFromHsv();break;case"r":case"g":case"b":ay.setValuesFromRgb();break;}ah();if(aj.expandable&&aj.liveUpdate){n.css({backgroundColor:"#"+aE.hex});if(aj.bindToInput){aj.input.val(aE.hex).css({backgroundColor:"#"+aE.hex,color:aE.v>75?"#000000":"#ffffff"});}}e.isFunction(w.liveCallback)&&w.liveCallback(aE);},al=function(){if(!ay||!G||!aa||!L){return;}N.active=ay.color;var aD=ay.fields,aE=N.active;switch(N.mode){case"h":aD.hue.val(360-aa.y);break;case"s":aD.saturation.val(100-aa.y);break;case"v":aD.value.val(100-aa.y);break;case"r":aD.red.val(255-aa.y);break;case"g":aD.green.val(255-aa.y);break;case"b":aD.blue.val(255-aa.y);break;}switch(N.mode){case"h":case"s":case"v":ay.setValuesFromHsv();break;case"r":case"g":case"b":ay.setValuesFromRgb();break;}ah();if(aj.expandable&&aj.liveUpdate){n.css({backgroundColor:"#"+aE.hex});if(aj.bindToInput){aj.input.val(aE.hex).css({backgroundColor:"#"+aE.hex,color:aE.v>75?"#000000":"#ffffff"});}}e.isFunction(w.liveCallback)&&w.liveCallback(aE);},s=function(){if(!ay||!G||!aa||!L){return;}N.active=ay.color;var aD=ay.fields,aE=N.active;aD.alpha.val(L.x);ay.setAlphaFromValue();ah();e.isFunction(w.liveCallback)&&w.liveCallback(N.active);},v=function(){N.active=ay.color;var aG=0,aF=N.active;switch(w.settings.color.mode){case"h":aG=360-aF.h;break;case"s":aG=100-aF.s;break;case"v":aG=100-aF.v;break;case"r":aG=255-aF.r;break;case"g":aG=255-aF.g;break;case"b":aG=255-aF.b;break;}aa.y=aG;L.x=aF.a;aa.setArrowPositionFromValues();L.setArrowPositionFromValues();var aE=0,aD=0;switch(w.settings.color.mode){case"h":aE=aF.s;aD=100-aF.v;break;case"s":aE=aF.h;aD=100-aF.v;break;case"v":aE=aF.h;aD=100-aF.s;break;case"r":aE=aF.b;aD=256-aF.g;break;case"g":aE=aF.b;aD=256-aF.r;break;case"b":aE=aF.r;aD=256-aF.g;break;}G.x=aE;G.y=aD;G.setArrowPositionFromValues();},ah=function(){aB();ar();ab();aA();},aB=function(){try{A.css({backgroundColor:"#"+ay.color.hex});ae(A,ay.color.a);}catch(aD){}},ar=function(){if(!N||!ay){return;}N.active=ay.color;var aD=N.active;switch(N.mode){case"h":z(ax,new f({h:aD.h,s:100,v:100}).hex);break;case"s":ae(aw,100-aD.s);break;case"v":ae(aw,aD.v);break;case"r":ae(aw,aD.r/256*100);break;case"g":ae(aw,aD.g/256*100);break;case"b":ae(aw,aD.b/256*100);break;}ae(av,100-aD.a);},ab=function(){if(!N||!ay){return;}N.active=ay.color;var aH=N.active,aK=N.mode,aM=ay.fields;switch(aK){case"h":break;case"s":var aI=new f({h:aH.h,s:100,v:aH.v});z(S,aI.hex);break;case"v":var aL=new f({h:aH.h,s:aH.s,v:100});z(S,aL.hex);break;case"r":case"g":case"b":var aJ=0,aN=0;if(aK=="r"){aJ=aM.blue.val();aN=aM.green.val();}else{if(aK=="g"){aJ=aM.blue.val();aN=aM.red.val();}else{if(aK=="b"){aJ=aM.red.val();aN=aM.green.val();}}}var aD=aJ/256*100,aG=aN/256*100,aF=(256-aJ)/256*100,aE=(256-aN)/256*100;ae(R,aG>aF?aF:aG);ae(S,aG>aD?aD:aG);ae(T,aE>aD?aD:aE);ae(U,aE>aF?aF:aE);break;}ae(Q,100-aH.a);},aA=function(){z(J,ay.color.hex);},z=function(aD,aF){try{aD.css({backgroundColor:"#"+aF});}catch(aE){}},t=function(aD,aE){if(aE.indexOf("png")&&this.isLessThanIE7){aD.attr("pngSrc",aE);aD.css({backgroundImage:"none",filter:"progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+aE+"')"});}else{aD.css({backgroundImage:"url("+aE+")"});}},x=function(aD,aE){aD.css({backgroundPosition:"0px "+aE+"px"});},ae=function(aE,aD){if(aD<100){if(this.isLessThanIE7){var aF=aE.attr("pngSrc");if(aF!=null&&aF.indexOf("map-hue")==-1){aE.css({filter:"progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+aF+"') progid:DXImageTransform.Microsoft.Alpha(opacity="+aD+")"});}}else{aE.css({opacity:aD/100});}}else{if(aD==100){if(this.isLessThanIE7){var aF=aE.attr("pngSrc");if(aF!=null&&aF.indexOf("map-hue")==-1){aE.css({filter:"progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+aF+"')"});}}else{aE.css({opacity:""});}}}},E=function(){ay.fields.hex.val(N.current.hex);ay.fields.alpha.val(N.current.a);ay.setValuesFromHex();ay.setAlphaFromValue();e.isFunction(ay.valuesChanged)&&ay.valuesChanged(ay);},D=function(aD){an(aD.target.value);},af=function(){E();},r=function(){E();aj.expandable&&w.hide();e.isFunction(w.cancelCallback)&&w.cancelCallback();},Z=function(){var aD=N.active;N.current=new f({hex:aD.hex});N.current.a=aD.a;l.css({backgroundColor:"#"+aD.hex});ae(l,ay.color.a);if(aj.expandable){n.css({backgroundColor:"#"+aD.hex});if(aj.bindToInput){aj.input.val(aD.hex).css({backgroundColor:"#"+aD.hex,color:aD.v>75?"#000000":"#ffffff"});}}e.isFunction(w.commitCallback)&&w.commitCallback(aD);},o=function(){Z();aj.expandable&&w.hide();},ag=function(){w.show();},Y=function(aF){var aD=aj.element,aE=aj.page;P=parseInt(X.css("left"));O=parseInt(X.css("top"));at=aF.pageX;aq=aF.pageY;e(document).bind("mousemove",k).bind("mouseup",q);aF.stopPropagation();aF.preventDefault();return false;},k=function(aD){X.css({left:P-(at-aD.pageX)+"px",top:O-(aq-aD.pageY)+"px"});aD.stopPropagation();aD.preventDefault();return false;},q=function(aD){e(document).unbind("mousemove",k).unbind("mouseup",q);aD.stopPropagation();aD.preventDefault();return false;},F=function(aD){ay.fields.hex.val(w.settings.window.input.val());ay.bindedHexKeyUp(aD);},H=function(aD){ay.fields.hex.val(N.quickList[aD.data.i].hex);ay.fields.alpha.val(N.quickList[aD.data.i].a);ay.setValuesFromHex();ay.setAlphaFromValue();e.isFunction(ay.valuesChanged)&&ay.valuesChanged(ay);};e.extend(true,w,{id:w.attr("id"),settings:y,color:null,icon:null,commitCallback:e.isFunction(h[1])&&h[1]||null,liveCallback:e.isFunction(h[2])&&h[2]||null,cancelCallback:e.isFunction(h[3])&&h[3]||null,show:function(){if(document.all){var aD=false;for(i=0;i<c.length;i++){if(aD){c[i].color.add(c[i].icon).css({display:"none"});}if(c[i].id==w.id){aD=true;}}}N.current=new f({hex:N.active.hex,a:N.active.a});l.css({backgroundColor:"#"+N.active.hex});ae(l,N.active.a);X.css({display:"block"});G.setPositioningVariables();aa.setPositioningVariables();v();},hide:function(){if(document.all){var aD=false;for(i=0;i<c.length;i++){if(aD){c[i].color.add(c[i].icon).css({display:"block"});}if(c[i].id==w.id){aD=true;}}}X.css({display:"none"});},destroy:function(){if(aj.expandable){C=e(".jPicker_Icon",X).unbind("click",ag);}if(aj.bindToInput){aj.input.unbind("keyup",F).unbind("change",F);}ac.add(az).add(ak).add(am).add(ao).add(K).unbind("click",D);l.unbind("click",af);ad.unbind("click",r);ap.unbind("click",o);if(aj.expandable){u.unbind("mousedown",Y);}e(".jPicker_QuickColor",X).unbind("click",H);ac=null;az=null;ak=null;am=null;ao=null;K=null;ax=null;aw=null;av=null;U=null;T=null;S=null;R=null;Q=null;aC=null;V=null;au=null;J=null;I=null;M=null;A=null;l=null;ap=null;ad=null;ai=null;w.color=null;w.icon=null;G.destroy();G=null;aa.destroy();aa=null;L.destroy();L=null;ay.destroy();ay=null;w.commitCallback=null;w.cancelCallback=null;w.liveCallback=null;X.html("");for(i=0;i<c.length;i++){if(c[i].id==w.id){c.splice(i,1);}}}});var p=w.settings.images,aj=w.settings.window,N=w.settings.color;X=aj.expandable?e(".jPicker_Container",w.next()):w;if(aj.expandable){X.css({left:aj.position.x=="left"?"-526px":aj.position.x=="center"?"-259px":aj.position.x=="right"?"0px":aj.position.x=="screenCenter"?((e(document).width()>>1)-259)-w.next().offset().left+"px":aj.position.x,position:"absolute",top:aj.position.y=="top"?"-340px":aj.position.y=="center"?"-153px":aj.position.y=="bottom"?"25px":aj.position.y});}if((typeof(N.active)).toString().toLowerCase()=="string"){N.active=new f({hex:N.active.substring(1)});}if(!N.alphaSupport){N.active.a=100;}X.html('<table class="jPicker_table"><tbody>'+(aj.expandable?'<tr><td class="jPicker_MoveBar" colspan="6">&nbsp;</td></tr>':"")+'<tr><td rowspan="8"><h2 class="jPicker_Title">'+(aj.title||"Drag Markers To Pick A Color")+'</h2><div class="jPicker_ColorMap"><span class="jPicker_ColorMap_l1">&nbsp;</span><span class="jPicker_ColorMap_l2">&nbsp;</span><span class="jPicker_ColorMap_l3">&nbsp;</span><img src="'+p.clientPath+p.colorMap.arrow.file+'" class="jPicker_ColorMap_Arrow"/></div></td><td rowspan="8"><div class="jPicker_ColorBar"><span class="jPicker_ColorBar_l1">&nbsp;</span><span class="jPicker_ColorBar_l2">&nbsp;</span><span class="jPicker_ColorBar_l3">&nbsp;</span><span class="jPicker_ColorBar_l4">&nbsp;</span><span class="jPicker_ColorBar_l5">&nbsp;</span><img src="'+p.clientPath+p.colorBar.arrow.file+'" class="jPicker_ColorBar_Arrow"/></div></td><td colspan="3" class="jPicker_Preview">new<div class="jPicker_NewCurrent"><span class="jPicker_Active" title="New Color - Press &ldquo;OK&rdquo; To Commit">&nbsp;</span><span class="jPicker_Current" title="Click To Revert To Original Color">&nbsp;</span></div>current</td><td rowspan="9" class="jPicker_OkCancel"><input type="button" class="jPicker_Ok" value="OK" title="Commit To This Color Selection"/><input type="button" class="jPicker_Cancel" value="Cancel" title="Cancel And Revert To Original Color"/><hr/><div class="jPicker_Grid">&nbsp;</div></td></tr><tr><td><input type="radio" class="jPicker_HueRadio" id="jPicker_Hue_'+c.length+'" name="jPicker_Mode_'+c.length+'" value="h" title="Set To &ldquo;Hue&rdquo; Color Mode"/></td><td><label for="jPicker_Hue_'+c.length+'" title="Set To &ldquo;Hue&rdquo; Color Mode">H:</label></td><td><input type="text" class="jPicker_HueText" value="'+N.active.h+'" title="Enter A &ldquo;Hue&rdquo; Value (0-360&deg;)"/> &deg;</td</tr><tr><td><input type="radio" class="jPicker_SaturationRadio" id="jPicker_Saturation_'+c.length+'" name="jPicker_Mode_'+c.length+'" value="s" title="Set To &ldquo;Saturation&rdquo; Color Mode"/></td><td><label for="jPicker_Saturation_'+c.length+'" title="Set To &ldquo;Saturation&rdquo; Color Mode">S:</label></td><td><input type="text" class="jPicker_SaturationText" value="'+N.active.s+'" title="Enter A &ldquo;Saturation&rdquo; Value (0-100%)"/> %</td></tr><tr><td><input type="radio" class="jPicker_BrightnessRadio" id="jPicker_Brightness_'+c.length+'" name="jPicker_Mode_'+c.length+'" value="v" title="Set To &ldquo;Brightness&rdquo; Color Mode"/></td><td><label for="jPicker_Brightness_'+c.length+'" title="Set To &ldquo;Brightness&rdquo; Color Mode">B:</label></td><td><input type="text" class="jPicker_BrightnessText" value="'+N.active.v+'" title="Enter A &ldquo;Brightness&rdquo; Value (0-100%)"/> %</td></tr><tr><td colspan="3" class="jPicker_Spacer">&nbsp;</td></tr><tr><td><input type="radio" class="jPicker_RedRadio" id="jPicker_Red_'+c.length+'" name="jPicker_Mode_'+c.length+'" value="r" title="Set To &ldquo;Red&rdquo; Color Mode"/></td><td><label for="jPicker_Red_'+c.length+'" title="Set To &ldquo;Red&rdquo; Color Mode">R:</label></td><td><input type="text" class="jPicker_RedText" value="'+N.active.r+'" title="Enter A &ldquo;Red&rdquo; Value (0-255)"/></td></tr><tr><td><input type="radio" class="jPicker_GreenRadio" id="jPicker_Green_'+c.length+'" name="jPicker_Mode_'+c.length+'" value="g" title="Set To &ldquo;Green&rdquo; Color Mode"/></td><td><label for="jPicker_Green_'+c.length+'" title="Set To &ldquo;Green&rdquo; Color Mode">G:</label></td><td><input type="text" class="jPicker_GreenText" value="'+N.active.g+'" title="Enter A &ldquo;Green&rdquo; Value (0-255)"/></td></tr><tr><td><input type="radio" class="jPicker_BlueRadio" id="jPicker_Blue_'+c.length+'" name="jPicker_Mode_'+c.length+'" value="b" title="Set To &ldquo;Blue&rdquo; Color Mode"/></td><td><label for="jPicker_Blue_'+c.length+'" title="Set To &ldquo;Blue&rdquo; Color Mode">B:</label></td><td><input type="text" class="jPicker_BlueText" value="'+N.active.b+'" title="Enter A &ldquo;Blue&rdquo; Value (0-255)"/></td></tr><tr><td><div class="jPicker_EnableAlpha"><input type="checkbox" class="jPicker_AlphaCheckbox" id="jPicker_AlphaCheckbox_'+c.length+'" title="Enable Alpha (Transparency) Support"/><label for="jPicker_AlphaCheckbox_'+c.length+'" title="Enabled Alpha (Transparency) Support">Enable Alpha (Transparency) Support</label></div><div class="jPicker_AlphaBar"><span class="jPicker_AlphaBar_l1">&nbsp;</span><span class="jPicker_AlphaBar_l2">&nbsp;</span><img src="'+p.clientPath+p.alphaBar.arrow.file+'" class="jPicker_AlphaBar_Arrow"/></div></td><td colspan="2" class="jPicker_OpacityCol"><label for="jPicker_Alpha_'+c.length+'" title="Enter An &ldquo;Alpha&rdquo; Value (0-100%)">A:</label><input type="text" class="jPicker_AlphaText" id="jPicker_Alpha_'+c.length+'" value="'+N.active.a+'" title="Enter An &ldquo;Alpha&rdquo; Value (0-100%)"/><span>%</span></td><td colspan="3" class="jPicker_HexCol"><label for="jPicker_Hex_'+c.length+'" title="Enter A &ldquo;Hex&rdquo; Color Value (#000000-#ffffff)">#:</label><input type="text" class="jPicker_HexText" id="jPicker_Hex_'+c.length+'" value="'+N.active.hex+'" title="Enter A &ldquo;Hex&rdquo; Color Value (#000000-#ffffff)"/></td><td colspan="2" class="jPicker_EnterHex"></td><td>&nbsp;</td></tr></tbody></table>');ac=e(".jPicker_HueRadio",X);az=e(".jPicker_SaturationRadio",X);ak=e(".jPicker_BrightnessRadio",X);am=e(".jPicker_RedRadio",X);ao=e(".jPicker_GreenRadio",X);K=e(".jPicker_BlueRadio",X);ax=e(".jPicker_ColorMap_l1",X);aw=e(".jPicker_ColorMap_l2",X);av=e(".jPicker_ColorMap_l3",X);U=e(".jPicker_ColorBar_l1",X);T=e(".jPicker_ColorBar_l2",X);S=e(".jPicker_ColorBar_l3",X);R=e(".jPicker_ColorBar_l4",X);Q=e(".jPicker_ColorBar_l5",X);J=e(".jPicker_AlphaBar_l1",X);I=e(".jPicker_AlphaBar_l2",X);aC=e(".jPicker_EnableAlpha",X);V=e(".jPicker_AlphaCheckbox",X);au=e(".jPicker_AlphaBar",X);M=e(".jPicker_NewCurrent",X);A=e(".jPicker_Active",X).css({backgroundColor:"#"+N.active.hex});l=e(".jPicker_Current",X).css({backgroundColor:"#"+N.active.hex});ap=e(".jPicker_Ok",X);ad=e(".jPicker_Cancel",X);ai=e(".jPicker_Grid",X);w.color=e(".Picker_Color");w.icon=e(".jPicker_Icon");ay=new b(X,m);G=new d(e(".jPicker_ColorMap",X),{map:{width:p.colorMap.width,height:p.colorMap.height},arrow:{image:p.clientPath+p.colorMap.arrow.file,width:p.colorMap.arrow.width,height:p.colorMap.arrow.height}},B);aa=new d(e(".jPicker_ColorBar",X),{map:{width:p.colorBar.width,height:p.colorBar.height},arrow:{image:p.clientPath+p.colorBar.arrow.file,width:p.colorBar.arrow.width,height:p.colorBar.arrow.height}},al);L=new d(e(".jPicker_AlphaBar",X),{map:{width:p.alphaBar.width,height:p.alphaBar.height},arrow:{image:p.clientPath+p.alphaBar.arrow.file,width:p.alphaBar.arrow.width,height:p.alphaBar.arrow.height}},s);L.mnX=0;L.mxX=100;t(ax,p.clientPath+"Maps.png");t(aw,p.clientPath+"Maps.png");t(av,p.clientPath+"map-opacity.png");t(U,p.clientPath+"Bars.png");t(T,p.clientPath+"Bars.png");t(S,p.clientPath+"Bars.png");t(R,p.clientPath+"Bars.png");t(Q,p.clientPath+"bar-opacity.png");t(I,p.clientPath+"Maps.png");x(I,-2816);t(M,p.clientPath+"preview-opacity.png");M.css({backgroundPosition:"1px 1px"});if(N.alphaSupport){aC.hide();au.show();e("td.jPicker_OpacityCol *",X).show();}else{V.bind("click",function(){aC.hide();au.show();e("td.jPicker_OpacityCol *",X).show();});}if(aj.expandable){n=e(".jPicker_Color",w.next()).css({backgroundColor:"#"+N.active.hex});C=e(".jPicker_Icon",w.next()).css({backgroundImage:"url("+p.clientPath+p.picker.file+")"}).bind("click",ag);if(aj.bindToInput){aj.input.bind("keyup",F).bind("change",F);}}ac.add(az).add(ak).add(am).add(ao).add(K).bind("click",D);l.bind("click",af);ad.bind("click",r);ap.bind("click",o);if(aj.expandable){u=e(".jPicker_MoveBar",X).bind("mousedown",Y);}if(N.quickList&&N.quickList.length>0){ai.html("");for(i=0;i<N.quickList.length;i++){if((typeof(N.quickList[i])).toString().toLowerCase()=="string"){N.quickList[i]=new f({hex:N.quickList[i].substring(1)});}ai.append('<span class="jPicker_QuickColor" title="#'+N.quickList[i].hex+'">&nbsp;</span>');e(".jPicker_QuickColor",X).eq(i).css({backgroundColor:"#"+N.quickList[i].hex}).bind("click",{i:i},H);}}an(N.mode);ay.fields.hex.val(aa.hex);ay.setValuesFromHex();ay.setAlphaFromValue();v();ah();if(!aj.expandable){w.show();}c.push(w);});};e.fn.jPicker.defaults={window:{title:null,position:{x:"screenCenter",y:"top"},expandable:false,liveUpdate:true},color:{mode:"h",active:new f({hex:"ffc000"}),alphaSupport:false,quickList:[new f({h:360,s:33,v:100}),new f({h:360,s:66,v:100}),new f({h:360,s:100,v:100}),new f({h:360,s:100,v:75}),new f({h:360,s:100,v:50}),new f({h:180,s:0,v:100}),new f({h:30,s:33,v:100}),new f({h:30,s:66,v:100}),new f({h:30,s:100,v:100}),new f({h:30,s:100,v:75}),new f({h:30,s:100,v:50}),new f({h:180,s:0,v:90}),new f({h:60,s:33,v:100}),new f({h:60,s:66,v:100}),new f({h:60,s:100,v:100}),new f({h:60,s:100,v:75}),new f({h:60,s:100,v:50}),new f({h:180,s:0,v:80}),new f({h:90,s:33,v:100}),new f({h:90,s:66,v:100}),new f({h:90,s:100,v:100}),new f({h:90,s:100,v:75}),new f({h:90,s:100,v:50}),new f({h:180,s:0,v:70}),new f({h:120,s:33,v:100}),new f({h:120,s:66,v:100}),new f({h:120,s:100,v:100}),new f({h:120,s:100,v:75}),new f({h:120,s:100,v:50}),new f({h:180,s:0,v:60}),new f({h:150,s:33,v:100}),new f({h:150,s:66,v:100}),new f({h:150,s:100,v:100}),new f({h:150,s:100,v:75}),new f({h:150,s:100,v:50}),new f({h:180,s:0,v:50}),new f({h:180,s:33,v:100}),new f({h:180,s:66,v:100}),new f({h:180,s:100,v:100}),new f({h:180,s:100,v:75}),new f({h:180,s:100,v:50}),new f({h:180,s:0,v:40}),new f({h:210,s:33,v:100}),new f({h:210,s:66,v:100}),new f({h:210,s:100,v:100}),new f({h:210,s:100,v:75}),new f({h:210,s:100,v:50}),new f({h:180,s:0,v:30}),new f({h:240,s:33,v:100}),new f({h:240,s:66,v:100}),new f({h:240,s:100,v:100}),new f({h:240,s:100,v:75}),new f({h:240,s:100,v:50}),new f({h:180,s:0,v:20}),new f({h:270,s:33,v:100}),new f({h:270,s:66,v:100}),new f({h:270,s:100,v:100}),new f({h:270,s:100,v:75}),new f({h:270,s:100,v:50}),new f({h:180,s:0,v:10}),new f({h:300,s:33,v:100}),new f({h:300,s:66,v:100}),new f({h:300,s:100,v:100}),new f({h:300,s:100,v:75}),new f({h:300,s:100,v:50}),new f({h:180,s:0,v:0}),new f({h:330,s:33,v:100}),new f({h:330,s:66,v:100}),new f({h:330,s:100,v:100}),new f({h:330,s:100,v:75}),new f({h:330,s:100,v:50})]},images:{clientPath:"/jPicker/images/",colorMap:{width:256,height:256,arrow:{file:"mappoint.gif",width:15,height:15}},colorBar:{width:20,height:256,arrow:{file:"rangearrows.gif",width:40,height:9}},alphaBar:{width:256,height:20,arrow:{file:"rangearrows2.gif",width:9,height:40}},picker:{file:"picker.gif",width:25,height:24}}};})(jQuery,"1.0.9");
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/editor/jquery.js	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,19 @@
+/*
+ * jQuery JavaScript Library v1.3.2
+ * http://jquery.com/
+ *
+ * Copyright (c) 2009 John Resig
+ * Dual licensed under the MIT and GPL licenses.
+ * http://docs.jquery.com/License
+ *
+ * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
+ * Revision: 6246
+ */
+(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F<J;F++){var G=M[F];if(G.selected){K=o(G).val();if(H){return K}L.push(K)}}return L}return(E.value||"").replace(/\r/g,"")}return g}if(typeof K==="number"){K+=""}return this.each(function(){if(this.nodeType!=1){return}if(o.isArray(K)&&/radio|checkbox/.test(this.type)){this.checked=(o.inArray(this.value,K)>=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G<E;G++){L.call(K(this[G],H),this.length>1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H<I;H++){if((G=arguments[H])!=null){for(var F in G){var K=J[F],L=G[F];if(J===L){continue}if(E&&L&&typeof L==="object"&&!L.nodeType){J[F]=o.extend(E,K||(L.length!=null?[]:{}),L)}else{if(L!==g){J[F]=L}}}}}return J};var b=/z-?index|font-?weight|opacity|zoom|line-?height/i,q=document.defaultView||{},s=Object.prototype.toString;o.extend({noConflict:function(E){l.$=p;if(E){l.jQuery=y}return o},isFunction:function(E){return s.call(E)==="[object Function]"},isArray:function(E){return s.call(E)==="[object Array]"},isXMLDoc:function(E){return E.nodeType===9&&E.documentElement.nodeName!=="HTML"||!!E.ownerDocument&&o.isXMLDoc(E.ownerDocument)},globalEval:function(G){if(G&&/\S/.test(G)){var F=document.getElementsByTagName("head")[0]||document.documentElement,E=document.createElement("script");E.type="text/javascript";if(o.support.scriptEval){E.appendChild(document.createTextNode(G))}else{E.text=G}F.insertBefore(E,F.firstChild);F.removeChild(E)}},nodeName:function(F,E){return F.nodeName&&F.nodeName.toUpperCase()==E.toUpperCase()},each:function(G,K,F){var E,H=0,I=G.length;if(F){if(I===g){for(E in G){if(K.apply(G[E],F)===false){break}}}else{for(;H<I;){if(K.apply(G[H++],F)===false){break}}}}else{if(I===g){for(E in G){if(K.call(G[E],E,G[E])===false){break}}}else{for(var J=G[0];H<I&&K.call(J,H,J)!==false;J=G[++H]){}}}return G},prop:function(H,I,G,F,E){if(o.isFunction(I)){I=I.call(H,F)}return typeof I==="number"&&G=="curCSS"&&!b.test(E)?I+"px":I},className:{add:function(E,F){o.each((F||"").split(/\s+/),function(G,H){if(E.nodeType==1&&!o.className.has(E.className,H)){E.className+=(E.className?" ":"")+H}})},remove:function(E,F){if(E.nodeType==1){E.className=F!==g?o.grep(E.className.split(/\s+/),function(G){return !o.className.has(F,G)}).join(" "):""}},has:function(F,E){return F&&o.inArray(E,(F.className||F).toString().split(/\s+/))>-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+"></"+T+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!O.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!O.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!O.indexOf("<td")||!O.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!O.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||!o.support.htmlSerialize&&[1,"div<div>","</div>"]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/<tbody/i.test(S),N=!O.indexOf("<table")&&!R?L.firstChild&&L.firstChild.childNodes:Q[1]=="<table>"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E<F;E++){if(H[E]===G){return E}}return -1},merge:function(H,E){var F=0,G,I=H.length;if(!o.support.getAll){while((G=E[F++])!=null){if(G.nodeType!=8){H[I++]=G}}}else{while((G=E[F++])!=null){H[I++]=G}}return H},unique:function(K){var F=[],E={};try{for(var G=0,H=K.length;G<H;G++){var J=o.data(K[G]);if(!E[J]){E[J]=true;F.push(K[G])}}}catch(I){F=K}return F},grep:function(F,J,E){var G=[];for(var H=0,I=F.length;H<I;H++){if(!E!=!J(F[H],H)){G.push(F[H])}}return G},map:function(E,J){var F=[];for(var G=0,H=E.length;G<H;G++){var I=J(E[G],G);if(I!=null){F[F.length]=I}}return F.concat.apply([],F)}});var C=navigator.userAgent.toLowerCase();o.browser={version:(C.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[0,"0"])[1],safari:/webkit/.test(C),opera:/opera/.test(C),msie:/msie/.test(C)&&!/opera/.test(C),mozilla:/mozilla/.test(C)&&!/(compatible|webkit)/.test(C)};o.each({parent:function(E){return E.parentNode},parents:function(E){return o.dir(E,"parentNode")},next:function(E){return o.nth(E,2,"nextSibling")},prev:function(E){return o.nth(E,2,"previousSibling")},nextAll:function(E){return o.dir(E,"nextSibling")},prevAll:function(E){return o.dir(E,"previousSibling")},siblings:function(E){return o.sibling(E.parentNode.firstChild,E)},children:function(E){return o.sibling(E.firstChild)},contents:function(E){return o.nodeName(E,"iframe")?E.contentDocument||E.contentWindow.document:o.makeArray(E.childNodes)}},function(E,F){o.fn[E]=function(G){var H=o.map(this,F);if(G&&typeof G=="string"){H=o.multiFilter(G,H)}return this.pushStack(o.unique(H),E,G)}});o.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(E,F){o.fn[E]=function(G){var J=[],L=o(G);for(var K=0,H=L.length;K<H;K++){var I=(K>0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}});
+/*
+ * Sizzle CSS Selector Engine - v0.9.3
+ *  Copyright 2009, The Dojo Foundation
+ *  Released under the MIT, BSD, and GPL Licenses.
+ *  More information: http://sizzlejs.com/
+ */
+(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa<ab.length;aa++){if(ab[aa]===ab[aa-1]){ab.splice(aa--,1)}}}}}return ab};F.matches=function(T,U){return F(T,null,null,U)};F.find=function(aa,T,ab){var Z,X;if(!aa){return[]}for(var W=0,V=I.order.length;W<V;W++){var Y=I.order[W],X;if((X=I.match[Y].exec(aa))){var U=RegExp.leftContext;if(U.substr(U.length-1)!=="\\"){X[1]=(X[1]||"").replace(/\\/g,"");Z=I.find[Y](X,T,ab);if(Z!=null){aa=aa.replace(I.match[Y],"");break}}}}if(!Z){Z=T.getElementsByTagName("*")}return{set:Z,expr:aa}};F.filter=function(ad,ac,ag,W){var V=ad,ai=[],aa=ac,Y,T,Z=ac&&ac[0]&&Q(ac[0]);while(ad&&ac.length){for(var ab in I.filter){if((Y=I.match[ab].exec(ad))!=null){var U=I.filter[ab],ah,af;T=false;if(aa==ai){ai=[]}if(I.preFilter[ab]){Y=I.preFilter[ab](Y,aa,ag,ai,W,Z);if(!Y){T=ah=true}else{if(Y===true){continue}}}if(Y){for(var X=0;(af=aa[X])!=null;X++){if(af){ah=U(af,Y,X,aa);var ae=W^!!ah;if(ag&&ah!=null){if(ae){T=true}else{aa[X]=false}}else{if(ae){ai.push(af);T=true}}}}}if(ah!==g){if(!ag){aa=ai}ad=ad.replace(I.match[ab],"");if(!T){return[]}break}}}if(ad==V){if(T==null){throw"Syntax error, unrecognized expression: "+ad}else{break}}V=ad}return aa};var I=F.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(T){return T.getAttribute("href")}},relative:{"+":function(aa,T,Z){var X=typeof T==="string",ab=X&&!/\W/.test(T),Y=X&&!ab;if(ab&&!Z){T=T.toUpperCase()}for(var W=0,V=aa.length,U;W<V;W++){if((U=aa[W])){while((U=U.previousSibling)&&U.nodeType!==1){}aa[W]=Y||U&&U.nodeName===T?U||false:U===T}}if(Y){F.filter(T,aa,true)}},">":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){var W=Y.parentNode;Z[V]=W.nodeName===U?W:false}}}else{for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){Z[V]=X?Y.parentNode:Y.parentNode===U}}if(X){F.filter(U,Z,true)}}},"":function(W,U,Y){var V=L++,T=S;if(!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("parentNode",U,V,W,X,Y)},"~":function(W,U,Y){var V=L++,T=S;if(typeof U==="string"&&!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("previousSibling",U,V,W,X,Y)}},find:{ID:function(U,V,W){if(typeof V.getElementById!=="undefined"&&!W){var T=V.getElementById(U[1]);return T?[T]:[]}},NAME:function(V,Y,Z){if(typeof Y.getElementsByName!=="undefined"){var U=[],X=Y.getElementsByName(V[1]);for(var W=0,T=X.length;W<T;W++){if(X[W].getAttribute("name")===V[1]){U.push(X[W])}}return U.length===0?null:U}},TAG:function(T,U){return U.getElementsByTagName(T[1])}},preFilter:{CLASS:function(W,U,V,T,Z,aa){W=" "+W[1].replace(/\\/g,"")+" ";if(aa){return W}for(var X=0,Y;(Y=U[X])!=null;X++){if(Y){if(Z^(Y.className&&(" "+Y.className+" ").indexOf(W)>=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return U<T[3]-0},gt:function(V,U,T){return U>T[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W<T;W++){if(Y[W]===Z){return false}}return true}}}},CHILD:function(T,W){var Z=W[1],U=T;switch(Z){case"only":case"first":while(U=U.previousSibling){if(U.nodeType===1){return false}}if(Z=="first"){return true}U=T;case"last":while(U=U.nextSibling){if(U.nodeType===1){return false}}return true;case"nth":var V=W[2],ac=W[3];if(V==1&&ac==0){return true}var Y=W[0],ab=T.parentNode;if(ab&&(ab.sizcache!==Y||!T.nodeIndex)){var X=0;for(U=ab.firstChild;U;U=U.nextSibling){if(U.nodeType===1){U.nodeIndex=++X}}ab.sizcache=Y}var aa=T.nodeIndex-ac;if(V==0){return aa==0}else{return(aa%V==0&&aa/V>=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V<T;V++){U.push(X[V])}}else{for(var V=0;X[V];V++){U.push(X[V])}}}return U}}var G;if(document.documentElement.compareDocumentPosition){G=function(U,T){var V=U.compareDocumentPosition(T)&4?-1:U===T?0:1;if(V===0){hasDuplicate=true}return V}}else{if("sourceIndex" in document.documentElement){G=function(U,T){var V=U.sourceIndex-T.sourceIndex;if(V===0){hasDuplicate=true}return V}}else{if(document.createRange){G=function(W,U){var V=W.ownerDocument.createRange(),T=U.ownerDocument.createRange();V.selectNode(W);V.collapse(true);T.selectNode(U);T.collapse(true);var X=V.compareBoundaryPoints(Range.START_TO_END,T);if(X===0){hasDuplicate=true}return X}}}}(function(){var U=document.createElement("form"),V="script"+(new Date).getTime();U.innerHTML="<input name='"+V+"'/>";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="<a href='#'></a>";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="<p class='TEST'></p>";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="<div class='test e'></div><div class='test'></div>";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1&&!ac){T.sizcache=Y;T.sizset=W}if(T.nodeName===Z){X=T;break}T=T[U]}ad[W]=X}}}function S(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1){if(!ac){T.sizcache=Y;T.sizset=W}if(typeof Z!=="string"){if(T===Z){X=true;break}}else{if(F.filter(Z,[T]).length>0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z<U;Z++){F(T,V[Z],W)}return F.filter(X,W)};o.find=F;o.filter=F.filter;o.expr=F.selectors;o.expr[":"]=o.expr.filters;F.selectors.filters.hidden=function(T){return T.offsetWidth===0||T.offsetHeight===0};F.selectors.filters.visible=function(T){return T.offsetWidth>0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F<E.length){o.event.proxy(G,E[F++])}return this.click(o.event.proxy(G,function(H){this.lastToggle=(this.lastToggle||0)%F;H.preventDefault();return E[this.lastToggle++].apply(this,arguments)||false}))},hover:function(E,F){return this.mouseenter(E).mouseleave(F)},ready:function(E){B();if(o.isReady){E.call(document,o)}else{o.readyList.push(E)}return this},live:function(G,F){var E=o.event.proxy(F);E.guid+=this.selector+G;o(document).bind(i(G,this.selector),this.selector,E);return this},die:function(F,E){o(document).unbind(i(F,this.selector),E?{guid:E.guid+this.selector+F}:null);return this}});function c(H){var E=RegExp("(^|\\.)"+H.type+"(\\.|$)"),G=true,F=[];o.each(o.data(this,"events").live||[],function(I,J){if(E.test(J.type)){var K=o(H.target).closest(J.data)[0];if(K){F.push({elem:K,fn:J})}}});F.sort(function(J,I){return o.data(J.elem,"closest")-o.data(I.elem,"closest")});o.each(F,function(){if(this.fn.call(this.elem,H,this.fn.data)===false){return(G=false)}});return G}function i(F,E){return["live",F,E.replace(/\./g,"`").replace(/ /g,"|")].join(".")}o.extend({isReady:false,readyList:[],ready:function(){if(!o.isReady){o.isReady=true;if(o.readyList){o.each(o.readyList,function(){this.call(document,o)});o.readyList=null}o(document).triggerHandler("ready")}}});var x=false;function B(){if(x){return}x=true;if(document.addEventListener){document.addEventListener("DOMContentLoaded",function(){document.removeEventListener("DOMContentLoaded",arguments.callee,false);o.ready()},false)}else{if(document.attachEvent){document.attachEvent("onreadystatechange",function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",arguments.callee);o.ready()}});if(document.documentElement.doScroll&&l==l.top){(function(){if(o.isReady){return}try{document.documentElement.doScroll("left")}catch(E){setTimeout(arguments.callee,0);return}o.ready()})()}}}o.event.add(l,"load",o.ready)}o.each(("blur,focus,load,resize,scroll,unload,click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,change,select,submit,keydown,keypress,keyup,error").split(","),function(F,E){o.fn[E]=function(G){return G?this.bind(E,G):this.trigger(E)}});o(l).bind("unload",function(){for(var E in o.cache){if(E!=1&&o.cache[E].handle){o.event.remove(o.cache[E].handle.elem)}}});(function(){o.support={};var F=document.documentElement,G=document.createElement("script"),K=document.createElement("div"),J="script"+(new Date).getTime();K.style.display="none";K.innerHTML='   <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';var H=K.getElementsByTagName("*"),E=K.getElementsByTagName("a")[0];if(!H||!H.length||!E){return}o.support={leadingWhitespace:K.firstChild.nodeType==3,tbody:!K.getElementsByTagName("tbody").length,objectAll:!!K.getElementsByTagName("object")[0].getElementsByTagName("*").length,htmlSerialize:!!K.getElementsByTagName("link").length,style:/red/.test(E.getAttribute("style")),hrefNormalized:E.getAttribute("href")==="/a",opacity:E.style.opacity==="0.5",cssFloat:!!E.style.cssFloat,scriptEval:false,noCloneEvent:true,boxModel:null};G.type="text/javascript";try{G.appendChild(document.createTextNode("window."+J+"=1;"))}catch(I){}F.insertBefore(G,F.firstChild);if(l[J]){o.support.scriptEval=true;delete l[J]}F.removeChild(G);if(K.attachEvent&&K.fireEvent){K.attachEvent("onclick",function(){o.support.noCloneEvent=false;K.detachEvent("onclick",arguments.callee)});K.cloneNode(true).fireEvent("onclick")}o(function(){var L=document.createElement("div");L.style.width=L.style.paddingLeft="1px";document.body.appendChild(L);o.boxModel=o.support.boxModel=L.offsetWidth===2;document.body.removeChild(L).style.display="none"})})();var w=o.support.cssFloat?"cssFloat":"styleFloat";o.props={"for":"htmlFor","class":"className","float":w,cssFloat:w,styleFloat:w,readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",tabindex:"tabIndex"};o.fn.extend({_load:o.fn.load,load:function(G,J,K){if(typeof G!=="string"){return this._load(G)}var I=G.indexOf(" ");if(I>=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("<div/>").append(M.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H<F;H++){var E=o.data(this[H],"olddisplay");this[H].style.display=E||"";if(o.css(this[H],"display")==="none"){var G=this[H].tagName,K;if(m[G]){K=m[G]}else{var I=o("<"+G+" />").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H<F;H++){this[H].style.display=o.data(this[H],"olddisplay")||""}return this}},hide:function(H,I){if(H){return this.animate(t("hide",3),H,I)}else{for(var G=0,F=this.length;G<F;G++){var E=o.data(this[G],"olddisplay");if(!E&&E!=="none"){o.data(this[G],"olddisplay",o.css(this[G],"display"))}}for(var G=0,F=this.length;G<F;G++){this[G].style.display="none"}return this}},_toggle:o.fn.toggle,toggle:function(G,F){var E=typeof G==="boolean";return o.isFunction(G)&&o.isFunction(F)?this._toggle.apply(this,arguments):G==null||E?this.each(function(){var H=E?G:o(this).is(":hidden");o(this)[H?"show":"hide"]()}):this.animate(t("toggle",3),G,F)},fadeTo:function(E,G,F){return this.animate({opacity:G},E,F)},animate:function(I,F,H,G){var E=o.speed(F,H,G);return this[E.queue===false?"each":"queue"](function(){var K=o.extend({},E),M,L=this.nodeType==1&&o(this).is(":hidden"),J=this;for(M in I){if(I[M]=="hide"&&L||I[M]=="show"&&!L){return K.complete.call(this)}if((M=="height"||M=="width")&&this.style){K.display=o.css(this,"display");K.overflow=this.style.overflow}}if(K.overflow!=null){this.style.overflow="hidden"}K.curAnim=o.extend({},I);o.each(I,function(O,S){var R=new o.fx(J,K,O);if(/toggle|show|hide/.test(S)){R[S=="toggle"?L?"show":"hide":S](I)}else{var Q=S.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),T=R.cur(true)||0;if(Q){var N=parseFloat(Q[2]),P=Q[3]||"px";if(P!="px"){J.style[O]=(N||1)+P;T=((N||1)/R.cur(true))*T;J.style[O]=T+P}if(Q[1]){N=((Q[1]=="-="?-1:1)*N)+T}R.custom(T,N,P)}else{R.custom(T,S,"")}}});return true})},stop:function(F,E){var G=o.timers;if(F){this.queue([])}this.each(function(){for(var H=G.length-1;H>=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J<K.length;J++){if(!K[J]()){K.splice(J--,1)}}if(!K.length){clearInterval(n);n=g}},13)}},show:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.show=true;this.custom(this.prop=="width"||this.prop=="height"?1:0,this.cur());o(this.elem).show()},hide:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(H){var G=e();if(H||G>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})();
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/editor/js-hotkeys/README.md	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,93 @@
+#About
+**jQuery.hotkeys** is a plug-in that lets you easily add and remove handlers for keyboard events anywhere in your code supporting almost any key combination.  
+
+It is based on a library [Shortcut.js](http://www.openjs.com/scripts/events/keyboard_shortcuts/shortcut.js) written by [Binny V A](http://www.openjs.com/).
+
+The syntax is as follows:
+<pre>
+$(expression).bind(<types>,<options>, <handler>);
+$(expression).unbind(<types>,<options>, <handler>);
+
+$(document).bind('keydown', 'Ctrl+a', fn);
+
+// e.g. replace '$' sign with 'EUR'
+$('input.foo').bind('keyup', '$', function(){
+    this.value = this.value.replace('$', 'EUR');
+});
+
+$('div.foo').unbind('keydown', 'Ctrl+a', fn);
+</pre>
+## [Live Demo](http://jshotkeys.googlepages.com/test-static-01.html)
+
+## Types
+Supported types are `'keydown'`, `'keyup'` and `'keypress'`
+
+## Options
+The options are `'combi'` i.e. the key combination, and `'disableInInput'` which allow your code not to be executed when the cursor is located inside an input ( `$(elem).is('input') || $(elem).is('textarea')` ).
+
+As you can see, the key combination can be passed as string or as an object. You may pass an object in case you wish to override the default option for `disableInInput` which is set to `false`:
+<pre>
+$(document).bind('keydown', {combi:'a', disableinInput: true}, fn);
+</pre>
+I.e. when cursor is within an input field, `'a'` will be inserted into the input field without interfering. 
+
+If you want to use more than one modifiers (e.g. alt+ctrl+z) you should define them by an alphabetical order e.g. alt+ctrl+shift
+
+Modifiers are case insensitive, i.e. 'Ctrl+a' 'ctrl+a'.
+
+## Handler
+In previous versions there was an option propagate which is removed now and implemented at the user code level.
+
+When using jQuery, if an event handler returns false, jQuery will call `stopPropagation()` and `preventDefault()`
+
+## jQuery Compatibility
+Tested with *jQuery 1.2.6*
+
+It known to be working with all the major browsers on all available platforms (Win/Mac/Linux)
+
+ * IE 6/7/8
+ * FF 1.5/2/3
+ * Opera-9
+ * Safari-3
+ * Chrome-0.2
+
+## Features added in this version (0.7.x)
+ * Implemented as $.fn - let you use `this`.
+ * jQuery selectors are supported.
+ * Extending `$.fn.bind` and `$.fn.unbind` so you get a single interface for binding events to handlers
+ 
+## Overriding jQuery
+The plugin wraps the following jQuery methods:
+ * $.fn.bind
+ * $.fn.unbind
+ * $.find
+
+Even though the plugin overrides these methods, the original methods will *always* be called.
+
+The plugin will add functionality only for the `keydown`, `keyup` and `keypress` event types. Any other types are passed untouched to the original `'bind()'` and `'unbind()'` methods.
+
+Moreover, if you call `bind()` without passing the shortcut key combination e.g. `$(document).bind('keydown', fn)` only the original `'bind()'` method will be executed.
+
+I also modified the `$.fn.find` method by adding a single line at the top of the function body. here is the code:
+
+<pre>
+    jQuery.fn.find = function( selector ) {
+        // the line I added
+        this.query=selector;
+        // call jQuery original find
+        return jQuery.fn.__find__.apply(this, arguments);
+    };
+</pre>
+
+You can read about this at [jQuery's User Group](http://groups.google.com/group/jquery-en/browse_thread/thread/18f9825e8d22f18d)
+
+###Notes
+
+Firefox is the most liberal one in the manner of letting you capture all short-cuts even those that are built-in in the browser such as `Ctrl-t` for new tab, or `Ctrl-a` for selecting all text. You can always bubble them up to the browser by returning `true` in your handler.
+
+Others, (IE) either let you handle built-in short-cuts, but will add their functionality after your code has executed. Or (Opera/Safari) will *not* pass those events to the DOM at all.
+
+*So, if you bind `Ctrl-Q` or `Alt-F4` and your Safari/Opera window is closed don't be surprised.*
+
+
+###Current Version is: beta 0.7
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/editor/js-hotkeys/jquery.hotkeys.min.js	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,19 @@
+(function(jQuery){jQuery.fn.__bind__=jQuery.fn.bind;jQuery.fn.__unbind__=jQuery.fn.unbind;jQuery.fn.__find__=jQuery.fn.find;var hotkeys={version:'0.7.9',override:/keypress|keydown|keyup/g,triggersMap:{},specialKeys:{27:'esc',9:'tab',32:'space',13:'return',8:'backspace',145:'scroll',20:'capslock',144:'numlock',19:'pause',45:'insert',36:'home',46:'del',35:'end',33:'pageup',34:'pagedown',37:'left',38:'up',39:'right',40:'down',109:'-',112:'f1',113:'f2',114:'f3',115:'f4',116:'f5',117:'f6',118:'f7',119:'f8',120:'f9',121:'f10',122:'f11',123:'f12',191:'/'},shiftNums:{"`":"~","1":"!","2":"@","3":"#","4":"$","5":"%","6":"^","7":"&","8":"*","9":"(","0":")","-":"_","=":"+",";":":","'":"\"",",":"<",".":">","/":"?","\\":"|"},newTrigger:function(type,combi,callback){var result={};result[type]={};result[type][combi]={cb:callback,disableInInput:false};return result;}};hotkeys.specialKeys=jQuery.extend(hotkeys.specialKeys,{96:'0',97:'1',98:'2',99:'3',100:'4',101:'5',102:'6',103:'7',104:'8',105:'9',106:'*',107:'+',109:'-',110:'.',111:'/'});jQuery.fn.find=function(selector){this.query=selector;return jQuery.fn.__find__.apply(this,arguments);};jQuery.fn.unbind=function(type,combi,fn){if(jQuery.isFunction(combi)){fn=combi;combi=null;}
+if(combi&&typeof combi==='string'){var selectorId=((this.prevObject&&this.prevObject.query)||(this[0].id&&this[0].id)||this[0]).toString();var hkTypes=type.split(' ');for(var x=0;x<hkTypes.length;x++){delete hotkeys.triggersMap[selectorId][hkTypes[x]][combi];}}
+return this.__unbind__(type,fn);};jQuery.fn.bind=function(type,data,fn){var handle=type.match(hotkeys.override);if(jQuery.isFunction(data)||!handle){return this.__bind__(type,data,fn);}
+else{var result=null,pass2jq=jQuery.trim(type.replace(hotkeys.override,''));if(pass2jq){result=this.__bind__(pass2jq,data,fn);}
+if(typeof data==="string"){data={'combi':data};}
+if(data.combi){for(var x=0;x<handle.length;x++){var eventType=handle[x];var combi=data.combi.toLowerCase(),trigger=hotkeys.newTrigger(eventType,combi,fn),selectorId=((this.prevObject&&this.prevObject.query)||(this[0].id&&this[0].id)||this[0]).toString();trigger[eventType][combi].disableInInput=data.disableInInput;if(!hotkeys.triggersMap[selectorId]){hotkeys.triggersMap[selectorId]=trigger;}
+else if(!hotkeys.triggersMap[selectorId][eventType]){hotkeys.triggersMap[selectorId][eventType]=trigger[eventType];}
+var mapPoint=hotkeys.triggersMap[selectorId][eventType][combi];if(!mapPoint){hotkeys.triggersMap[selectorId][eventType][combi]=[trigger[eventType][combi]];}
+else if(mapPoint.constructor!==Array){hotkeys.triggersMap[selectorId][eventType][combi]=[mapPoint];}
+else{hotkeys.triggersMap[selectorId][eventType][combi][mapPoint.length]=trigger[eventType][combi];}
+this.each(function(){var jqElem=jQuery(this);if(jqElem.attr('hkId')&&jqElem.attr('hkId')!==selectorId){selectorId=jqElem.attr('hkId')+";"+selectorId;}
+jqElem.attr('hkId',selectorId);});result=this.__bind__(handle.join(' '),data,hotkeys.handler)}}
+return result;}};hotkeys.findElement=function(elem){if(!jQuery(elem).attr('hkId')){if(jQuery.browser.opera||jQuery.browser.safari){while(!jQuery(elem).attr('hkId')&&elem.parentNode){elem=elem.parentNode;}}}
+return elem;};hotkeys.handler=function(event){var target=hotkeys.findElement(event.currentTarget),jTarget=jQuery(target),ids=jTarget.attr('hkId');if(ids){ids=ids.split(';');var code=event.which,type=event.type,special=hotkeys.specialKeys[code],character=!special&&String.fromCharCode(code).toLowerCase(),shift=event.shiftKey,ctrl=event.ctrlKey,alt=event.altKey||event.originalEvent.altKey,mapPoint=null;for(var x=0;x<ids.length;x++){if(hotkeys.triggersMap[ids[x]][type]){mapPoint=hotkeys.triggersMap[ids[x]][type];break;}}
+if(mapPoint){var trigger;if(!shift&&!ctrl&&!alt){trigger=mapPoint[special]||(character&&mapPoint[character]);}
+else{var modif='';if(alt)modif+='alt+';if(ctrl)modif+='ctrl+';if(shift)modif+='shift+';trigger=mapPoint[modif+special];if(!trigger){if(character){trigger=mapPoint[modif+character]||mapPoint[modif+hotkeys.shiftNums[character]]||(modif==='shift+'&&mapPoint[hotkeys.shiftNums[character]]);}}}
+if(trigger){var result=false;for(var x=0;x<trigger.length;x++){if(trigger[x].disableInInput){var elem=jQuery(event.target);if(jTarget.is("input")||jTarget.is("textarea")||jTarget.is("select")||elem.is("input")||elem.is("textarea")||elem.is("select")){return true;}}
+result=result||trigger[x].cb.apply(this,[event]);}
+return result;}}}};window.hotkeys=hotkeys;return jQuery;})(jQuery);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/editor/spinbtn/JQuerySpinBtn.css	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,41 @@
+/*
+	Styles to make ordinary <INPUT type="text"/> look like a spinbutton/spinbox control.
+	Use with JQuerySpinBtn.js to provide the spin functionality by reacting to mouse etc.
+	(Requires a reference to the JQuery library found at http://jquery.com/src/latest/)
+	(Hats-off to John Resig for creating the excellent JQuery library. It is fab.)
+
+	This control is achieved with no extra html markup whatsoever and uses unobtrusive javascript.
+
+	Written by George Adamson, Software Unity (george.jquery@softwareunity.com) September 2006.
+	Big improvements added by Mark Gibson, (mgibson@designlinks.net) September 2006.
+
+	Do contact me with comments and suggestions but please don't ask for support.
+	As much as I'd love to help with specific problems I have plenty to get on with already!
+
+	Go ahead and use it in your own projects. This code is provided 'as is'.
+	Sure I've tested in heaps of ways. Its good for me, but you use it at your own risk.
+	SoftwareUnity and I are certainly not responsible if your computer sets fire to the sofa,
+	hacks into the pentagon, hijacks a plane or gives you any kind of hassle whatsoever.
+
+	If you'd like your spin-button image in a different place then you'll need to alter both
+	the CSS below and the javascript isMouseOverUpDn() function to accommodate the new position.
+	You could even have left and right buttons either side of the textbox.
+*/
+
+INPUT.spin-button {
+	/* explicitly put padding for top/bottom/left in here so that Opera displays it better */
+	padding: 2px 20px 2px 2px;
+	background-repeat:no-repeat;		/* Warning: Img may disappear in Firefox if you use 'background-attachment:fixed' ! */
+	background-position:100% 0%;
+	background-image:url('spinbtn_updn.png');
+	background-color:white; /* Needed for Opera */
+}
+
+INPUT.spin-button.up {					/* Change button img when mouse is over the UP-arrow */
+	cursor:pointer;
+	background-position:100% -18px;		/* 18px matches height of 2 visible buttons */
+}
+INPUT.spin-button.down {				/* Change button img when mouse is over the DOWN-arrow */
+	cursor:pointer;
+	background-position:100% -36px;		/* 36px matches height of 2x2 visible buttons */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/editor/spinbtn/JQuerySpinBtn.js	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,234 @@
+/* SpinButton control
+ *
+ * Adds bells and whistles to any ordinary textbox to
+ * make it look and feel like a SpinButton Control.
+ *
+ * Originally written by George Adamson, Software Unity (george.jquery@softwareunity.com) August 2006.
+ * - Added min/max options
+ * - Added step size option
+ * - Added bigStep (page up/down) option
+ *
+ * Modifications made by Mark Gibson, (mgibson@designlinks.net) September 2006:
+ * - Converted to jQuery plugin
+ * - Allow limited or unlimited min/max values
+ * - Allow custom class names, and add class to input element
+ * - Removed global vars
+ * - Reset (to original or through config) when invalid value entered
+ * - Repeat whilst holding mouse button down (with initial pause, like keyboard repeat)
+ * - Support mouse wheel in Firefox
+ * - Fix double click in IE
+ * - Refactored some code and renamed some vars
+ *
+ * Modifications by Jeff Schiller, June 2009:
+ * - provide callback function for when the value changes based on the following
+ *   http://www.mail-archive.com/jquery-en@googlegroups.com/msg36070.html
+ * Modifications by Jeff Schiller, July 2009:
+ * - improve styling for widget in Opera
+ * - consistent key-repeat handling cross-browser
+ *
+ * Tested in IE6, Opera9, Firefox 1.5
+ * v1.0  11 Aug 2006 - George Adamson	- First release
+ * v1.1     Aug 2006 - George Adamson	- Minor enhancements
+ * v1.2  27 Sep 2006 - Mark Gibson		- Major enhancements
+ * v1.3a 28 Sep 2006 - George Adamson	- Minor enhancements
+ * v1.4  18 Jun 2009 - Jeff Schiller    - Added callback function
+ * v1.5  06 Jul 2009 - Jeff Schiller    - Fixes for Opera.  
+ *                                        Fast-repeat for keys and live updating as you type.
+ 
+ Sample usage:
+ 
+	// Create group of settings to initialise spinbutton(s). (Optional)
+	var myOptions = {
+					min: 0,						// Set lower limit.
+					max: 100,					// Set upper limit.
+					step: 1,					// Set increment size.
+					spinClass: mySpinBtnClass,	// CSS class to style the spinbutton. (Class also specifies url of the up/down button image.)
+					upClass: mySpinUpClass,		// CSS class for style when mouse over up button.
+					downClass: mySpinDnClass	// CSS class for style when mouse over down button.
+					}
+ 
+	$(document).ready(function(){
+
+		// Initialise INPUT element(s) as SpinButtons: (passing options if desired)
+		$("#myInputElement").SpinButton(myOptions);
+
+	});
+ 
+ */
+$.fn.SpinButton = function(cfg){
+	return this.each(function(){
+
+		this.repeating = false;
+		
+		// Apply specified options or defaults:
+		// (Ought to refactor this some day to use $.extend() instead)
+		this.spinCfg = {
+			//min: cfg && cfg.min ? Number(cfg.min) : null,
+			//max: cfg && cfg.max ? Number(cfg.max) : null,
+			min: cfg && !isNaN(parseFloat(cfg.min)) ? Number(cfg.min) : null,	// Fixes bug with min:0
+			max: cfg && !isNaN(parseFloat(cfg.max)) ? Number(cfg.max) : null,
+			step: cfg && cfg.step ? Number(cfg.step) : 1,
+			page: cfg && cfg.page ? Number(cfg.page) : 10,
+			upClass: cfg && cfg.upClass ? cfg.upClass : 'up',
+			downClass: cfg && cfg.downClass ? cfg.downClass : 'down',
+			reset: cfg && cfg.reset ? cfg.reset : this.value,
+			delay: cfg && cfg.delay ? Number(cfg.delay) : 500,
+			interval: cfg && cfg.interval ? Number(cfg.interval) : 100,
+			_btn_width: 20,
+			_btn_height: 12,
+			_direction: null,
+			_delay: null,
+			_repeat: null,
+			callback: cfg && cfg.callback ? cfg.callback : null,
+		};
+		
+		this.adjustValue = function(i){
+			var v = (isNaN(this.value) ? this.spinCfg.reset : Number(this.value)) + Number(i);
+			if (this.spinCfg.min !== null) v = Math.max(v, this.spinCfg.min);
+			if (this.spinCfg.max !== null) v = Math.min(v, this.spinCfg.max);
+			this.value = v;
+			if ($.isFunction(this.spinCfg.callback)) this.spinCfg.callback(this);
+		};
+		
+		$(this)
+		.addClass(cfg && cfg.spinClass ? cfg.spinClass : 'spin-button')
+		
+		.mousemove(function(e){
+			// Determine which button mouse is over, or not (spin direction):
+			var x = e.pageX || e.x;
+			var y = e.pageY || e.y;
+			var el = e.target || e.srcElement;
+			var direction = 
+				(x > coord(el,'offsetLeft') + el.offsetWidth - this.spinCfg._btn_width)
+				? ((y < coord(el,'offsetTop') + this.spinCfg._btn_height) ? 1 : -1) : 0;
+			
+			if (direction !== this.spinCfg._direction) {
+				// Style up/down buttons:
+				switch(direction){
+					case 1: // Up arrow:
+						$(this).removeClass(this.spinCfg.downClass).addClass(this.spinCfg.upClass);
+						break;
+					case -1: // Down arrow:
+						$(this).removeClass(this.spinCfg.upClass).addClass(this.spinCfg.downClass);
+						break;
+					default: // Mouse is elsewhere in the textbox
+						$(this).removeClass(this.spinCfg.upClass).removeClass(this.spinCfg.downClass);
+				}
+				
+				// Set spin direction:
+				this.spinCfg._direction = direction;
+			}
+		})
+		
+		.mouseout(function(){
+			// Reset up/down buttons to their normal appearance when mouse moves away:
+			$(this).removeClass(this.spinCfg.upClass).removeClass(this.spinCfg.downClass);
+			this.spinCfg._direction = null;
+		})
+		
+		.mousedown(function(e){
+			if (this.spinCfg._direction != 0) {
+				// Respond to click on one of the buttons:
+				var self = this;
+				var adjust = function() {
+					self.adjustValue(self.spinCfg._direction * self.spinCfg.step);
+				};
+			
+				adjust();
+				
+				// Initial delay before repeating adjustment
+				self.spinCfg._delay = window.setTimeout(function() {
+					adjust();
+					// Repeat adjust at regular intervals
+					self.spinCfg._repeat = window.setInterval(adjust, self.spinCfg.interval);
+				}, self.spinCfg.delay);
+			}
+		})
+		
+		.mouseup(function(e){
+			// Cancel repeating adjustment
+			window.clearInterval(this.spinCfg._repeat);
+			window.clearTimeout(this.spinCfg._delay);
+		})
+		
+		.dblclick(function(e) {
+			if ($.browser.msie)
+				this.adjustValue(this.spinCfg._direction * this.spinCfg.step);
+		})
+		
+		.keydown(function(e){
+			// Respond to up/down arrow keys.
+			switch(e.keyCode){
+				case 38: this.adjustValue(this.spinCfg.step);  break; // Up
+				case 40: this.adjustValue(-this.spinCfg.step); break; // Down
+				case 33: this.adjustValue(this.spinCfg.page);  break; // PageUp
+				case 34: this.adjustValue(-this.spinCfg.page); break; // PageDown
+			}
+		})
+		
+		/*
+		http://unixpapa.com/js/key.html describes the current state-of-affairs for
+		key repeat events:
+		- Safari 3.1 changed their model so that keydown is reliably repeated going forward
+		- Firefox and Opera still only repeat the keypress event, not the keydown
+		*/
+		.keypress(function(e){
+			if (this.repeating) {
+				// Respond to up/down arrow keys.
+				switch(e.keyCode){
+					case 38: this.adjustValue(this.spinCfg.step);  break; // Up
+					case 40: this.adjustValue(-this.spinCfg.step); break; // Down
+					case 33: this.adjustValue(this.spinCfg.page);  break; // PageUp
+					case 34: this.adjustValue(-this.spinCfg.page); break; // PageDown
+				}
+			} 
+			// we always ignore the first keypress event (use the keydown instead)
+			else {
+				this.repeating = true;
+			}
+		})
+		
+		// clear the 'repeating' flag
+		.keyup(function(e) {
+			this.repeating = false;
+			this.adjustValue(0);
+		})
+		
+		.bind("mousewheel", function(e){
+			// Respond to mouse wheel in IE. (It returns up/dn motion in multiples of 120)
+			if (e.wheelDelta >= 120)
+				this.adjustValue(this.spinCfg.step);
+			else if (e.wheelDelta <= -120)
+				this.adjustValue(-this.spinCfg.step);
+			
+			e.preventDefault();
+		})
+		
+		.change(function(e){
+			this.adjustValue(0);
+		});
+		
+		if (this.addEventListener) {
+			// Respond to mouse wheel in Firefox
+			this.addEventListener('DOMMouseScroll', function(e) {
+				if (e.detail > 0)
+					this.adjustValue(-this.spinCfg.step);
+				else if (e.detail < 0)
+					this.adjustValue(this.spinCfg.step);
+				
+				e.preventDefault();
+			}, false);
+		}
+	});
+	
+	function coord(el,prop) {
+		var c = el[prop], b = document.body;
+		
+		while ((el = el.offsetParent) && (el != b)) {
+			if (!$.browser.msie || (el.currentStyle.position != 'relative'))
+				c += el[prop];
+		}
+		
+		return c;
+	}
+};
Binary file htdocs/svg-edit/editor/spinbtn/spinbtn_updn.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/editor/svg-editor.css	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,328 @@
+body {
+	background: #E8E8E8;
+}
+
+#svg_editor {
+	font-size: 8pt;
+	font-family: Verdana, Helvetica, Arial;
+	color: #000000;
+}
+
+#svg_editor a {
+	color: #0000FF;
+}
+
+#svg_editor hr {
+	border: none;
+	border-bottom: 1px solid #808080;
+}
+
+#svg_editor select {
+	margin-top: 4px;
+}
+
+#svg_editor #svgroot {
+	-moz-user-select: none;
+}
+
+#svg_editor #svgcanvas {
+	background-color: #FFFFFF;
+	text-align: center;
+	vertical-align: middle;
+	width: 640px;
+	height: 480px;
+	-apple-dashboard-region:dashboard-region(control rectangle 0px 0px 0px 0px); /* for widget regions that shouldn't react to dragging */
+}
+
+#svg_editor div#palette_holder {
+	overflow-x: scroll;
+	overflow-y: hidden;
+	height: 31px;
+	border: 1px solid #808080;
+	border-top: none;
+	margin-top: 2px;
+}
+
+#svg_editor #fill_color, #svg_editor #stroke_color {
+	height: 16px;
+	width: 16px;
+	border: 1px solid #808080;
+	cursor: pointer;
+}
+
+#svg_editor div#palette {
+	float: left;
+	width: 6848px;
+	height: 16px;
+}
+
+#svg_editor div#workarea {
+	position:absolute;
+	top: 70px;
+	left: 40px;
+	right: 2px;
+	bottom: 60px;
+	background-color: #A0A0A0;
+	border: 1px solid #808080;
+	overflow: auto;
+}
+
+#svg_editor div.palette_item {
+	height: 16px;
+	width: 16px;
+	float: left;
+}
+
+#svg_editor #logo {
+	position: absolute;
+	top: 1px;
+	left: 1px;
+	width: 30px;
+	height: 30px;
+	padding: 0px;
+}
+
+#svg_editor #tools_top {
+	position: absolute;
+	left: 38px;
+	right: 2px;
+	top: 2px;
+	height: 68px;
+	border-bottom: none;
+}
+
+#svg_editor #tools_top div {
+	float: left;
+}
+
+#svg_editor #tools_left {
+	position: absolute;
+	border-right: none;
+	width: 36px;
+	top: 68px;
+	left: 2px;
+}
+
+/* TODO: fix this */
+div.color_block {
+	background-image: url('images/none.png');
+	display: inline-block;
+}
+
+#svg_editor #selected_panel {
+	display: none;
+}
+
+#svg_editor #multiselected_panel {
+	display: none;
+}
+
+#svg_editor #rect_panel {
+	display: none;
+}
+
+#svg_editor #circle_panel {
+	display: none;
+}
+
+#svg_editor #ellipse_panel {
+	display: none;
+}
+
+#svg_editor #line_panel {
+	display: none;
+}
+
+#svg_editor #text_panel {
+	display: none;
+}
+
+#svg_editor #selected_panel .selected_tool {
+	vertical-align: 12px;
+}
+
+#svg_editor #text_panel .text_tool {
+	vertical-align: 12px;
+}
+
+#svg_editor #rect_panel .rect_tool {
+	vertical-align: 12px;
+}
+
+#svg_editor #circle_panel .circle_tool {
+	vertical-align:12px;
+}
+
+#svg_editor #ellipse_panel .ellipse_tool {
+	vertical-align:12px;
+}
+
+#svg_editor #line_panel .line_tool {
+	vertical-align:12px;
+}
+
+/* TODO: figure out why there is a couple pixels between
+   the tools with a flyout arrow */
+#svg_editor .flyout_arrow_horiz {
+	float: right;
+	position: relative;
+	top: -13px;
+	left: -5px;
+	margin-bottom: -13px;
+}
+
+#svg_editor .tool_button, #svg_editor .tool_button_current, #svg_editor .tool_button_disabled {
+	height: 24px;
+	width: 24px;
+	margin: 2px;
+	padding: 2px;
+	border-left: 1px solid #FFFFFF;
+	border-top: 1px solid #FFFFFF;
+	border-right: 1px solid #808080;
+	border-bottom: 1px solid #808080;
+	cursor: pointer;
+}
+
+#svg_editor .tool_button_current {
+	border-left: 1px solid #808080;
+	border-top: 1px solid #808080;
+	border-right: 1px solid #FFFFFF;
+	border-bottom: 1px solid #FFFFFF;
+	background-color: #B0B0B0;
+}
+
+#svg_editor .tool_button_disabled {
+	opacity: 0.5;
+	cursor: default;
+}
+
+#svg_editor .tool_sep {
+	width: 2px;
+	height: 24px;
+	margin: 2px;
+	margin-right: 0;
+	padding: 2px;
+}
+
+#svg_editor #color_picker {
+	position: absolute;
+	display: none;
+	background: #E8E8E8;
+}
+
+#svg_editor .tools_flyout {
+	position: absolute;
+	display: none;
+	cursor: pointer;
+}
+
+#svg_editor .tools_flyout_v {
+	position: absolute;
+	display: none;
+	cursor: pointer;
+	width: 30px;
+}
+
+#svg_editor #tool_square { background: 2px 2px url('images/square.png') no-repeat; }
+#svg_editor #tool_rect { background: 2px 2px url('images/rect.png') no-repeat; }
+#svg_editor #tool_fhrect { background: 2px 2px url('images/freehand-square.png') no-repeat; }
+#svg_editor #tool_circle { background: 2px 2px url('images/circle.png') no-repeat; }
+#svg_editor #tool_ellipse { background: 2px 2px url('images/ellipse.png') no-repeat; }
+#svg_editor #tool_fhellipse { background: 2px 2px url('images/freehand-circle.png') no-repeat; }
+#svg_editor #tool_stacktop { background: 2px 2px url('images/move_top.png') no-repeat; }
+#svg_editor #tool_stackbottom { background: 2px 2px url('images/move_bottom.png') no-repeat; }
+#svg_editor #tool_aligntop { background: 2px 2px url('images/align-vertical-top.png') no-repeat; }
+#svg_editor #tool_alignmiddle { background: 2px 2px url('images/align-vertical-middle.png') no-repeat; }
+#svg_editor #tool_alignbottom { background: 2px 2px url('images/align-vertical-bottom.png') no-repeat; }
+#svg_editor #tool_alignleft { background: 2px 2px url('images/align-horizontal-left.png') no-repeat; }
+#svg_editor #tool_aligncenter { background: 2px 2px url('images/align-horizontal-center.png') no-repeat; }
+#svg_editor #tool_alignright { background: 2px 2px url('images/align-horizontal-right.png') no-repeat; }
+
+/* TODO: figure out what more-specific selector causes me to write this atrocity and not
+         simply .tool_flyout_button */
+#svg_editor #tools_rect .tool_flyout_button, #svg_editor #tools_ellipse .tool_flyout_button {
+	float: left;
+	background-color: #E8E8E8;
+	border-left: 1px solid #FFFFFF;
+	border-top: 1px solid #FFFFFF;
+	border-right: 1px solid #808080;
+	border-bottom: 1px solid #808080;
+	height: 28px;
+	width: 28px;
+}
+
+#svg_editor #tools_rect .tool_flyout_button_current, #svg_editor #tools_ellipse .tool_flyout_button_current {
+	border-left: 1px solid #808080;
+	border-top: 1px solid #808080;
+	border-right: 1px solid #FFFFFF;
+	border-bottom: 1px solid #FFFFFF;
+	background-color: #B0B0B0;
+}
+
+#svg_editor #tools_bottom {
+	position: absolute;
+	left: 40px;
+	right: 2px;
+	bottom: 2px;
+	height: 60px;
+}
+
+#svg_editor #tools_bottom_1 {
+	width: 115px;
+	float: left;
+}
+
+#svg_editor #tools_bottom_2 {
+	width: 250px;
+	float: left;
+}
+
+#svg_editor #tools_bottom_3 {
+}
+
+#svg_editor #copyright {
+	text-align: right;
+}
+
+#svg_source_editor {
+	display: none;
+}
+
+#svg_source_overlay {
+	position: absolute;
+	top: 0px;
+	right: 0px;
+	left: 0px;
+	bottom: 0px;
+	background-color: black;
+	opacity: 0.6;
+}
+
+#svg_source_container {
+	position: absolute;
+	top: 30px;
+	left: 30px;
+	right: 30px;
+	bottom: 30px;
+	background-color: #B0B0B0;
+	opacity: 1.0;
+	text-align: center;
+}
+
+#svg_source_textarea {
+	position: relative;
+	width: 95%;
+	top: 5px;
+	height: 250px;
+	padding: 5px;
+	font-size: 12px;
+}
+
+#tool_source_back {
+	text-align: left;
+	padding-left: 20px;
+}
+
+#tool_source_back button {
+	margin: 10px;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/editor/svg-editor.html	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,288 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
+<link rel="icon" type="image/png" href="images/logo.png">
+<link rel="stylesheet" href="jgraduate/css/jPicker-1.0.9.css" type="text/css"/>
+<link rel="stylesheet" href="jgraduate/css/jGraduate-0.2.0.css" type="text/css"/>
+<link rel="stylesheet" href="svg-editor.css" type="text/css"/>
+<link rel="stylesheet" href="spinbtn/JQuerySpinBtn.css" type="text/css"/>
+<script type="text/javascript" src="jquery.js"></script>
+<!--script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script-->
+<script type="text/javascript" src="js-hotkeys/jquery.hotkeys.min.js"></script>
+<!--script type="text/javascript" src="js-hotkeys/jquery.hotkeys-0.7.9.js"></script-->
+<script type="text/javascript" src="jgraduate/jpicker-1.0.9.min.js"></script>
+<script type="text/javascript" src="jgraduate/jquery.jgraduate.js"></script>
+<script type="text/javascript" src="spinbtn/JQuerySpinBtn.js"></script>
+<!--script type="text/javascript" src="spinbtn/JQuerySpinBtn.min.js"></script-->
+<!--script type="text/javascript" src="jgraduate/jquery.jgraduate.min.js"></script-->
+<script type="text/javascript" src="svgcanvas.js"></script>
+<!--script type="text/javascript" src="svgcanvas.min.js"></script-->
+<script type="text/javascript" src="svg-editor.js"></script>
+<!--script type="text/javascript" src="svg-editor.min.js"></script-->
+<title>SVG-edit demo</title>
+</head>
+<body>
+
+<div id="svg_editor">
+
+<div id="workarea">
+<style id="styleoverrides" type="text/css"></style>
+<div id="svgcanvas"></div>
+</div>
+
+<div id="logo">
+	<a href="http://svg-edit.googlecode.com/" target="_blank" title="SVG-edit Home Page">
+		<img src="images/logo.png" width="32" height="32"/>
+	</a>
+</div>
+
+<div id="tools_top" class="tools_panel">
+	<!-- File-like buttons: New, Save, Source -->
+	<div>
+		<img class="tool_sep" src="images/sep.png" alt="|"/>
+		<img class="tool_button" id="tool_clear" src="images/clear.png" title="New Image [N]" alt="Clear" />
+		<img style="display:none" eeclass="tool_button" id="tool_open" src="images/open.png" title="Open Image [O]" alt="Open"/>
+		<img class="tool_button" id="tool_save" src="images/save.png" title="Save Image [S]" alt="Save"/>
+		<img class="tool_button" id="tool_source" src="images/source.png" title="Edit Source [U]" alt="Source"/>
+	</div>
+
+    <!-- History buttons -->
+	<div>
+		<img class="tool_sep" src="images/sep.png" alt="|"/>
+		<img class="tool_button tool_button_disabled" id="tool_undo" src="images/undo.png" title="Undo [Z]" alt="Undo" />
+		<img class="tool_button tool_button_disabled" id="tool_redo" src="images/redo.png" title="Redo [Y]" alt="Redo"/>
+	</div>
+
+	<!-- Buttons when a single element is selected -->
+	<div id="selected_panel">
+		<img class="tool_sep" src="images/sep.png" alt="|"/>
+		<img class="tool_button" id="tool_clone" src="images/clone.png" title="Clone Element [C]" alt="Copy"/>
+		<img class="tool_button" id="tool_delete" src="images/delete.png" title="Delete Element [Delete/Backspace]" alt="Delete"/>
+		<img class="tool_sep" src="images/sep.png" alt="|"/>
+		<img class="tool_button" id="tool_move_top" src="images/move_top.png" title="Move to Top [Shift+Up]" alt="Top"/>
+		<img class="tool_button" id="tool_move_bottom" src="images/move_bottom.png" title="Move to Bottom [Shift+Down]" alt="Bottom"/>
+		<img class="tool_sep" src="images/sep.png" alt="|"/>
+		<select id="group_opacity" class="selected_tool" title="Change selected item opacity">
+			<option selected="selected" value="1">100 %</option>
+			<option value="0.9">90 %</option>
+			<option value="0.8">80 %</option>
+			<option value="0.7">70 %</option>
+			<option value="0.6">60 %</option>
+			<option value="0.5">50 %</option>
+			<option value="0.4">40 %</option>
+			<option value="0.3">30 %</option>
+			<option value="0.2">20 %</option>
+			<option value="0.1">10 %</option>
+		</select>
+		<span class="selected_tool">angle:</span>
+		<input id="angle" class="selected_tool" title="Change rotation angle" alt="Rotation Angle" size="2" value="0" type="text"/>
+	</div>
+
+	<!-- Buttons when multiple elements are selected -->
+	<div id="multiselected_panel">
+		<img class="tool_sep" src="images/sep.png" alt="|"/>
+		<img class="tool_button" id="tool_clone_multi" src="images/clone.png" title="Clone Elements [C]" alt="Clone"/>
+		<img class="tool_button" id="tool_delete_multi" src="images/delete.png" title="Delete Selected Elements [Delete/Backspace]" alt="Delete"/>
+		<img class="tool_sep" src="images/sep.png" alt="|"/>
+		<img class="tool_button" id="tool_alignleft" src="images/align-left.png" title="Align Left" alt="Left"/>
+		<img class="tool_button" id="tool_aligncenter" src="images/align-center.png" title="Align Center" alt="Center"/>
+		<img class="tool_button" id="tool_alignright" src="images/align-right.png" title="Align Right" alt="Right"/>
+		<img class="tool_sep" src="images/sep.png" alt="|"/>
+		<img class="tool_button" id="tool_aligntop" src="images/align-top.png" title="Align Top" alt="Top"/>
+		<img class="tool_button" id="tool_alignmiddle" src="images/align-middle.png" title="Align Middle" alt="Middle"/>
+		<img class="tool_button" id="tool_alignbottom" src="images/align-bottom.png" title="Align Bottom" alt="Bottom"/>
+	</div>
+
+	<div id="rect_panel">
+		<img class="tool_sep" src="images/sep.png" alt="|"/>
+		<label class="rect_tool">x:</label>
+		<input id="rect_x" class="rect_tool attr_changer" title="Change rectangle X coordinate" alt="x" size="3"/>
+		<label class="rect_tool">y:</label>
+		<input id="rect_y" class="rect_tool attr_changer" title="Change rectangle Y coordinate" alt="y" size="3"/>
+		<label class="rect_tool">width:</label>
+		<input id="rect_width" class="rect_tool attr_changer" title="Change rectangle width" alt="width" size="3"/>
+		<label class="rect_tool">height:</label>
+		<input id="rect_height" class="rect_tool attr_changer" title="Change rectangle height" alt="height" size="3"/>
+		<label class="rect_tool">Corner Radius:</label>
+		<input id="rect_rx" size="3" value="0" class="rect_tool" type="text" title="Change Rectangle Corner Radius" alt="Corner Radius"/>
+	</div>
+
+	<div id="circle_panel">
+		<img class="tool_sep" src="images/sep.png" alt="|"/>
+		<label class="circle_tool">cx:</label>
+		<input id="circle_cx" class="circle_tool attr_changer" title="Change circle's cx coordinate" alt="cx" size="3"/>
+		<label class="circle_tool">cy:</label>
+		<input id="circle_cy" class="circle_tool attr_changer" title="Change circle's cy coordinate" alt="cy" size="3"/>
+		<label class="circle_tool">r:</label>
+		<input id="circle_r" class="circle_tool attr_changer" title="Change circle's radius" alt="r" size="3"/>
+	</div>
+
+	<div id="ellipse_panel">
+		<img class="tool_sep" src="images/sep.png" alt="|"/>
+		<label class="ellipse_tool">cx:</label>
+		<input id="ellipse_cx" class="ellipse_tool attr_changer" title="Change ellipse's cx coordinate" alt="cx" size="3"/>
+		<label class="ellipse_tool">cy:</label>
+		<input id="ellipse_cy" class="ellipse_tool attr_changer" title="Change ellipse's cy coordinate" alt="cy" size="3"/>
+		<label class="ellipse_tool">rx:</label>
+		<input id="ellipse_rx" class="ellipse_tool attr_changer" title="Change ellipse's x radius" alt="rx" size="3"/>
+		<label class="ellipse_tool">ry:</label>
+		<input id="ellipse_ry" class="ellipse_tool attr_changer" title="Change ellipse's y radius" alt="ry" size="3"/>
+	</div>
+
+	<div id="line_panel">
+		<img class="tool_sep" src="images/sep.png" alt="|"/>
+		<label class="line_tool">x1:</label>
+		<input id="line_x1" class="line_tool attr_changer" title="Change line's starting x coordinate" alt="x1" size="3"/>
+		<label class="line_tool">y1:</label>
+		<input id="line_y1" class="line_tool attr_changer" title="Change line's starting y coordinate" alt="y1" size="3"/>
+		<label class="line_tool">x2:</label>
+		<input id="line_x2" class="line_tool attr_changer" title="Change line's ending x coordinate" alt="x2" size="3"/>
+		<label class="line_tool">y2:</label>
+		<input id="line_y2" class="line_tool attr_changer" title="Change line's ending y coordinate" alt="x1" size="3"/>
+	</div>
+
+	<div id="text_panel">
+		<img class="tool_sep" src="images/sep.png" alt="|"/>
+		<label class="text_tool">x:</label>
+		<input id="text_x" class="text_tool attr_changer" title="Change text X coordinate" alt="x" size="3"/>
+		<label class="text_tool">y:</label>
+		<input id="text_y" class="text_tool attr_changer" title="Change text Y coordinate" alt="y" size="3"/>
+		<img class="tool_button" id="tool_bold" src="images/bold.png" title="Bold Text [B]" alt="Bold"/>
+		<img class="tool_button" id="tool_italic" src="images/italic.png" title="Italic Text [I]" alt="Italic"/>
+		<select id="font_family" class="text_tool" title="Change Font Family">
+			<option selected="selected" value="serif">serif</option>
+			<option value="sans-serif">sans-serif</option>
+			<option value="cursive">cursive</option>
+			<option value="fantasy">fantasy</option>
+			<option value="monospace">monospace</option>
+		</select>
+		<select id="font_size" class="text_tool" title="Change Font Size">
+			<option value="6pt">6pt</option>
+			<option value="8pt">8pt</option>
+			<option value="10pt">10pt</option>
+			<option selected="selected" value="12pt">12pt</option>
+			<option value="14pt">14pt</option>
+			<option value="16pt">16pt</option>
+			<option value="20pt">20pt</option>
+			<option value="24pt">24pt</option>
+			<option value="32pt">32pt</option>
+			<option value="48pt">48pt</option>
+			<option value="64pt">64pt</option>
+			<option value="72pt">72pt</option>
+			<option value="80pt">80pt</option>
+			<option value="96pt">96pt</option>
+			<option value="120pt">120pt</option>
+		</select>
+		<input id="text" class="text_tool" type="text" title="Change text contents" size="35"/>
+	</div>
+</div> <!-- tools_top -->
+
+<div id="tools_left" class="tools_panel">
+	<img class="tool_button_current" id="tool_select" src="images/select.png" title="Select Tool [1]" alt="Select"/><br/>
+	<img class="tool_button" id="tool_path" src="images/path.png" title="Pencil Tool [2]" alt="Pencil"/><br/>
+	<img class="tool_button" id="tool_line" src="images/line.png" title="Line Tool [3]" alt="Line"/><br/>
+	<img class="tool_button" id="tools_rect_show" src="images/square.png" title="Square/Rect Tool [4/Shift+4]" alt="Square"/>
+	<img class="flyout_arrow_horiz" src="images/flyouth.png"/>
+	<img class="tool_button" id="tools_ellipse_show" src="images/circle.png" title="Ellipse/Circle Tool [5/Shift+5]" alt="Circle"/><br/>
+	<img class="flyout_arrow_horiz" src="images/flyouth.png"/>
+	<img class="tool_button" id="tool_text" src="images/text.png" title="Text Tool [6]" alt="Text"/>
+	<img class="tool_button" id="tool_poly" src="images/polygon.png" title="Poly Tool [7]" alt="Poly"/>
+</div> <!-- tools_left -->
+
+<div id="tools_bottom" class="tools_panel">
+
+	<div id="tools_bottom_1">
+		<select id="resolution">
+			<option selected="selected">640x480</option>
+			<option>800x600</option>
+			<option>1024x768</option>
+			<option>1280x960</option>
+			<option>1600x1200</option>
+			<option>Fit to Content</option>
+			<option>Custom</option>
+		</select>
+	</div>
+
+	<div id="tools_bottom_2">
+		<table>
+		<tr>
+			<td>fill:</td>
+			<td><div id="fill_color" class="color_block"  title="Change fill color"></div></td>
+			<td><div id="fill_opacity">100%</div></td>
+		</tr><tr>
+			<td>stroke:</td>
+			<td><div id="stroke_color" class="color_block" title="Change stroke color"></div></td>
+			<td><div id="stroke_opacity">100 %</div></td>
+			<td>
+				<input id="stroke_width" title="Change stroke width" alt="Stroke Width" size="2" value="5" type="text"/>
+			</td>
+			<td>
+				<select id="stroke_style" title="Change stroke dash style">
+					<option selected="selected" value="none">---</option>
+					<option value="2,2">...</option>
+					<option value="5,5">- -</option>
+					<option value="5,2,2,2">- .</option>
+					<option value="5,2,2,2,2,2">- ..</option>
+				</select>
+			</td>
+		</tr>
+		</table>
+	</div>
+
+	<div id="tools_bottom_3">
+		<div id="palette_holder"><div id="palette" title="Click to change fill color, shift-click to change stroke color"></div></div>
+		<div id="copyright">Powered by <a href="http://svg-edit.googlecode.com/" target="_blank">SVG-edit v2.3-Alpha</a></div>
+	</div>
+</div>
+
+<!-- hidden divs -->
+<div id="color_picker"></div>
+
+<div id="tools_rect" class="tools_flyout">
+	<div id="tool_square" class="tool_flyout_button" title="Square"></div>
+	<div id="tool_rect" class="tool_flyout_button" title="Rectangle"></div>
+	<div id="tool_fhrect" class="tool_flyout_button" title="Free-Hand Rectangle"></div>
+</div>
+
+<div id="tools_ellipse" class="tools_flyout">
+	<div id="tool_circle" class="tool_flyout_button" title="Circle"></div>
+	<div id="tool_ellipse" class="tool_flyout_button" title="Ellipse"></div>
+	<div id="tool_fhellipse" class="tool_flyout_button" title="Free-Hand Ellipse"></div>
+</div>
+
+<div id="tools_stacking" class="tools_flyout_v">
+	<div id="tool_stacktop" class="tool_flyout_button" title="Move to Top [Shift+Up]"></div>
+	<div id="tool_stackbottom" class="tool_flyout_button" title="Move to Bottom [Shift+Down]"></div>
+</div>
+
+<div id="tools_align" class="tools_flyout_v">
+	<div id="tool_aligntop" class="tool_flyout_button" title="Align to Top"></div>
+	<div id="tool_alignbottom" class="tool_flyout_button" title="Align to Bottom"></div>
+	<div id="tool_alignmiddle" class="tool_flyout_button" title="Align to Middle"></div>
+	<div id="tool_alignleft" class="tool_flyout_button" title="Align to Left"></div>
+	<div id="tool_alignright" class="tool_flyout_button" title="Align to Right"></div>
+	<div id="tool_aligncenter" class="tool_flyout_button" title="Align to Center"></div>
+</div>
+
+</div> <!-- svg_editor -->
+
+<div id="svg_source_editor">
+	<div id="svg_source_overlay"></div>
+	<div id="svg_source_container">
+		<div id="tool_source_back" class="toolbar_button">
+			<button id="tool_source_save"><img src="images/save.png" alt="save" /> Save</button>
+			<button id="tool_source_cancel"><img src="images/cancel.png" alt="cancel" />Cancel</button>
+		</div>
+		<form>
+			<textarea id="svg_source_textarea"></textarea>
+		</form>
+	</div>
+</div>
+
+<script type="text/javascript">
+$(document).ready(svg_edit_setup);
+</script>
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/editor/svg-editor.js	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,906 @@
+if(!window.console) {
+  window.console = new function() {
+    this.log = function(str) {};
+    this.dir = function(str) {};
+  };
+}
+
+function svg_edit_setup() {
+	var palette = ["#000000","#202020","#404040","#606060","#808080","#a0a0a0","#c0c0c0","#e0e0e0","#ffffff","#800000","#ff0000","#808000","#ffff00","#008000","#00ff00","#008080","#00ffff","#000080","#0000ff","#800080","#ff00ff","#2b0000","#550000","#800000","#aa0000","#d40000","#ff0000","#ff2a2a","#ff5555","#ff8080","#ffaaaa","#ffd5d5","#280b0b","#501616","#782121","#a02c2c","#c83737","#d35f5f","#de8787","#e9afaf","#f4d7d7","#241c1c","#483737","#6c5353","#916f6f","#ac9393","#c8b7b7","#e3dbdb","#2b1100","#552200","#803300","#aa4400","#d45500","#ff6600","#ff7f2a","#ff9955","#ffb380","#ffccaa","#ffe6d5","#28170b","#502d16","#784421","#a05a2c","#c87137","#d38d5f","#deaa87","#e9c6af","#f4e3d7","#241f1c","#483e37","#6c5d53","#917c6f","#ac9d93","#c8beb7","#e3dedb","#2b2200","#554400","#806600","#aa8800","#d4aa00","#ffcc00","#ffd42a","#ffdd55","#ffe680","#ffeeaa","#fff6d5","#28220b","#504416","#786721","#a0892c","#c8ab37","#d3bc5f","#decd87","#e9ddaf","#f4eed7","#24221c","#484537","#6c6753","#918a6f","#aca793","#c8c4b7","#e3e2db","#222b00","#445500","#668000","#88aa00","#aad400","#ccff00","#d4ff2a","#ddff55","#e5ff80","#eeffaa","#f6ffd5","#22280b","#445016","#677821","#89a02c","#abc837","#bcd35f","#cdde87","#dde9af","#eef4d7","#22241c","#454837","#676c53","#8a916f","#a7ac93","#c4c8b7","#e2e3db","#112b00","#225500","#338000","#44aa00","#55d400","#66ff00","#7fff2a","#99ff55","#b3ff80","#ccffaa","#e5ffd5","#17280b","#2d5016","#447821","#5aa02c","#71c837","#8dd35f","#aade87","#c6e9af","#e3f4d7","#1f241c","#3e4837","#5d6c53","#7c916f","#9dac93","#bec8b7","#dee3db","#002b00","#005500","#008000","#00aa00","#00d400","#00ff00","#2aff2a","#55ff55","#80ff80","#aaffaa","#d5ffd5","#0b280b","#165016","#217821","#2ca02c","#37c837","#5fd35f","#87de87","#afe9af","#d7f4d7","#1c241c","#374837","#536c53","#6f916f","#93ac93","#b7c8b7","#dbe3db","#002b11","#005522","#008033","#00aa44","#00d455","#00ff66","#2aff80","#55ff99","#80ffb3","#aaffcc","#d5ffe6","#0b2817","#16502d","#217844","#2ca05a","#37c871","#5fd38d","#87deaa","#afe9c6","#d7f4e3","#1c241f","#37483e","#536c5d","#6f917c","#93ac9d","#b7c8be","#dbe3de","#002b22","#005544","#008066","#00aa88","#00d4aa","#00ffcc","#2affd5","#55ffdd","#80ffe6","#aaffee","#d5fff6","#0b2822","#165044","#217867","#2ca089","#37c8ab","#5fd3bc","#87decd","#afe9dd","#d7f4ee","#1c2422","#374845","#536c67","#6f918a","#93aca7","#b7c8c4","#dbe3e2","#00222b","#004455","#006680","#0088aa","#00aad4","#00ccff","#2ad4ff","#55ddff","#80e5ff","#aaeeff","#d5f6ff","#0b2228","#164450","#216778","#2c89a0","#37abc8","#5fbcd3","#87cdde","#afdde9","#d7eef4","#1c2224","#374548","#53676c","#6f8a91","#93a7ac","#b7c4c8","#dbe2e3","#00112b","#002255","#003380","#0044aa","#0055d4","#0066ff","#2a7fff","#5599ff","#80b3ff","#aaccff","#d5e5ff","#0b1728","#162d50","#214478","#2c5aa0","#3771c8","#5f8dd3","#87aade","#afc6e9","#d7e3f4","#1c1f24","#373e48","#535d6c","#6f7c91","#939dac","#b7bec8","#dbdee3","#00002b","#000055","#000080","#0000aa","#0000d4","#0000ff","#2a2aff","#5555ff","#8080ff","#aaaaff","#d5d5ff","#0b0b28","#161650","#212178","#2c2ca0","#3737c8","#5f5fd3","#8787de","#afafe9","#d7d7f4","#1c1c24","#373748","#53536c","#6f6f91","#9393ac","#b7b7c8","#dbdbe3","#11002b","#220055","#330080","#4400aa","#5500d4","#6600ff","#7f2aff","#9955ff","#b380ff","#ccaaff","#e5d5ff","#170b28","#2d1650","#442178","#5a2ca0","#7137c8","#8d5fd3","#aa87de","#c6afe9","#e3d7f4","#1f1c24","#3e3748","#5d536c","#7c6f91","#9d93ac","#beb7c8","#dedbe3","#22002b","#440055","#660080","#8800aa","#aa00d4","#cc00ff","#d42aff","#dd55ff","#e580ff","#eeaaff","#f6d5ff","#220b28","#441650","#672178","#892ca0","#ab37c8","#bc5fd3","#cd87de","#ddafe9","#eed7f4","#221c24","#453748","#67536c","#8a6f91","#a793ac","#c4b7c8","#e2dbe3","#2b0022","#550044","#800066","#aa0088","#d400aa","#ff00cc","#ff2ad4","#ff55dd","#ff80e5","#ffaaee","#ffd5f6","#280b22","#501644","#782167","#a02c89","#c837ab","#d35fbc","#de87cd","#e9afdd","#f4d7ee","#241c22","#483745","#6c5367","#916f8a","#ac93a7","#c8b7c4","#e3dbe2","#2b0011","#550022","#800033","#aa0044","#d40055","#ff0066","#ff2a7f","#ff5599","#ff80b2","#ffaacc","#ffd5e5","#280b17","#50162d","#782144","#a02c5a","#c83771","#d35f8d","#de87aa","#e9afc6","#f4d7e3","#241c1f","#48373e","#6c535d","#916f7c","#ac939d","#c8b7be","#e3dbde"]
+
+	var isMac = false; //(navigator.platform.indexOf("Mac") != -1);
+	var modKey = ""; //(isMac ? "meta+" : "ctrl+");
+	var svgCanvas = new SvgCanvas(document.getElementById("svgcanvas"));
+
+	var setSelectMode = function() {
+		$('.tool_button_current').removeClass('tool_button_current').addClass('tool_button');
+		$('#tool_select').addClass('tool_button_current');
+		$('#styleoverrides').text('*{cursor:move;pointer-events:all} svg{cursor:default}');
+		svgCanvas.setMode('select');
+	};
+
+	// used to make the flyouts stay on the screen longer the very first time
+	var flyoutspeed = 1250;
+	var textBeingEntered = false;
+	var selectedElement = null;
+	var multiselected = false;
+	var editingsource = false;
+	
+	var fillPaint = new $.jGraduate.Paint({solidColor: "FF0000"}); // solid red
+	var strokePaint = new $.jGraduate.Paint({solidColor: "000000"}); // solid black
+
+	// TODO: Unfortunately Mozilla does not handle internal references to gradients
+	// inside a data: URL document.  This means that any elements filled/stroked 
+	// with a gradient will appear black in Firefox, etc.  See bug 308590
+	// https://bugzilla.mozilla.org/show_bug.cgi?id=308590
+	var saveHandler = function(window,svg) {
+		if(window.opera && window.opera.io && window.opera.io.filesystem)
+		{
+			try {
+				window.opera.io.filesystem.browseForSave(
+					new Date().getTime(), /* mountpoint name */
+					"", /* default location */
+					function(file) {
+						try {
+							if (file) {
+								var fstream = file.open(file, "w");
+								fstream.write(svg, "UTF-8");
+								fstream.close();
+							}
+						}
+						catch(e) {
+							console.log("Write to file failed.");
+						}
+					}, 
+					false /* not persistent */
+				);
+			}
+			catch(e) {
+				console.log("Save file failed.");
+			}
+		}
+		else
+		{
+			window.open("data:image/svg+xml;base64," + Utils.encode64(svg));
+		}
+	};
+
+	// called when we've selected a different element
+	var selectedChanged = function(window,elems) {
+		// if elems[1] is present, then we have more than one element
+		selectedElement = (elems.length == 1 || elems[1] == null ? elems[0] : null);
+		multiselected = (elems.length >= 2 && elems[1] != null);
+		if (selectedElement != null) {
+			// unless we're already in always set the mode of the editor to select because
+			// upon creation of a text element the editor is switched into
+			// select mode and this event fires - we need our UI to be in sync
+			if (svgCanvas.getMode() != "multiselect") {
+				setSelectMode();
+			}
+
+			updateToolbar();
+		} // if (elem != null)
+
+		updateContextPanel(); 
+	};
+
+	// called when any element has changed
+	var elementChanged = function(window,elems) {
+		for (var i = 0; i < elems.length; ++i) {
+			var elem = elems[i];
+			// if the element changed was the svg, then it could be a resolution change
+			if (elem && elem.tagName == "svg") {
+				changeResolution(parseInt(elem.getAttribute("width")),
+								 parseInt(elem.getAttribute("height")));
+			}
+		}
+
+		// we update the contextual panel with potentially new
+		// positional/sizing information (we DON'T want to update the
+		// toolbar here as that creates an infinite loop)
+		// also this updates the history buttons
+
+		// we tell it to skip focusing the text control if the
+		// text element was previously in focus
+		updateContextPanel();
+	};
+
+	// updates the toolbar (colors, opacity, etc) based on the selected element
+	var updateToolbar = function() {
+		if (selectedElement != null) {
+			// get opacity values
+			var fillOpacity = parseFloat(selectedElement.getAttribute("fill-opacity"));
+			if (isNaN(fillOpacity)) {
+				fillOpacity = 1.0;
+			}
+			
+			var strokeOpacity = parseFloat(selectedElement.getAttribute("stroke-opacity"));
+			if (isNaN(strokeOpacity)) {
+				strokeOpacity = 1.0;
+			}
+
+			// update fill color and opacity
+			var fillColor = selectedElement.getAttribute("fill")||"none";
+			svgCanvas.setFillColor(fillColor);
+			svgCanvas.setFillOpacity(fillOpacity);
+
+			// update stroke color and opacity
+			var strokeColor = selectedElement.getAttribute("stroke")||"none";
+			svgCanvas.setStrokeColor(strokeColor);
+			svgCanvas.setStrokeOpacity(strokeOpacity);
+
+			fillOpacity *= 100;
+			strokeOpacity *= 100;
+			
+			var getPaint = function(color, opac) {
+				// update the editor's fill paint
+				var opts = null;
+				
+				if (color.substr(0,5) == "url(#") {
+					opts = {
+						alpha: opac,
+						linearGradient: document.getElementById(color.substr(5,color.length-6))
+					};
+				} 
+				else if (color.substr(0,1) == "#") {
+					opts = {
+						alpha: opac,
+						solidColor: color.substr(1)
+					};
+				}
+				return new $.jGraduate.Paint(opts);
+			}
+			
+			fillPaint = getPaint(fillColor, fillOpacity);
+			strokePaint = getPaint(strokeColor, strokeOpacity);
+			
+			fillOpacity = fillOpacity + " %";
+			strokeOpacity = strokeOpacity + " %";
+
+			// update fill color
+			if (fillColor == "none") {
+				fillOpacity = "N/A";
+			}
+			document.getElementById("gradbox_fill").parentNode.firstChild.setAttribute("fill", fillColor);
+
+			if (strokeColor == null || strokeColor == "" || strokeColor == "none") {
+				strokeColor = "none";
+				strokeOpacity = "N/A";
+			}
+			
+			// update the rect inside #fill_color
+			document.getElementById("gradbox_stroke").parentNode.firstChild.setAttribute("fill", strokeColor);
+			
+			$('#fill_opacity').html(fillOpacity);
+			$('#stroke_opacity').html(strokeOpacity);
+			$('#group_opacity').val(((selectedElement.getAttribute("opacity")||1.0)*100)+" %");
+			$('#stroke_width').val(selectedElement.getAttribute("stroke-width")||1);
+			$('#stroke_style').val(selectedElement.getAttribute("stroke-dasharray")||"none");
+		}
+
+		updateToolButtonState();
+	};
+
+	// updates the context panel tools based on the selected element
+	var updateContextPanel = function() {
+		var elem = selectedElement;
+		$('#selected_panel, #multiselected_panel, #rect_panel, #circle_panel,\
+			#ellipse_panel, #line_panel, #text_panel').hide();
+		if (elem != null) {
+			$('#angle').val(svgCanvas.getRotationAngle(elem));
+			$('#selected_panel').show();
+			
+			// update contextual tools here
+			var panels = {
+				rect: ['radius','x','y','width','height'],
+				circle: ['cx','cy','r'],
+				ellipse: ['cx','cy','rx','ry'],
+				line: ['x1','y1','x2','y2'], 
+				text: ['x','y']
+			};
+			
+			var el_name = elem.tagName;
+			
+			if(panels[el_name]) {
+			
+				var cur_panel = panels[el_name];
+				
+				
+				$('#' + el_name + '_panel').show();
+	
+				$.each(cur_panel, function(i, item) {
+					$('#' + el_name + '_' + item).val(elem.getAttribute(item) || 0);
+				});
+				
+				if(el_name == 'text') {
+					$('#text_panel').css("display", "inline");	
+					if (svgCanvas.getItalic()) {
+						$('#tool_italic').addClass('tool_button_current');
+					}
+					else {
+						$('#tool_italic').removeClass('tool_button_current');
+					}
+					if (svgCanvas.getBold()) {
+						$('#tool_bold').addClass('tool_button_current');
+					}
+					else {
+						$('#tool_bold').removeClass('tool_button_current');
+					}
+					$('#font_family').val(elem.getAttribute("font-family"));
+					$('#font_size').val(elem.getAttribute("font-size"));
+					$('#text').val(elem.textContent);
+					if (svgCanvas.addedNew) {
+						$('#text').focus().select();
+					}
+				}
+			}
+		} // if (elem != null)
+		else if (multiselected) {
+			$('#multiselected_panel').show();
+		}
+		
+		// update history buttons
+		if (svgCanvas.getUndoStackSize() > 0) {
+			$('#tool_undo').removeClass( 'tool_button_disabled');
+		}
+		else {
+			$('#tool_undo').addClass( 'tool_button_disabled');
+		}
+		if (svgCanvas.getRedoStackSize() > 0) {
+			$('#tool_redo').removeClass( 'tool_button_disabled');
+		}
+		else {
+			$('#tool_redo').addClass( 'tool_button_disabled');
+		}
+		
+		svgCanvas.addedNew = false;
+	};
+
+	$('#text').focus( function(){ textBeingEntered = true; } );
+	$('#text').blur( function(){ textBeingEntered = false; } );
+
+	// bind the selected event to our function that handles updates to the UI
+	svgCanvas.bind("selected", selectedChanged);
+	svgCanvas.bind("changed", elementChanged);
+	svgCanvas.bind("saved", saveHandler);
+
+	var str = '<div class="palette_item" style="background-image: url(\'images/none.png\');" data-rgb="none"></div>'
+	$.each(palette, function(i,item){
+		str += '<div class="palette_item" style="background-color: ' + item + ';" data-rgb="' + item + '"></div>';
+	});
+	$('#palette').append(str);
+
+	var pos = $('#tools_rect_show').position();
+	$('#tools_rect').css({'left': pos.left+4, 'top': pos.top+70});
+	pos = $('#tools_ellipse_show').position();
+	$('#tools_ellipse').css({'left': pos.left+4, 'top': pos.top+70});
+
+	var changeRectRadius = function(ctl) {
+		svgCanvas.setRectRadius(ctl.value);
+	}
+	
+	var changeStrokeWidth = function(ctl) {
+		svgCanvas.setStrokeWidth(ctl.value);
+	}
+	
+	var changeRotationAngle = function(ctl) {
+		svgCanvas.setRotationAngle(ctl.value);
+	}
+
+	$('#stroke_style').change(function(){
+		svgCanvas.setStrokeStyle(this.options[this.selectedIndex].value);
+	});
+
+	$('#group_opacity').change(function(){
+		svgCanvas.setOpacity(this.options[this.selectedIndex].value);
+	});
+
+	$('#font_size').change(function(){
+		svgCanvas.setFontSize(this.options[this.selectedIndex].value);
+	});
+
+	$('#font_family').change(function(){
+		svgCanvas.setFontFamily(this.options[this.selectedIndex].value);
+	});
+
+	$('#text').keyup(function(){
+		svgCanvas.setTextContent(this.value);
+	});
+
+	$('.attr_changer').change(function() {
+		svgCanvas.changeSelectedAttribute(this.getAttribute("alt"), this.value);
+	});
+
+	$('.palette_item').click(function(evt){
+		var picker = (evt.shiftKey ? "stroke" : "fill");
+		var id = (evt.shiftKey ? '#stroke_' : '#fill_');
+		var color = $(this).attr('data-rgb');
+		var rectbox = document.getElementById("gradbox_"+picker).parentNode.firstChild;
+		var paint = null;
+
+		// Webkit-based browsers returned 'initial' here for no stroke
+		if (color == 'transparent' || color == 'initial') {
+			color = 'none';
+			$(id + "opacity").html("N/A");
+			paint = new $.jGraduate.Paint();
+		}
+		else {
+			paint = new $.jGraduate.Paint({alpha: 100, solidColor: color.substr(1)});
+		}
+		rectbox.setAttribute("fill", color);
+		
+		if (evt.shiftKey) {
+			strokePaint = paint;
+			svgCanvas.setStrokeColor(color);
+			if (color != 'none') {
+				svgCanvas.setStrokeOpacity(1.0);
+				$("#stroke_opacity").html("100 %");
+			}
+		} else {
+			fillPaint = paint;
+			svgCanvas.setFillColor(color);
+			if (color != 'none') {
+				svgCanvas.setFillOpacity(1.0);
+				$("#fill_opacity").html("100 %");
+			}
+		}
+		updateToolButtonState();
+	});
+
+	// This is a common function used when a tool has been clicked (chosen)
+	// It does several common things:
+	// - removes the tool_button_current class from whatever tool currently has it
+	// - hides any flyouts
+	// - adds the tool_button_current class to the button passed in
+	var toolButtonClick = function(button, fadeFlyouts) {
+		if ($(button).hasClass('tool_button_disabled')) return false;
+		var fadeFlyouts = fadeFlyouts || 'normal';
+		$('.tools_flyout').fadeOut(fadeFlyouts);
+		$('#styleoverrides').text('');
+		$('.tool_button_current').removeClass('tool_button_current').addClass('tool_button');
+		$(button).addClass('tool_button_current');
+		// when a tool is selected, we should deselect any currently selected elements
+		svgCanvas.clearSelection();
+		return true;
+	};
+
+	var clickSelect = function() {
+		if (toolButtonClick('#tool_select')) {
+			svgCanvas.setMode('select');
+			$('#styleoverrides').text('*{cursor:move;pointer-events:all} svg{cursor:default}');
+		}
+	};
+
+	var clickPath = function() {
+		if (toolButtonClick('#tool_path')) {
+			svgCanvas.setMode('path');
+		}
+	};
+
+	var clickLine = function() {
+		if (toolButtonClick('#tool_line')) {
+			svgCanvas.setMode('line');
+		}
+	};
+
+	var clickSquare = function(){
+		if (toolButtonClick('#tools_rect_show', flyoutspeed)) {
+			flyoutspeed = 'normal';
+			svgCanvas.setMode('square');
+		}
+		$('#tools_rect_show').attr('src', 'images/square.png');
+	};
+
+	var clickRect = function(){
+		if (toolButtonClick('#tools_rect_show')) {
+			svgCanvas.setMode('rect');
+		}
+		$('#tools_rect_show').attr('src', 'images/rect.png');
+	};
+
+	var clickFHRect = function(){
+		if (toolButtonClick('#tools_rect_show')) {
+			svgCanvas.setMode('fhrect');
+		}
+		$('#tools_rect_show').attr('src', 'images/freehand-square.png');
+	};
+
+	var clickCircle = function(){
+		if (toolButtonClick('#tools_ellipse_show', flyoutspeed)) {
+			flyoutspeed = 'normal';
+			svgCanvas.setMode('circle');
+		}
+		$('#tools_ellipse_show').attr('src', 'images/circle.png');
+	};
+
+	var clickEllipse = function(){
+		if (toolButtonClick('#tools_ellipse_show')) {
+			svgCanvas.setMode('ellipse');
+		}
+		$('#tools_ellipse_show').attr('src', 'images/ellipse.png');
+	};
+
+	var clickFHEllipse = function(){
+		if (toolButtonClick('#tools_ellipse_show')) {
+			svgCanvas.setMode('fhellipse');
+		}
+		$('#tools_ellipse_show').attr('src', 'images/freehand-circle.png');
+	};
+
+	var clickText = function(){
+		toolButtonClick('#tool_text');
+		svgCanvas.setMode('text');
+	};
+	
+	var clickPoly = function(){
+		toolButtonClick('#tool_poly');
+		svgCanvas.setMode('poly');
+	};
+	
+	// Delete is a contextual tool that only appears in the ribbon if
+	// an element has been selected
+	var deleteSelected = function() {
+		if (selectedElement != null || multiselected) {
+			svgCanvas.deleteSelectedElements();
+		}
+	};
+
+	var moveToTopSelected = function() {
+		if (selectedElement != null) {
+			svgCanvas.moveToTopSelectedElement();
+		}
+	};
+
+	var moveToBottomSelected = function() {
+		if (selectedElement != null) {
+			svgCanvas.moveToBottomSelectedElement();
+		}
+	};
+
+	var moveSelected = function(dx,dy) {
+		if (selectedElement != null || multiselected) {
+			svgCanvas.moveSelectedElements(dx,dy);
+		}
+	};
+	
+	var selectNext = function() {
+		svgCanvas.cycleElement(1);
+	}
+	
+	var selectPrev = function() {
+		svgCanvas.cycleElement(0);
+	}
+
+	var rotateSelected = function(cw) {
+		if (selectedElement == null || multiselected) return;
+		var step = 5;
+		if(!cw) step *= -1;
+		var new_angle = $('#angle').val()*1 + step;
+		svgCanvas.setRotationAngle(new_angle);
+	}
+	
+	var clickClear = function(){
+		if( confirm('Do you want to clear the drawing?\nThis will also erase your undo history!') ) {
+			svgCanvas.clear();
+			updateContextPanel();
+		}
+	};
+	
+	var clickBold = function(){
+		svgCanvas.setBold( !svgCanvas.getBold() );
+		updateContextPanel();
+	};
+	
+	var clickItalic = function(){
+		svgCanvas.setItalic( !svgCanvas.getItalic() );
+		updateContextPanel();
+	};
+
+	var clickSave = function(){
+		svgCanvas.save();
+	};
+	
+	var clickOpen = function(){
+		svgCanvas.open();
+	};
+
+	var clickUndo = function(){
+		if (svgCanvas.getUndoStackSize() > 0)
+			svgCanvas.undo();
+	};
+
+	var clickRedo = function(){
+		if (svgCanvas.getRedoStackSize() > 0)
+			svgCanvas.redo();
+	};
+	
+	var clickClone = function(){
+		svgCanvas.cloneSelectedElements();
+	};
+	
+	var clickAlignLeft = function(){
+		svgCanvas.alignSelectedElements('l');
+	};
+	var clickAlignCenter = function(){
+		svgCanvas.alignSelectedElements('c');
+	};
+	var clickAlignRight = function(){
+		svgCanvas.alignSelectedElements('r');
+	};
+	var clickAlignTop = function(){
+		svgCanvas.alignSelectedElements('t');
+	};
+	var clickAlignMiddle = function(){
+		svgCanvas.alignSelectedElements('m');
+	};
+	var clickAlignBottom = function(){
+		svgCanvas.alignSelectedElements('b');
+	};
+	
+	var showSourceEditor = function(){
+		if (editingsource) return;
+		editingsource = true;
+		var str = svgCanvas.getSvgString();
+		$('#svg_source_textarea').val(str);
+		$('#svg_source_editor').fadeIn();
+		properlySourceSizeTextArea();
+		$('#svg_source_textarea').focus();
+	};
+	
+	var properlySourceSizeTextArea = function(){
+		// TODO: remove magic numbers here and get values from CSS
+		var height = $('#svg_source_container').height() - 80;
+		$('#svg_source_textarea').css('height', height);
+	};
+	
+	var saveSourceEditor = function(){
+		if (!editingsource) return;
+
+		if (!svgCanvas.setSvgString($('#svg_source_textarea').val())) {
+			if( !confirm('There were parsing errors in your SVG source.\nRevert back to original SVG source?') ) {
+				return false;
+			}
+		}
+		svgCanvas.clearSelection();
+		hideSourceEditor();
+	};
+
+	var cancelSourceEditor = function() {
+		if (!editingsource) return;
+
+		var oldString = svgCanvas.getSvgString();
+		if (oldString != $('#svg_source_textarea').val()) {
+			if( !confirm('Ignore changes made to SVG source?') ) {
+				return false;
+			}
+		}
+		hideSourceEditor();
+	};
+
+	var hideSourceEditor = function(){
+		$('#svg_source_editor').hide();
+		editingsource = false;
+		$('#svg_source_textarea').blur();
+	};
+	
+	// TODO: add canvas-centering code in here
+	$(window).resize(function(evt) {
+		if (!editingsource) return;
+		properlySourceSizeTextArea();
+	});
+
+	$('#tool_select').click(clickSelect);
+	$('#tool_path').click(clickPath);
+	$('#tool_line').click(clickLine);
+	$('#tool_square').mouseup(clickSquare);
+	$('#tool_rect').mouseup(clickRect);
+	$('#tool_fhrect').mouseup(clickFHRect);
+	$('#tool_circle').mouseup(clickCircle);
+	$('#tool_ellipse').mouseup(clickEllipse);
+	$('#tool_fhellipse').mouseup(clickFHEllipse);
+	$('#tool_text').click(clickText);
+	$('#tool_poly').click(clickPoly);
+	$('#tool_clear').click(clickClear);
+	$('#tool_save').click(clickSave);
+	$('#tool_open').click(clickOpen);
+	$('#tool_source').click(showSourceEditor);
+	$('#tool_source_cancel,#svg_source_overlay').click(cancelSourceEditor);
+	$('#tool_source_save').click(saveSourceEditor);
+	$('#tool_delete').click(deleteSelected);
+	$('#tool_delete_multi').click(deleteSelected);
+	$('#tool_move_top').click(moveToTopSelected);
+	$('#tool_move_bottom').click(moveToBottomSelected);
+	$('#tool_undo').click(clickUndo);
+	$('#tool_redo').click(clickRedo);
+	$('#tool_clone').click(clickClone);
+	$('#tool_clone_multi').click(clickClone);
+	$('#tool_alignleft').click(clickAlignLeft);
+	$('#tool_aligncenter').click(clickAlignCenter);
+	$('#tool_alignright').click(clickAlignRight);
+	$('#tool_aligntop').click(clickAlignTop);
+	$('#tool_alignmiddle').click(clickAlignMiddle);
+	$('#tool_alignbottom').click(clickAlignBottom);
+	// these two lines are required to make Opera work properly with the flyout mechanism
+	$('#tools_rect_show').click(clickSquare);
+	$('#tools_ellipse_show').click(clickCircle);
+	$('#tool_bold').mousedown(clickBold);
+	$('#tool_italic').mousedown(clickItalic);
+
+	// added these event handlers for all the push buttons so they
+	// behave more like buttons being pressed-in and not images
+	function setPushButtons() {
+		var toolnames = ['clear','open','save','source','delete','delete_multi','paste','clone','clone_multi','move_top','move_bottom'];
+		var all_tools = '';
+		var cur_class = 'tool_button_current';
+		
+		$.each(toolnames, function(i,item) {
+			all_tools += '#tool_' + item + (i==toolnames.length-1?',':'');
+		});
+		
+		$(all_tools).mousedown(function() {
+			$(this).addClass(cur_class);
+		}).bind('mousedown mouseout', function() {
+			$(this).removeClass(cur_class);
+		});
+		
+		$('#tool_undo, #tool_redo').mousedown(function(){ 
+			if (!$(this).hasClass('tool_button_disabled')) $(this).addClass(cur_class);
+		}).bind('mousedown mouseout',function(){
+			$(this).removeClass(cur_class);}
+		);
+	}
+	
+	setPushButtons();
+
+	// switch modifier key in tooltips if mac
+	// NOTE: This code is not used yet until I can figure out how to successfully bind ctrl/meta
+	// in Opera and Chrome
+	if (isMac) {
+		var shortcutButtons = ["tool_clear", "tool_save", "tool_source", "tool_undo", "tool_redo", "tool_clone"];
+		var i = shortcutButtons.length;
+		while (i--) {
+			var button = document.getElementById(shortcutButtons[i]);
+			var title = button.title;
+			var index = title.indexOf("Ctrl+");
+			console.log(index);
+			button.title = [title.substr(0,index), "Cmd+", title.substr(index+5)].join('');
+		}
+	}
+	
+	// do keybindings using jquery-hotkeys plugin
+	function setKeyBindings() {
+		var keys = [
+			['1', clickSelect],
+			['2', clickPath],
+			['3', clickLine],
+			['Shift+4', clickSquare],
+			['4', clickRect],
+			['Shift+5', clickCircle],
+			['5', clickEllipse],
+			['6', clickText],
+			['7', clickPoly],
+			[modKey+'N', function(evt){clickClear();evt.preventDefault();}],
+			[modKey+'S', function(evt){editingsource?saveSourceEditor():clickSave();evt.preventDefault();}],
+			[modKey+'O', function(evt){clickOpen();evt.preventDefault();}],
+			['del', function(evt){deleteSelected();evt.preventDefault();}],
+			['backspace', function(evt){deleteSelected();evt.preventDefault();}],
+			['shift+up', moveToTopSelected],
+			['shift+down', moveToBottomSelected],
+			['shift+left', function(){rotateSelected(0)}],
+			['shift+right', function(){rotateSelected(1)}],
+			['shift+9', selectPrev],
+			['shift+0', selectNext],
+			['up', function(evt){moveSelected(0,-1);evt.preventDefault();}],
+			['down', function(evt){moveSelected(0,1);evt.preventDefault();}],
+			['left', function(evt){moveSelected(-1,0);evt.preventDefault();}],
+			['right', function(evt){moveSelected(1,0);evt.preventDefault();}],
+			[modKey+'z', function(evt){clickUndo();evt.preventDefault();}],
+			[modKey+'y', function(evt){clickRedo();evt.preventDefault();}],
+			[modKey+'u', function(evt){showSourceEditor();evt.preventDefault();}],
+			[modKey+'c', function(evt){clickClone();evt.preventDefault();}],
+			['esc', cancelSourceEditor, false],
+		];
+		
+		$.each(keys,function(i,item) {
+			var disable = !(item.length > 2 && !item[2]);
+			$(document).bind('keydown', {combi:item[0], disableInInput: disable}, item[1]);
+		});
+	}
+	
+	setKeyBindings();
+
+	// TODO: fix opacity being updated
+	// TODO: go back to the color boxes having white background-color and then setting
+	//       background-image to none.png (otherwise partially transparent gradients look weird)	
+	var colorPicker = function(elem) {
+		var picker = elem.attr('id') == 'stroke_color' ? 'stroke' : 'fill';
+		var opacity = (picker == 'stroke' ? $('#stroke_opacity') : $('#fill_opacity'));
+
+		var paint = (picker == 'stroke' ? strokePaint : fillPaint);
+		var title = (picker == 'stroke' ? 'Pick a Stroke Paint and Opacity' : 'Pick a Fill Paint and Opacity');
+		var was_none = false;
+		
+		if (paint.type == "none") {
+			// if it was none, then set to solid white
+			paint = new $.jGraduate.Paint({solidColor: 'ffffff'});
+			was_none = true;
+		}
+		var pos = elem.position();
+		$('#color_picker').css({'left': pos.left - 140, 'bottom': 124 - pos.top}).jGraduate(
+			{ 
+				paint: paint,
+				window: { pickerTitle: title },
+				images: { clientPath: "jgraduate/images/" },
+			},
+			function(p) {
+				paint = new $.jGraduate.Paint(p);
+				
+				var oldgrad = document.getElementById("gradbox_"+picker);
+				var svgbox = oldgrad.parentNode;
+				var rectbox = svgbox.firstChild;
+				
+				if (paint.type == "linearGradient") {
+					svgbox.removeChild(oldgrad);
+					var newgrad = svgbox.appendChild(document.importNode(paint.linearGradient, true));
+					newgrad.id = "gradbox_"+picker;
+					rectbox.setAttribute("fill", "url(#gradbox_" + picker + ")");
+				}
+				else {
+					rectbox.setAttribute("fill", "#" + paint.solidColor);
+				}
+				opacity.html(paint.alpha + " %");
+
+				if (picker == 'stroke') {
+					svgCanvas.setStrokePaint(paint, true);
+				}
+				else {
+					svgCanvas.setFillPaint(paint, true);
+				}
+				
+				$('#color_picker').hide();
+			},
+			function(p) {
+				$('#color_picker').hide();
+			});
+	};
+
+	var updateToolButtonState = function() {
+		var bNoFill = (svgCanvas.getFillColor() == 'none');
+		var bNoStroke = (svgCanvas.getStrokeColor() == 'none');
+		var buttonsNeedingStroke = [ '#tool_path', '#tool_line' ];
+		var buttonsNeedingFillAndStroke = [ '#tools_rect_show', '#tools_ellipse_show', '#tool_text' ];
+		if (bNoStroke) {
+			for (index in buttonsNeedingStroke) {
+				var button = buttonsNeedingStroke[index];
+				if ($(button).hasClass('tool_button_current')) {
+					clickSelect();
+				}
+				$(button).removeClass('tool_button').addClass('tool_button_disabled');
+			}
+		}
+		else {
+			for (index in buttonsNeedingStroke) {
+				var button = buttonsNeedingStroke[index];
+				$(button).removeClass('tool_button_disabled').addClass('tool_button');
+			}
+		}
+
+		if (bNoStroke && bNoFill) {
+			for (index in buttonsNeedingFillAndStroke) {
+				var button = buttonsNeedingFillAndStroke[index];
+				if ($(button).hasClass('tool_button_current')) {
+					clickSelect();
+				}
+				$(button).removeClass('tool_button').addClass('tool_button_disabled');
+			}
+		}
+		else {
+			for (index in buttonsNeedingFillAndStroke) {
+				var button = buttonsNeedingFillAndStroke[index];
+				$(button).removeClass('tool_button_disabled').addClass('tool_button');
+			}
+		}
+	};
+
+	// set up gradients to be used for the buttons
+	var svgdocbox = new DOMParser().parseFromString(
+		'<svg xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="#FF0000"/>\
+		<linearGradient id="gradbox_">\
+				<stop stop-color="#000" offset="0.0"/>\
+				<stop stop-color="#FF0000" offset="1.0"/>\
+		</linearGradient></svg>', 'text/xml');
+
+	var boxgrad = svgdocbox.getElementById('gradbox_');
+	boxgrad.id = 'gradbox_fill';
+	$('#fill_color').append( document.importNode(svgdocbox.documentElement,true) );
+	
+	boxgrad.id = 'gradbox_stroke';	
+	$(svgdocbox.documentElement.firstChild).attr('fill', '#000000');
+	$('#stroke_color').append( document.importNode(svgdocbox.documentElement,true) );
+		
+	$('#fill_color').click(function(){
+		colorPicker($(this));
+		updateToolButtonState();
+	});
+
+	$('#stroke_color').click(function(){
+		colorPicker($(this));
+		updateToolButtonState();
+	});
+
+	$('#tools_rect_show').mousedown(function(evt){
+		$('#tools_rect').show();
+		// this prevents the 'image drag' behavior in Firefox
+		evt.preventDefault();
+	});
+	$('#tools_rect').mouseleave(function(){$('#tools_rect').fadeOut();});
+
+	$('#tool_move_top').mousedown(function(evt){
+		$('#tools_stacking').show();
+		evt.preventDefault();
+	});
+
+	$('#tools_ellipse_show').mousedown(function(evt){
+		$('#tools_ellipse').show();
+		// this prevents the 'image drag' behavior in Firefox
+		evt.preventDefault();
+	});
+	$('#tools_ellipse').mouseleave(function() {$('#tools_ellipse').fadeOut();});
+
+	$('.tool_flyout_button').mouseover(function() {
+		$(this).addClass('tool_flyout_button_current');
+	}).mouseout(function() {
+		$(this).removeClass('tool_flyout_button_current');
+	});
+
+	function changeResolution(x,y) {
+		var new_res = x+'x'+y;
+		var found = false;
+		$('#resolution option').each(function() {
+			if($(this).text() == new_res) {
+				$('#resolution').val(x+'x'+y);
+				found = true;
+			}
+		});
+		if(!found) $('#resolution').val('Custom');
+		
+		$('#svgcanvas').css( { 'width': x, 'height': y } );
+	}
+
+	$('#resolution').change(function(){
+		if(this.value == 'Custom') {
+			var cust_val = prompt("Please enter custom size (i.e. 400x300)","");
+			var res_vals = cust_val.match(/(\d+)[x \/,](\d+)/);
+			if(!res_vals) {
+				alert('Invalid size. Please format it as WIDTHxHEIGHT (like 400x300)');
+				return false;
+			} else {
+				var x = res_vals[1], y = res_vals[2];
+				if(x == '0' || y == '0') {
+					alert('Invalid size. Width or height may not be 0.');
+					return false;
+				}
+			}
+		} else if(this.value == 'Fit to content'){
+			var x = '', y = '';
+		} else {
+			var res = this.value.split('x');
+			var x = parseInt(res[0]), y = parseInt(res[1]);
+		}
+		svgCanvas.setResolution(x,y);
+	});
+
+	$('#rect_rx').SpinButton({ min: 0, max: 1000, step: 1, callback: changeRectRadius });
+	$('#stroke_width').SpinButton({ min: 1, max: 99, step: 1, callback: changeStrokeWidth });
+	$('#angle').SpinButton({ min: -180, max: 180, step: 5, callback: changeRotationAngle });
+
+	// if Opera and in widget form, enable the Open button
+	if (window.opera) {
+		opera.postError('opera.io=' + opera.io);
+		if(opera && opera.io && opera.io.filesystem) {
+			$('#tool_open').show();
+		}
+	}
+
+	return svgCanvas;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/svg-edit/editor/svgcanvas.js	Sun Aug 23 00:56:18 2009 +0200
@@ -0,0 +1,2855 @@
+/*
+TODOs for Rotator:
+
+- resize rotated elements must work properly with the selector (aligned to the axis of rotation)
+- show the proper resize cursor based on the rotation
+- add a rotator line/handle to the selector group
+- respond to mouse down on the rotator handle to start 'rotate' mode
+- respond to mouse move in rotate mode to change the rotation of the element
+- upon mouse up in rotate mode go back to select mode
+
+*/
+if(!window.console) {
+  window.console = new function() {
+    this.log = function(str) {};
+    this.dir = function(str) {};
+  };
+}
+
+// this defines which elements and attributes that we support
+// TODO: add <g> elements to this
+// TODO: add <a> elements to this
+// TODO: add xmlns:xlink attr to <svg> element
+var svgWhiteList = {
+	"circle": ["cx", "cy", "fill", "fill-opacity", "id", "r", "stroke", "stroke-dasharray", "stroke-opacity", "stroke-width", "transform"],
+	"defs": [],
+	"ellipse": ["cx", "cy", "fill", "fill-opacity", "id", "rx", "ry", "stroke", "stroke-dasharray", "stroke-opacity", "stroke-width", "transform"],
+	"line": ["fill", "fill-opacity", "id", "stroke", "stroke-dasharray", "stroke-linecap", "stroke-opacity", "stroke-width",  "transform", "x1", "x2", "y1", "y2"],
+	"linearGradient": ["id", "gradientTransform", "gradientUnits", "spreadMethod", "x1", "x2", "y1", "y2"],
+	"path": ["d", "fill", "fill-opacity", "id", "stroke", "stroke-dasharray", "stroke-linecap", "stroke-linejoin", "stroke-opacity", "stroke-width", "transform"],
+	"polygon": ["id", "fill", "fill-opacity", "points", "stroke", "stroke-dasharray", "stroke-linecap", "stroke-linejoin", "stroke-opacity", "stroke-width", "transform"],
+	"polyline": ["id", "points", "stroke", "stroke-dasharray", "stroke-linecap", "stroke-linejoin", "stroke-opacity", "stroke-width", "transform"],
+	"radialGradient": ["id", "cx", "cy", "fx", "fy", "gradientTransform", "gradientUnits", "r", "spreadMethod"],
+	"rect": ["fill", "fill-opacity", "height", "id", "stroke", "stroke-dasharray", "stroke-linecap", "stroke-linejoin", "stroke-opacity", "stroke-width", "transform", "width", "x", "y"],
+	"stop": ["id", "offset", "stop-color", "stop-opacity"],
+	"svg": ["id", "height", "transform", "width", "xmlns"],
+	"text": ["fill", "fill-opacity", "font-family", "font-size", "font-style", "font-weight", "id", "stroke", "stroke-dasharray", "stroke-linecap", "stroke-linejoin", "stroke-opacity", "stroke-width", "transform", "x", "y"],
+};
+
+// These command objects are used for the Undo/Redo stack
+// attrs contains the values that the attributes had before the change
+function ChangeElementCommand(elem, attrs, text) {
+	this.elem = elem;
+	this.text = text ? ("Change " + elem.tagName + " " + text) : ("Change " + elem.tagName);
+	this.newValues = {};
+	this.oldValues = attrs;
+	for (attr in attrs) {
+		if (attr == "#text") this.newValues[attr] = elem.textContent;
+		else this.newValues[attr] = elem.getAttribute(attr);
+	}
+
+	this.apply = function() {
+		for( attr in this.newValues ) {
+			if (this.newValues[attr]) {
+				if (attr == "#text") this.elem.textContent = this.newValues[attr];
+				else this.elem.setAttribute(attr, this.newValues[attr]);
+			}
+			else {
+				if (attr != "#text") this.elem.textContent = "";
+				else this.elem.removeAttribute(attr);
+			}
+		}
+		return true;
+	};
+
+	this.unapply = function() {
+		for( attr in this.oldValues ) {
+			if (this.oldValues[attr]) {
+				if (attr == "#text") this.elem.textContent = this.oldValues[attr];
+				else this.elem.setAttribute(attr, this.oldValues[attr]);
+			}
+			else {
+				if (attr == "#text") this.elem.textContent = "";
+				else this.elem.removeAttribute(attr);
+			}
+		}
+		return true;
+	};
+
+	this.elements = function() { return [this.elem]; }
+}
+
+function InsertElementCommand(elem, text) {
+	this.elem = elem;
+	this.text = text || ("Create " + elem.tagName);
+	this.parent = elem.parentNode;
+
+	this.apply = function() { this.elem = this.parent.insertBefore(this.elem, this.elem.nextSibling); };
+
+	this.unapply = function() {
+		this.parent = this.elem.parentNode;
+		this.elem = this.elem.parentNode.removeChild(this.elem);
+	};
+
+	this.elements = function() { return [this.elem]; };
+}
+
+function RemoveElementCommand(elem, parent, text) {
+	this.elem = elem;
+	this.text = text || ("Delete " + elem.tagName);
+	this.parent = parent;
+
+	this.apply = function() {
+		this.parent = this.elem.parentNode;
+		this.elem = this.parent.removeChild(this.elem);
+	};
+
+	this.unapply = function() { this.elem = this.parent.insertBefore(this.elem, this.elem.nextSibling); };
+
+	this.elements = function() { return [this.elem]; };
+}
+
+function MoveElementCommand(elem, oldNextSibling, oldParent, text) {
+	this.elem = elem;
+	this.text = text ? ("Move " + elem.tagName + " to " + text) : ("Move " + elem.tagName + "top/bottom");
+	this.oldNextSibling = oldNextSibling;
+	this.oldParent = oldParent;
+	this.newNextSibling = elem.nextSibling;
+	this.newParent = elem.parentNode;
+
+	this.apply = function() {
+		this.elem = this.newParent.insertBefore(this.elem, this.newNextSibling);
+	};
+
+	this.unapply = function() {
+		this.elem = this.oldParent.insertBefore(this.elem, this.oldNextSibling);
+	};
+
+	this.elements = function() { return [this.elem]; };
+}
+
+// TODO: create a 'typing' command object that tracks changes in text
+// if a new Typing command is created and the top command on the stack is also a Typing
+// and they both affect the same element, then collapse the two commands into one
+
+// this command object acts an arbitrary number of subcommands 
+function BatchCommand(text) {
+	this.text = text || "Batch Command";
+	this.stack = [];
+
+	this.apply = function() {
+		var len = this.stack.length;
+		for (var i = 0; i < len; ++i) {
+			this.stack[i].apply();
+		}
+	};
+
+	this.unapply = function() {
+		for (var i = this.stack.length-1; i >= 0; i--) {
+			this.stack[i].unapply();
+		}
+	};
+
+	this.elements = function() {
+		// iterate through all our subcommands and find all the elements we are changing
+		var elems = [];
+		var cmd = this.stack.length;
+		while (cmd--) {
+			var thisElems = this.stack[cmd].elements();
+			var elem = thisElems.length;
+			while (elem--) {
+				if (elems.indexOf(thisElems[elem]) == -1) elems.push(thisElems[elem]);
+			}
+		}
+		return elems; 
+	};
+
+	this.addSubCommand = function(cmd) { this.stack.push(cmd); };
+
+	this.isEmpty = function() { return this.stack.length == 0; };
+}
+
+function SvgCanvas(c)
+{
+// private members
+
+	// **************************************************************************************
+	// FIXME: what's the right way to make this 'class' private to the SelectorManager? 
+	function Selector(id, elem) {
+		// this is the selector's unique number
+		this.id = id;
+
+		// this holds a reference to the element for which this selector is being used
+		this.selectedElement = elem;
+
+		// this is a flag used internally to track whether the selector is being used or not
+		this.locked = true;
+
+		// this function is used to reset the id and element that the selector is attached to
+		this.reset = function(e) {
+			this.locked = true;
+			this.selectedElement = e;
+			this.resize();
+			selectorManager.update();
+			this.selectorGroup.setAttribute("display", "inline");
+		};
+
+		// this holds a reference to the <g> element that holds all visual elements of the selector
+		this.selectorGroup = addSvgElementFromJson({ "element": "g",
+													"attr": {"id": ("selectorGroup"+this.id)}
+													});
+
+		// this holds a reference to <rect> element
+		this.selectorRect = this.selectorGroup.appendChild( addSvgElementFromJson({
+								"element": "rect",
+								"attr": {
+									"id": ("selectedBox"+this.id),
+									"fill": "none",
+									"stroke": "blue",
+									"stroke-width": "1",
+									"stroke-dasharray": "5,5",
+									"width": 1,
+									"height": 1,
+									// need to specify this so that the rect is not selectable
+									"style": "pointer-events:none"
+								}
+							}) );
+
+		// this holds a reference to the grip elements for this selector
+		this.selectorGrips = {	"nw":null,
+								"n":null,
+								"ne":null,
+								"w":null,
+								"e":null,
+								"sw":null,
+								"s":null,
+								"se":null
+								};
+
+		// add the corner grips
+		for (dir in this.selectorGrips) {
+			this.selectorGrips[dir] = this.selectorGroup.appendChild( 
+				addSvgElementFromJson({
+					"element": "rect",
+					"attr": {
+						"id": ("selectorGrip_" + dir + "_" + this.id),
+						"fill": "blue",
+						"width": 6,
+						"height": 6,
+						"style": ("cursor:" + dir + "-resize"),
+						// This expands the mouse-able area of the grips making them
+						// easier to grab with the mouse.
+						// This works in Opera and WebKit, but does not work in Firefox
+						// see https://bugzilla.mozilla.org/show_bug.cgi?id=500174
+						"stroke-width": 2,
+						"pointer-events":"all",
+						"display":"none"
+					}
+				}) );
+			$('#'+this.selectorGrips[dir].id).mousedown( function() {
+				current_mode = "resize";
+				current_resize_mode = this.id.substr(13,this.id.indexOf("_",13)-13);
+			});
+		}
+
+		this.showGrips = function(show) {
+			// TODO: use suspendRedraw() here
+			for (dir in this.selectorGrips) {
+				this.selectorGrips[dir].setAttribute("display", show ? "inline" : "none");
+			}
+		};
+
+		this.resize = function(cur_bbox) {
+			var selectedBox = this.selectorRect;
+			var selectedGrips = this.selectorGrips;
+			var selected = this.selectedElement;
+			var sw = parseInt(selected.getAttribute("stroke-width"));
+			var offset = 1;
+			if (!isNaN(sw)) {
+				offset += sw/2;
+			}
+			if (selected.tagName == "text") {
+				offset += 2;
+			}
+			var bbox = cur_bbox || canvas.getBBox(this.selectedElement);
+			var l=bbox.x-offset, t=bbox.y-offset, w=bbox.width+(offset<<1), h=bbox.height+(offset<<1);
+			// TODO: use suspendRedraw() here
+			selectedBox.setAttribute("x", l);
+			selectedBox.setAttribute("y", t);
+			selectedBox.setAttribute("width", w);
+			selectedBox.setAttribute("height", h);
+			selectedGrips.nw.setAttribute("x", l-3);
+			selectedGrips.nw.setAttribute("y", t-3);
+			selectedGrips.ne.setAttribute("x", l+w-3);
+			selectedGrips.ne.setAttribute("y", t-3);
+			selectedGrips.sw.setAttribute("x", l-3);
+			selectedGrips.sw.setAttribute("y", t+h-3);
+			selectedGrips.se.setAttribute("x", l+w-3);
+			selectedGrips.se.setAttribute("y", t+h-3);
+			selectedGrips.n.setAttribute("x", l+w/2-3);
+			selectedGrips.n.setAttribute("y", t-3);
+			selectedGrips.w.setAttribute("x", l-3);
+			selectedGrips.w.setAttribute("y", t+h/2-3);
+			selectedGrips.e.setAttribute("x", l+w-3);
+			selectedGrips.e.setAttribute("y", t+h/2-3);
+			selectedGrips.s.setAttribute("x", l+w/2-3);
+			selectedGrips.s.setAttribute("y", t+h-3);
+			
+			// empty out the transform attribute
+			this.selectorGroup.setAttribute("transform", "");
+			this.selectorGroup.removeAttribute("transform");
+			
+			// align selector group with element coordinate axes
+			var transform = this.selectedElement.getAttribute("transform");
+			if (transform && transform != "") {
+//				this.selectorGroup.setAttribute("transform", transform);
+				var rotind = transform.indexOf("rotate(");
+				if (rotind != -1) {
+					var rotstr = transform.substr(rotind, transform.indexOf(')',rotind)+1);
+					this.selectorGroup.setAttribute("transform", rotstr);
+				}
+			}
+		};
+
+		// now initialize the selector
+		this.reset(elem);
+	};
+
+	function SelectorManager() {
+
+		// this will hold the <g> element that contains all selector rects/grips
+		this.selectorParentGroup = null;
+
+		// this is a special rect that is used for multi-select
+		this.rubberBandBox = null;
+
+		// this will hold objects of type Selector (see above)
+		this.selectors = [];
+
+		// this holds a map of SVG elements to their Selector object
+		this.selectorMap = {};
+
+		// local reference to this object
+		var mgr = this;
+		// private function
+		var initGroup = function() {
+			mgr.selectorParentGroup = addSvgElementFromJson({
+											"element": "g",
+											"attr": {"id": "selectorParentGroup"}
+										});
+		};
+
+		this.requestSelector = function(elem) {
+			if (elem == null) return null;
+			var N = this.selectors.length;
+
+			// if we've already acquired one for this element, return it
+			if (typeof(this.selectorMap[elem.id]) == "object") {
+				this.selectorMap[elem.id].locked = true;
+				return this.selectorMap[elem.id];
+			}
+
+			for (var i = 0; i < N; ++i) {
+				if (this.selectors[i] && !this.selectors[i].locked) {
+					this.selectors[i].locked = true;
+					this.selectors[i].reset(elem);
+					this.selectorMap[elem.id] = this.selectors[i];
+					return this.selectors[i];
+				}
+			}
+			// if we reached here, no available selectors were found, we create one
+			this.selectors[N] = new Selector(N, elem);
+			this.selectorParentGroup.appendChild(this.selectors[N].selectorGroup);
+			this.selectorMap[elem.id] = this.selectors[N];
+			return this.selectors[N];
+		};
+		this.releaseSelector = function(elem) {
+			if (elem == null) return;
+			var N = this.selectors.length;
+			var sel = this.selectorMap[elem.id];
+			for (var i = 0; i < N; ++i) {
+				if (this.selectors[i] && this.selectors[i] == sel) {
+					if (sel.locked == false) {
+						console.log("WARNING! selector was released but was already unlocked");
+					}
+					delete this.selectorMap[elem.id];
+					sel.locked = false;
+					sel.selectedElement = null;
+					sel.showGrips(false);
+
+					// remove from DOM and store reference in JS but only if it exists in the DOM
+					try {
+						sel.selectorGroup.setAttribute("display", "none");
+					} catch(e) { }
+
+					break;
+				}
+			}
+		};
+
+		// this keeps the selector groups as the last child in the document
+		this.update = function() {
+			this.selectorParentGroup = svgroot.appendChild(this.selectorParentGroup);
+		};
+
+		this.getRubberBandBox = function() {
+			if (this.rubberBandBox == null) {
+				this.rubberBandBox = this.selectorParentGroup.appendChild(
+						addSvgElementFromJson({ "element": "rect",
+							"attr": {
+								"id": "selectorRubberBand",
+								"fill": "blue",
+								"fill-opacity": 0.15,
+								"stroke": "blue",
+								"stroke-width": 0.5,
+								"display": "none",
+								"style": "pointer-events:none"
+							}
+						}));
+			}
+			return this.rubberBandBox;
+		};
+
+		initGroup();
+	}
+	// **************************************************************************************
+
+	var addSvgElementFromJson = function(data) {
+		return canvas.updateElementFromJson(data)
+	};
+
+	var assignAttributes = function(node, attrs) {
+		var handle = svgroot.suspendRedraw(60);
+		for (i in attrs) {
+			node.setAttributeNS(null, i, attrs[i]);
+		}
+		svgroot.unsuspendRedraw(handle);
+	};
+
+	// remove unneeded attributes
+	// makes resulting SVG smaller
+	var cleanupElement = function(element) {
+		var handle = svgroot.suspendRedraw(60);
+		if (element.getAttribute('fill-opacity') == '1')
+			element.removeAttribute('fill-opacity');
+		if (element.getAttribute('opacity') == '1')
+			element.removeAttribute('opacity');
+		if (element.getAttribute('stroke') == 'none')
+			element.removeAttribute('stroke');
+		if (element.getAttribute('stroke-dasharray') == 'none')
+			element.removeAttribute('stroke-dasharray');
+		if (element.getAttribute('stroke-opacity') == '1')
+			element.removeAttribute('stroke-opacity');
+		if (element.getAttribute('stroke-width') == '1')
+			element.removeAttribute('stroke-width');
+		if (element.getAttribute('rx') == '0')
+			element.removeAttribute('rx')
+		if (element.getAttribute('ry') == '0')
+			element.removeAttribute('ry')
+		svgroot.unsuspendRedraw(handle);
+	};
+
+	this.updateElementFromJson = function(data) {
+		var shape = svgdoc.getElementById(data.attr.id);
+		// if shape is a path but we need to create a rect/ellipse, then remove the path
+		if (shape && data.element != shape.tagName) {
+			svgroot.removeChild(shape);
+			shape = null;
+		}
+		if (!shape) {
+			shape = svgdoc.createElementNS(svgns, data.element);
+			svgroot.appendChild(shape);
+		}
+		assignAttributes(shape, data.attr);
+		cleanupElement(shape);
+		return shape;
+	};
+
+	var canvas = this;
+	var container = c;
+	var svgns = "http://www.w3.org/2000/svg";
+
+	var idprefix = "svg_";
+	var svgdoc  = c.ownerDocument;
+	var svgroot = svgdoc.createElementNS(svgns, "svg");
+	svgroot.setAttribute("width", 640);
+	svgroot.setAttribute("height", 480);
+	svgroot.setAttribute("id", "svgroot");
+	svgroot.setAttribute("xmlns", svgns);
+	container.appendChild(svgroot);
+
+	var d_attr = null;
+	var started = false;
+	var obj_num = 1;
+	var start_x = null;
+	var start_y = null;
+	var current_mode = "select";
+	var current_resize_mode = "none";
+	var current_fill = "#FF0000";
+	var current_stroke = "#000000";
+	var current_stroke_paint = null;
+	var current_fill_paint = null;
+	var current_stroke_width = 5;
+	var current_stroke_style = "none";
+	var current_opacity = 1;
+	var current_stroke_opacity = 1;
+	var current_fill_opacity = 1;
+	var current_text_fill = "#000000";
+	var current_text_stroke_width = 0;
+	var current_font_size = "12pt";
+	var current_font_family = "serif";
+	var freehand_min_x = null;
+	var freehand_max_x = null;
+	var freehand_min_y = null;
+	var freehand_max_y = null;
+	var current_poly = null;
+	var current_poly_pts = [];
+	var current_poly_pt_drag = -1;
+	// this will hold all the currently selected elements
+	// default size of 1 until it needs to grow bigger
+	var selectedElements = new Array(1); 
+	// this holds the selected's bbox
+	var selectedBBoxes = new Array(1);
+	// this object manages selectors for us
+	var selectorManager = new SelectorManager();
+	var rubberBox = null;
+	var events = {};
+	var undoStackPointer = 0;
+	var undoStack = [];
+
+	// This method sends back an array or a NodeList full of elements that
+	// intersect the multi-select rubber-band-box.
+	// 
+	// Since the only browser that supports the SVG DOM getIntersectionList is Opera, 
+	// we need to provide an implementation here.  We brute-force it for now.
+	// 
+	// Reference:
+	// Firefox does not implement getIntersectionList(), see https://bugzilla.mozilla.org/show_bug.cgi?id=501421
+	// Webkit does not implement getIntersectionList(), see https://bugs.webkit.org/show_bug.cgi?id=11274
+	var getIntersectionList = function(rect) {
+		if (rubberBox == null) { return null; }
+
+		var resultList = null;
+		try {
+			resultList = svgroot.getIntersectionList(rect, null);
+		} catch(e) { }
+
+		if (resultList == null || typeof(resultList.item) != "function") 
+		{
+			resultList = [];
+
+			var rubberBBox = rubberBox.getBBox();
+			var nodes = svgroot.childNodes;
+			var i = svgroot.childNodes.length;
+			while (i--) {
+				// need to do this since the defs has no bbox and causes an exception
+				// to be thrown in Mozilla
+				try {
+					if (nodes[i].id != "selectorParentGroup" &&
+						Utils.rectsIntersect(rubberBBox, canvas.getBBox(nodes[i]))) 
+					{
+						resultList.push(nodes[i]);
+					}
+				} catch(e) {
+					// do nothing, this element did not have a bbox
+				}
+			}
+		}
+		// addToSelection expects an array, but it's ok to pass a NodeList 
+		// because using square-bracket notation is allowed: 
+		// http://www.w3.org/TR/DOM-Level-2-Core/ecma-script-binding.html
+		return resultList;
+	};
+
+	// FIXME: we MUST compress consecutive text changes to the same element
+	// (right now each keystroke is saved as a separate command that includes the
+	// entire text contents of the text element)
+	// TODO: consider limiting the history that we store here (need to do some slicing)
+	var addCommandToHistory = function(cmd) {
+		// if our stack pointer is not at the end, then we have to remove
+		// all commands after the pointer and insert the new command
+		if (undoStackPointer < undoStack.length && undoStack.length > 0) {
+			undoStack = undoStack.splice(0, undoStackPointer);
+		}
+		undoStack.push(cmd);
+		undoStackPointer = undoStack.length;
+	};
+
+// private functions
+	var getId = function() {
+		if (events["getid"]) return call("getid", obj_num);
+		return idprefix + obj_num;
+	};
+
+	var getNextId = function() {
+		// ensure the ID does not exist
+		var id = getId();
+		while (svgdoc.getElementById(id)) {
+			obj_num++;
+			id = getId();
+		}
+		return id;
+	};
+
+	var call = function(event, arg) {
+		if (events[event]) {
+			return events[event](this,arg);
+		}
+	};
+
+	// this function sanitizes the input node and its children
+	// this function only keeps what is allowed from our whitelist defined above
+	var sanitizeSvg = function(node) {
+		// we only care about element nodes
+		// automatically return for all comment, etc nodes
+		// for text, we do a whitespace trim
+		if (node.nodeType == 3) {
+			node.nodeValue = node.nodeValue.replace(/^\s+|\s+$/g, "");
+		}
+		if (node.nodeType != 1) return;
+
+		var doc = node.ownerDocument;
+		var parent = node.parentNode;
+		// can parent ever be null here?  I think the root node's parent is the document...
+		if (!doc || !parent) return;
+
+		var allowedAttrs = svgWhiteList[node.nodeName];
+		// if this element is allowed
+		if (allowedAttrs != undefined) {
+			var i = node.attributes.length;
+			while (i--) {
+				// if the attribute is not in our whitelist, then remove it
+				// could use jQuery's inArray(), but I don't know if that's any better
+				var attrName = node.attributes.item(i).nodeName;
+				if (allowedAttrs.indexOf(attrName) == -1) {
+					// TODO: do I need to call setAttribute(..., "") here for Fx2?
+					node.removeAttribute(attrName);
+				}
+			}
+
+			// recurse to children
+			i = node.childNodes.length;
+			while (i--) { sanitizeSvg(node.childNodes.item(i)); }
+		}
+		// else, remove this element
+		else {
+			// remove all children from this node and insert them before this node
+			var children = [];
+			while (node.hasChildNodes()) {
+				children.push(parent.insertBefore(node.firstChild, node));
+			}
+
+			// remove this node from the document altogether
+			parent.removeChild(node);
+
+			// call sanitizeSvg on each of those children
+			var i = children.length;
+			while (i--) { sanitizeSvg(children[i]); }
+
+		}
+	};
+
+	var removeUnusedGrads = function() {
+		var defs = svgroot.getElementsByTagNameNS(svgns, "defs");
+		if(!defs.length) return;
+		
+		var all_els = svgroot.getElementsByTagNameNS(svgns, '*');
+		var grad_uses = [];
+		
+		$.each(all_els, function(i, el) {
+			var fill = el.getAttribute('fill');
+			if(fill && fill.indexOf('url(#') == 0) {
+				//found gradient
+				grad_uses.push(fill);
+			} 
+			
+			var stroke = el.getAttribute('stroke');
+			if(stroke && stroke.indexOf('url(#') == 0) {
+				//found gradient
+				grad_uses.push(stroke);
+			} 
+		});
+		
+		var lgrads = svgroot.getElementsByTagNameNS(svgns, "linearGradient");
+		var grad_ids = [];
+
+		var i = lgrads.length;
+		while (i--) {
+			var grad = lgrads[i];
+			var id = grad.getAttribute('id');
+			var url_id = 'url(#' + id + ')';
+			if($.inArray(url_id, grad_uses) == -1) {
+				// Not found, so remove
+				grad.parentNode.removeChild(grad);
+			}
+		}
+		
+		// Remove defs if empty
+		var i = defs.length;
+		while (i--) {
+			var def = defs[i];
+			if(!def.getElementsByTagNameNS(svgns,'*').length) {
+				def.parentNode.removeChild(def);
+			}
+		}
+	}
+
+	var svgToString = function(elem, indent) {
+		var out = new Array();
+		if (elem) {
+			var attrs = elem.attributes;
+			var attr;
+			var i;
+			var childs = elem.childNodes;
+			for (i=0; i<indent; i++) out.push(" ");
+			out.push("<"); out.push(elem.nodeName);
+			for (i=attrs.length-1; i>=0; i--) {
+				attr = attrs.item(i);
+				if (attr.nodeValue != "") {
+					out.push(" "); out.push(attr.nodeName); out.push("=\""); 
+					out.push(attr.nodeValue); out.push("\"");
+				}
+			}
+			if (elem.hasChildNodes()) {
+				out.push(">");
+				indent++;
+				var bOneLine = false;
+				for (i=0; i<childs.length; i++)
+				{
+					var child = childs.item(i);
+					if (child.id == "selectorParentGroup") continue;
+					switch(child.nodeType) {
+					case 1: // element node
+						out.push("\n");
+						out.push(svgToString(childs.item(i), indent));
+						break;
+					case 3: // text node
+						var str = child.nodeValue.replace(/^\s+|\s+$/g, "");
+						if (str != "") {
+							bOneLine = true;
+							out.push(str + "");
+						}
+						break;
+					case 8: // comment
+						out.push("\n");
+						out.push(new Array(indent+1).join(" "));
+						out.push("<!--");
+						out.push(child.data);
+						out.push("-->");
+						break;
+					} // switch on node type
+				}
+				indent--;
+				if (!bOneLine) {
+					out.push("\n");
+					for (i=0; i<indent; i++) out.push(" ");
+				}
+				out.push("</"); out.push(elem.nodeName); out.push(">");
+			} else {
+				out.push("/>");
+			}
+		}
+		return out.join('');
+	}; // end svgToString()
+
+	var recalculateAllSelectedDimensions = function() {
+		var text = (current_resize_mode == "none" ? "position" : "size");
+		var batchCmd = new BatchCommand(text);
+
+		var i = selectedElements.length;
+		while(i--) {
+			var cmd = recalculateSelectedDimensions(i);
+			if (cmd) {
+				batchCmd.addSubCommand(cmd);
+			}
+		}
+
+		if (!batchCmd.isEmpty()) {
+			addCommandToHistory(batchCmd);
+			call("changed", selectedElements);
+		}
+	};
+
+	// this is how we map paths to our preferred relative segment types
+	var pathMap = [ 0, 'z', 'm', 'm', 'l', 'l', 'c', 'c', 'q', 'q', 'a', 'a', 
+					'l', 'l', 'l', 'l', // TODO: be less lazy below and map them to h and v
+					's', 's', 't', 't' ];
+
+	// this function returns the command which resulted from the selected change
+	var recalculateSelectedDimensions = function(i) {
+		var selected = selectedElements[i];
+		if (selected == null) return null;
+		var selectedBBox = selectedBBoxes[i];
+		var box = canvas.getBBox(selected);
+
+		// if we have not moved/resized, then immediately leave
+		if (box.x == selectedBBox.x && box.y == selectedBBox.y &&
+			box.width == selectedBBox.width && box.height == selectedBBox.height) {
+			return null;
+		}
+
+		// after this point, we have some change to this element
+
+		var remapx = function(x) {return parseInt(((x-box.x)/box.width)*selectedBBox.width + selectedBBox.x);}
+		var remapy = function(y) {return parseInt(((y-box.y)/box.height)*selectedBBox.height + selectedBBox.y);}
+		var scalew = function(w) {return parseInt(w*selectedBBox.width/box.width);}
+		var scaleh = function(h) {return parseInt(h*selectedBBox.height/box.height);}
+
+		var changes = {};
+
+		// if there was a rotation transform, re-set it, otherwise empty out the transform attribute
+		// This fixes Firefox 2- behavior - which does not reset values when the attribute has
+		// been removed, see https://bugzilla.mozilla.org/show_bug.cgi?id=320622
+		var angle = canvas.getRotationAngle(selected);
+		var pointGripContainer = document.getElementById("polypointgrip_container");
+		if (angle) {
+			var cx = remapx(box.x + box.width/2),
+				cy = remapy(box.y + box.height/2);
+			var rotate = ["rotate(", angle, " ", cx, ",", cy, ")"].join('');
+			selected.setAttribute("transform", rotate);
+			if(pointGripContainer) {
+				pointGripContainer.setAttribute("transform", rotate);
+			}
+		}
+		else {
+			selected.setAttribute("transform", "");
+			selected.removeAttribute("transform");
+			if(pointGripContainer) {
+				pointGripContainer.setAttribute("transform", "");
+				pointGripContainer.removeAttribute("transform");
+			}
+		}
+
+		switch (selected.tagName)
+		{
+		// NOTE: at the moment, there's no way to create an actual polygon element except by 
+		// editing source or importing from somewhere else but we'll cover it here anyway
+		// polygon is handled just like polyline
+		case "polygon": 
+		case "polyline":
+			// extract the points from the polygon/polyline, adjust it and write back the new points
+			// but first, save the old points
+			changes["points"] = selected.getAttribute("points");
+			var list = selected.points;
+			var len = list.numberOfItems;
+			var newpoints = "";
+			for (var i = 0; i < len; ++i) {
+				var pt = list.getItem(i);
+				var x = remapx(pt.x), y = remapy(pt.y);
+				newpoints += x + "," + y + " ";
+			}
+			selected.setAttributeNS(null, "points", newpoints);
+			break;
+		case "path":
+			// extract the x,y from the path, adjust it and write back the new path
+			// but first, save the old path
+			changes["d"] = selected.getAttribute("d");
+			var M = selected.pathSegList.getItem(0);
+			var curx = M.x, cury = M.y;
+			var newd = "M" + remapx(curx) + "," + remapy(cury);
+			var segList = selected.pathSegList;
+			var len = segList.numberOfItems;
+			// for all path segments in the path, we first turn them into relative path segments,
+			// then we remap the coordinates from the resize
+			for (var i = 1; i < len; ++i) {
+				var seg = segList.getItem(i);
+				// if these properties are not in the segment, set them to zero
+				var x = seg.x || 0,
+					y = seg.y || 0,
+					x1 = seg.x1 || 0,
+					y1 = seg.y1 || 0,
+					x2 = seg.x2 || 0,
+					y2 = seg.y2 || 0;
+
+				var type = seg.pathSegType;
+				switch (type) {
+					case 1: // z,Z closepath (Z/z)
+						newd += "z";
+						continue;
+					// turn this into a relative segment then fall through
+					case 2: // absolute move (M)
+					case 4: // absolute line (L)
+					case 12: // absolute horizontal line (H)
+					case 14: // absolute vertical line (V)
+					case 18: // absolute smooth quad (T)
+						x -= curx;
+						y -= cury;
+					case 3: // relative move (m)
+					case 5: // relative line (l)
+					case 13: // relative horizontal line (h)
+					case 15: // relative vertical line (v)
+					case 19: // relative smooth quad (t)
+						curx += x;
+						cury += y;
+						newd += [" ", pathMap[type], scalew(x), ",", scaleh(y)].join('');
+						break;
+					case 6: // absolute cubic (C)
+						x -= curx; x1 -= curx; x2 -= curx;
+						y -= cury; y1 -= cury; y2 -= cury;
+					case 7: // relative cubic (c)
+						curx += x;
+						cury += y;
+						newd += [" c", scalew(x1), ",", scaleh(y1), " ", scalew(x2), ",", scaleh(y2),
+									" ", scalew(x), ",", scaleh(y)].join('');
+						break;
+					case 8: // absolute quad (Q)
+						x -= curx; x1 -= curx;
+						y -= cury; y1 -= cury;
+					case 9: // relative quad (q) 
+						curx += x;
+						cury += y;
+						newd += [" q", scalew(x1), ",", scaleh(y1), " ", scalew(x), ",", scaleh(y)].join('');
+						break;
+					case 10: // absolute elliptical arc (A)
+						x -= curx;
+						y -= cury;
+					case 11: // relative elliptical arc (a)
+						curx += x;
+						cury += y;
+						newd += [ "a", scalew(seg.r1), ",", scaleh(seg.r2), " ", seg.angle, " ", 
+									(seg.largeArcFlag ? 1 : 0), " ", (seg.sweepFlag ? 1 : 0), " ", 
+									scalew(x), ",", scaleh(y) ].join('')
+						break;
+					case 16: // absolute smooth cubic (S)
+						x -= curx; x2 -= curx;
+						y -= cury; y2 -= cury;
+					case 17: // relative smooth cubic (s)
+						curx += x;
+						cury += y;
+						newd += [" s", scalew(x2), ",", scaleh(y2), " ", scalew(x), ",", scaleh(y)].join('');
+						break;
+				} // switch on path segment type
+			} // for each segment
+			selected.setAttributeNS(null, "d", newd);
+			break;
+		case "line":
+			changes["x1"] = selected.getAttribute("x1");
+			changes["y1"] = selected.getAttribute("y1");
+			changes["x2"] = selected.getAttribute("x2");
+			changes["y2"] = selected.getAttribute("y2");
+			var handle = svgroot.suspendRedraw(1000);
+			selected.setAttribute("x1", remapx(changes["x1"]));
+			selected.setAttribute("y1", remapy(changes["y1"]));
+			selected.setAttribute("x2", remapx(changes["x2"]));
+			selected.setAttribute("y2", remapy(changes["y2"]));
+			svgroot.unsuspendRedraw(handle);
+			break;
+		case "circle":
+			changes["cx"] = selected.getAttribute("cx");
+			changes["cy"] = selected.getAttribute("cy");
+			changes["r"] = selected.getAttribute("r");
+			var handle = svgroot.suspendRedraw(1000);
+			selected.setAttribute("cx", remapx(changes["cx"]));
+			selected.setAttribute("cy", remapy(changes["cy"]));
+			// take the minimum of the new selected box's dimensions for the new circle radius
+			selected.setAttribute("r", Math.min(selectedBBox.width/2,selectedBBox.height/2));
+			svgroot.unsuspendRedraw(handle);
+			break;
+		case "ellipse":
+			changes["cx"] = selected.getAttribute("cx");
+			changes["cy"] = selected.getAttribute("cy");
+			changes["rx"] = selected.getAttribute("rx");
+			changes["ry"] = selected.getAttribute("ry");
+			var handle = svgroot.suspendRedraw(1000);
+			selected.setAttribute("cx", remapx(changes["cx"]));
+			selected.setAttribute("cy", remapy(changes["cy"]));
+			selected.setAttribute("rx", scalew(changes["rx"]));
+			selected.setAttribute("ry", scaleh(changes["ry"]));
+			svgroot.unsuspendRedraw(handle);
+			break;
+		case "text":
+			changes["x"] = selected.getAttribute("x");
+			changes["y"] = selected.getAttribute("y");
+			var handle = svgroot.suspendRedraw(1000);
+			selected.setAttribute("x", remapx(changes["x"]));
+			selected.setAttribute("y", remapy(changes["y"]));
+			svgroot.unsuspendRedraw(handle);
+			break;
+		case "rect":
+			changes["x"] = selected.getAttribute("x");
+			changes["y"] = selected.getAttribute("y");
+			changes["width"] = selected.getAttribute("width");
+			changes["height"] = selected.getAttribute("height");
+			var handle = svgroot.suspendRedraw(1000);
+			selected.setAttribute("x", remapx(changes["x"]));
+			selected.setAttribute("y", remapy(changes["y"]));
+			selected.setAttribute("width", scalew(changes["width"]));
+			selected.setAttribute("height", scaleh(changes["height"]));
+			svgroot.unsuspendRedraw(handle);
+			break;
+		default: // rect
+			console.log("Unknown shape type: " + selected.tagName);
+			break;
+		}
+		if (changes) {
+			return new ChangeElementCommand(selected, changes);
+		}
+	};
+
+// public events
+
+	this.clearSelection = function() {
+		if (selectedElements[0] == null) { return; }
+		var len = selectedElements.length;
+		for (var i = 0; i < len; ++i) {
+			var elem = selectedElements[i];
+			if (elem == null) break;
+			selectorManager.releaseSelector(elem);
+			selectedElements[i] = null;
+			selectedBBoxes[i] = null;
+		}
+		call("selected", selectedElements);
+	};
+
+	this.addToSelection = function(elemsToAdd, showGrips) {
+		if (elemsToAdd.length == 0) { return; }
+
+		// find the first null in our selectedElements array
+		var j = 0;
+		while (j < selectedElements.length) {
+			if (selectedElements[j] == null) { 
+				break;
+			}
+			++j;
+		}
+
+		// now add each element consecutively
+		var i = elemsToAdd.length;
+		while (i--) {
+			var elem = elemsToAdd[i];
+			// we ignore any selectors
+			if (elem.id.substr(0,13) == "selectorGrip_") continue;
+			// if it's not already there, add it
+			if (selectedElements.indexOf(elem) == -1) {
+				selectedElements[j] = elem;
+				selectedBBoxes[j++] = this.getBBox(elem);
+				selectorManager.requestSelector(elem);
+				call("selected", selectedElements);
+			}
+		}
+		
+		if(showGrips) {
+			selectorManager.requestSelector(selectedElements[0]).showGrips(elem.tagName != "text");
+		}
+	};
+
+	// 
+	this.removeFromSelection = function(elemsToRemove) {
+		if (selectedElements[0] == null) { return; }
+		if (elemsToRemove.length == 0) { return; }
+
+		// find every element and remove it from our array copy
+		var newSelectedItems = new Array(selectedElements.length);
+		var j = 0;
+		var len = selectedElements.length;
+		for (var i = 0; i < len; ++i) {
+			var elem = selectedElements[i];
+			if (elem) {
+				// keep the item
+				if (elemsToRemove.indexOf(elem) == -1) {
+					newSelectedItems[j++] = elem;
+				}
+				else { // remove the item and its selector
+					selectorManager.releaseSelector(elem);
+				}
+			}
+		}
+		// the copy becomes the master now
+		selectedElements = newSelectedItems;
+	};
+
+	// in mouseDown :
+	// - when we are in a create mode, the element is added to the canvas
+	//   but the action is not recorded until mousing up
+	// - when we are in select mode, select the element, remember the position
+	//   and do nothing else
+	var mouseDown = function(evt)
+	{
+		var x = evt.pageX - container.parentNode.offsetLeft + container.parentNode.scrollLeft;
+		var y = evt.pageY - container.parentNode.offsetTop + container.parentNode.scrollTop;
+		
+		if($.inArray(current_mode, ['select', 'resize']) == -1) {
+			addGradient();
+		}
+		
+		switch (current_mode) {
+			case "select":
+				started = true;
+				start_x = x;
+				start_y = y;
+				current_resize_mode = "none";
+				var t = evt.target;
+				// WebKit returns <div> when the canvas is clicked, Firefox/Opera return <svg>
+				var nodeName = t.nodeName.toLowerCase();
+				if (nodeName != "div" && nodeName != "svg") {
+					// if this element is not yet selected, clear selection and select it
+					if (selectedElements.indexOf(t) == -1) {
+						canvas.clearSelection();
+						canvas.addToSelection([t]);
+						current_poly = null;
+					}
+					// else if it's a poly, go into polyedit mode in mouseup
+				}
+				else {
+					canvas.clearSelection();
+					current_mode = "multiselect";
+					if (rubberBox == null) {
+						rubberBox = selectorManager.getRubberBandBox();
+					}
+					rubberBox.setAttribute("x", start_x);
+					rubberBox.setAttribute("y", start_y);
+					rubberBox.setAttribute("width", 0);
+					rubberBox.setAttribute("height", 0);
+					rubberBox.setAttribute("display", "inline");
+				}
+				break;
+			case "resize":
+				started = true;
+				start_x = x;
+				start_y = y;
+				break;
+			case "fhellipse":
+			case "fhrect":
+			case "path":
+				started = true;
+				start_x = x;
+				start_y = y;
+				d_attr = x + "," + y + " ";
+				addSvgElementFromJson({
+					"element": "polyline",
+					"attr": {
+						"points": d_attr,
+						"id": getNextId(),
+						"fill": "none",
+						"stroke": current_stroke,
+						"stroke-width": current_stroke_width,
+						"stroke-dasharray": current_stroke_style,
+						"stroke-opacity": current_stroke_opacity,
+						"stroke-linecap": "round",
+						"stroke-linejoin": "round",
+						"opacity": current_opacity / 2
+					}
+				});
+				freehand_min_x = x;
+				freehand_max_x = x;
+				freehand_min_y = y;
+				freehand_max_y = y;
+				break;
+			case "square":
+				// FIXME: once we create the rect, we lose information that this was a square
+				// (for resizing purposes this could be important)
+			case "rect":
+				started = true;
+				start_x = x;
+				start_y = y;
+				addSvgElementFromJson({
+					"element": "rect",
+					"attr": {
+						"x": x,
+						"y": y,
+						"width": 0,
+						"height": 0,
+						"id": getNextId(),
+						"fill": current_fill,
+						"stroke": current_stroke,
+						"stroke-width": current_stroke_width,
+						"stroke-dasharray": current_stroke_style,
+						"stroke-opacity": current_stroke_opacity,
+						"fill-opacity": current_fill_opacity,
+						"opacity": current_opacity / 2
+					}
+				});
+				break;
+			case "line":
+				started = true;
+				addSvgElementFromJson({
+					"element": "line",
+					"attr": {
+						"x1": x,
+						"y1": y,
+						"x2": x,
+						"y2": y,
+						"id": getNextId(),
+						"stroke": current_stroke,
+						"stroke-width": current_stroke_width,
+						"stroke-dasharray": current_stroke_style,
+						"stroke-opacity": current_stroke_opacity,
+						"fill": "none",
+						"opacity": current_opacity / 2
+					}
+				});
+				break;
+			case "circle":
+				started = true;
+				addSvgElementFromJson({
+					"element": "circle",
+					"attr": {
+						"cx": x,
+						"cy": y,
+						"r": 0,
+						"id": getNextId(),
+						"fill": current_fill,
+						"stroke": current_stroke,
+						"stroke-width": current_stroke_width,
+						"stroke-dasharray": current_stroke_style,
+						"stroke-opacity": current_stroke_opacity,
+						"fill-opacity": current_fill_opacity,
+						"opacity": current_opacity / 2
+					}
+				});
+				break;
+			case "ellipse":
+				started = true;
+				addSvgElementFromJson({
+					"element": "ellipse",
+					"attr": {
+						"cx": x,
+						"cy": y,
+						"rx": 0,
+						"ry": 0,
+						"id": getNextId(),
+						"fill": current_fill,
+						"stroke": current_stroke,
+						"stroke-width": current_stroke_width,
+						"stroke-dasharray": current_stroke_style,
+						"stroke-opacity": current_stroke_opacity,
+						"fill-opacity": current_fill_opacity,
+						"opacity": current_opacity / 2
+					}
+				});
+				break;
+			case "text":
+				started = true;
+				var newText = addSvgElementFromJson({
+					"element": "text",
+					"attr": {
+						"x": x,
+						"y": y,
+						"id": getNextId(),
+						"fill": current_text_fill,
+						"stroke": current_stroke,
+						"stroke-width": current_text_stroke_width,
+						"stroke-dasharray": current_stroke_style,
+						"stroke-opacity": current_stroke_opacity,
+						"fill-opacity": current_fill_opacity,
+						// fix for bug where text elements were always 50% opacity
+						"opacity": current_opacity,
+						"font-size": current_font_size,
+						"font-family": current_font_family
+					}
+				});
+				newText.textContent = "text";
+				break;
+			case "poly":
+				started = true;
+				break;
+			case "polyedit":
+				started = true;
+				var id = evt.target.id;
+				if (id.substr(0,14) == "polypointgrip_") {
+					current_poly_pt_drag = parseInt(id.substr(14));
+				}
+				break;
+			default:
+				console.log("Unknown mode in mousedown: " + current_mode);
+				break;
+		}
+	};
+
+	// in this function we do not record any state changes yet (but we do update
+	// any elements that are still being created, moved or resized on the canvas)
+	// TODO: svgcanvas should just retain a reference to the image being dragged instead
+	// of the getId() and getElementById() funkiness - this will help us customize the ids 
+	// a little bit for squares and polys
+	var mouseMove = function(evt)
+	{
+		if (!started) return;
+		var selected = selectedElements[0];
+		var x = evt.pageX - container.parentNode.offsetLeft + container.parentNode.scrollLeft;
+		var y = evt.pageY - container.parentNode.offsetTop + container.parentNode.scrollTop;
+		var shape = svgdoc.getElementById(getId());
+		switch (current_mode)
+		{
+			case "select":
+				// we temporarily use a translate on the element being dragged
+				// this transform is removed upon mousing up and the element is 
+				// relocated to the new location
+				if (selectedElements[0] != null) {
+					var dx = x - start_x;
+					var dy = y - start_y;
+					
+					if (dx != 0 || dy != 0) {
+						var ts = ["translate(",dx,",",dy,")"].join('');
+						var len = selectedElements.length;
+						for (var i = 0; i < len; ++i) {
+							var selected = selectedElements[i];
+							if (selected == null) break;
+
+							var box = canvas.getBBox(selected);
+							selectedBBoxes[i].x = box.x + dx;
+							selectedBBoxes[i].y = box.y + dy;
+							var angle = canvas.getRotationAngle(selected);
+							if (angle) {
+								var cx = box.x+box.width/2, 
+									cy = box.y+box.height/2;
+								ts += [" rotate(", angle, " ", cx, ",", cy, ")"].join('');
+
+ 								var r = Math.sqrt( dx*dx + dy*dy );
+								var theta = Math.atan2(dy,dx) - angle * Math.PI / 180.0;
+								dx = r * Math.cos(theta);
+								dy = r * Math.sin(theta);
+							}
+							selected.setAttribute("transform", ts);
+							// update our internal bbox that we're tracking while dragging
+							box.x += dx; box.y += dy;
+							selectorManager.requestSelector(selected).resize(box);
+						}
+					}
+				}
+				break;
+			case "multiselect":
+				rubberBox.setAttribute("x", Math.min(start_x,x));
+				rubberBox.setAttribute("y", Math.min(start_y,y));
+				rubberBox.setAttribute("width", Math.abs(x-start_x));
+				rubberBox.setAttribute("height", Math.abs(y-start_y));
+
+				// this code will probably be faster than using getIntersectionList(), but
+				// not as accurate (only grabs an element if the mouse happens to pass over
+				// its bbox and elements would never be released from selection)
+//				var nodeName = evt.target.nodeName.toLowerCase();
+//				if (nodeName != "div" && nodeName != "svg") {
+//					canvas.addToSelection([evt.target]);
+//				}
+
+				// clear out selection and set it to the new list
+				canvas.clearSelection();
+				canvas.addToSelection(getIntersectionList());
+
+				/*
+				// for each selected:
+				// - if newList contains selected, do nothing
+				// - if newList doesn't contain selected, remove it from selected
+				// - for any newList that was not in selectedElements, add it to selected
+				var elemsToRemove = [];
+				var newList = getIntersectionList();
+				var len = selectedElements.length;
+				for (var i = 0; i < len; ++i) {
+					var ind = newList.indexOf(selectedElements[i]);
+					if (ind == -1) {
+						elemsToRemove.push(selectedElements[i]);
+					}
+					else {
+						newList[ind] = null;
+					}
+				}
+				if (elemsToRemove.length > 0) 
+					canvas.removeFromSelection(elemsToRemove);
+				*/
+				break;
+			case "resize":
+				// we track the resize bounding box and translate/scale the selected element
+				// while the mouse is down, when mouse goes up, we use this to recalculate
+				// the shape's coordinates
+				var box=canvas.getBBox(selected), left=box.x, top=box.y, width=box.width,
+					height=box.height, dx=(x-start_x), dy=(y-start_y);
+								
+				// if rotated, adjust the dx,dy values
+				console.log(box);
+				var angle = canvas.getRotationAngle(selected);
+				if (angle) {
+ 					var r = Math.sqrt( dx*dx + dy*dy );
+					var theta = Math.atan2(dy,dx) - angle * Math.PI / 180.0;
+					dx = r * Math.cos(theta);
+					dy = r * Math.sin(theta);
+				}
+				
+				// if not stretching in y direction, set dy to 0
+				// if not stretching in x direction, set dx to 0
+				if(current_resize_mode.indexOf("n")==-1 && current_resize_mode.indexOf("s")==-1) {
+					dy = 0;
+				}
+				if(current_resize_mode.indexOf("e")==-1 && current_resize_mode.indexOf("w")==-1) {
+					dx = 0;
+				}				
+				
+				var ts = null;
+				var tx = 0, ty = 0;
+				var sy = (height+dy)/height, sx = (width+dx)/width;
+				if(current_resize_mode.indexOf("n") != -1) {
+					sy = (height-dy)/height;
+					ty = height;
+				}
+				if(current_resize_mode.indexOf("w") != -1) {
+					sx = (width-dx)/width;
+					tx = width;
+				}
+				
+				var selectedBBox = selectedBBoxes[0];				
+
+				// find the rotation transform and prepend it
+				var ts = [" translate(", (left+tx), ",", (top+ty), ") scale(", sx, ",", sy,
+							") translate(", -(left+tx), ",", -(top+ty), ")"].join('');
+				if (angle) {
+					var cx = left + width/2;//selectedBBox.x + selectedBBox.width/2,
+						cy = top + height/2;//selectedBBox.y + selectedBBox.height/2;
+					ts = ["rotate(", angle, " ", cx, ",", cy, ")", ts].join('')
+				}
+				selected.setAttribute("transform", ts);
+				
+				if (tx) {
+					selectedBBox.x = left+dx;
+				}
+				if (ty) {
+					selectedBBox.y = top+dy;
+				}
+				selectedBBox.width = width*sx;
+				selectedBBox.height = height*sy;
+				// normalize selectedBBox
+				if (selectedBBox.width < 0) {
+					selectedBBox.x += selectedBBox.width;
+					selectedBBox.width *= -1;//-selectedBBox.width;
+				}
+				if (selectedBBox.height < 0) {
+					selectedBBox.y += selectedBBox.height;
+					selectedBBox.height *= -1;//-selectedBBox.height;
+				}
+				selectorManager.requestSelector(selected).resize(selectedBBox);
+				break;
+			case "text":
+				var handle = svgroot.suspendRedraw(1000);
+				shape.setAttribute("x", x);
+				shape.setAttribute("y", y);
+				svgroot.unsuspendRedraw(handle);
+				break;
+			case "line":
+				var handle = svgroot.suspendRedraw(1000);
+				shape.setAttributeNS(null, "x2", x);
+				shape.setAttributeNS(null, "y2", y);
+				svgroot.unsuspendRedraw(handle);
+				break;
+			case "square":
+				var size = Math.max( Math.abs(x - start_x), Math.abs(y - start_y) );
+				var handle = svgroot.suspendRedraw(1000);
+				shape.setAttributeNS(null, "width", size);
+				shape.setAttributeNS(null, "height", size);
+				shape.setAttributeNS(null, "x", start_x < x ? start_x : start_x - size);
+				shape.setAttributeNS(null, "y", start_y < y ? start_y : start_y - size);
+				svgroot.unsuspendRedraw(handle);
+				break;
+			case "rect":
+				var handle = svgroot.suspendRedraw(1000);
+				shape.setAttributeNS(null, "x", Math.min(start_x,x));
+				shape.setAttributeNS(null, "y", Math.min(start_y,y));
+				shape.setAttributeNS(null, "width", Math.abs(x-start_x));
+				shape.setAttributeNS(null, "height", Math.abs(y-start_y));
+				svgroot.unsuspendRedraw(handle);
+				break;
+			case "circle":
+				var cx = shape.getAttributeNS(null, "cx");
+				var cy = shape.getAttributeNS(null, "cy");
+				var rad = Math.sqrt( (x-cx)*(x-cx) + (y-cy)*(y-cy) );
+				shape.setAttributeNS(null, "r", rad);
+				break;
+			case "ellipse":
+				var cx = shape.getAttributeNS(null, "cx");
+				var cy = shape.getAttributeNS(null, "cy");
+				var handle = svgroot.suspendRedraw(1000);
+				shape.setAttributeNS(null, "rx", Math.abs(x - cx) );
+				shape.setAttributeNS(null, "ry", Math.abs(y - cy) );
+				svgroot.unsuspendRedraw(handle);
+				break;
+			case "fhellipse":
+			case "fhrect":
+				freehand_min_x = Math.min(x, freehand_min_x);
+				freehand_max_x = Math.max(x, freehand_max_x);
+				freehand_min_y = Math.min(y, freehand_min_y);
+				freehand_max_y = Math.max(y, freehand_max_y);
+			// break; missing on purpose
+			case "path":
+				start_x = x;
+				start_y = y;
+				d_attr += + x + "," + y + " ";
+				shape.setAttributeNS(null, "points", d_attr);
+				break;
+			// update poly stretch line coordinates
+			case "poly":
+				var line = document.getElementById("poly_stretch_line");
+				if (line) {
+					line.setAttribute("x2", x);
+					line.setAttribute("y2", y);
+				}
+				break;
+			case "polyedit":
+				// if we are dragging a point, let's move it
+				if (current_poly_pt_drag != -1 && current_poly) {
+					var i = current_poly_pt_drag * 2;
+					
+					// if the image is rotated, then we must modify the x,y mouse coordinates
+					// and rotate them into the shape's rotated coordinate system
+					
+					// FIXME: the problem is that the element's rotation is controlled by 
+					// two things: an angle and a rotation point (the center of the element).
+					// If the element's bbox is changed, its center changes.  In this case,
+					// we keep the rotation center where it is (parse it out from the transform
+					// attribute), and move the poly point appropriately.  This looks good while
+					// dragging, but looks funny when you subsequently rotate the element again.
+					var angle = canvas.getRotationAngle(current_poly) * Math.PI / 180.0;
+					if (angle) {
+						// extract the shape's (potentially) old 'center' from the transform attribute
+						var matched_numbers = current_poly.getAttribute('transform').match(/([\d\.\-\+]+)/g);
+						var cx = parseFloat(matched_numbers[1]), 
+							cy = parseFloat(matched_numbers[2]);
+						var dx = x - cx, dy = y - cy;
+ 						var r = Math.sqrt( dx*dx + dy*dy );
+						var theta = Math.atan2(dy,dx) - angle;						
+						x = cx + r * Math.cos(theta);
+						y = cy + r * Math.sin(theta);
+					}
+
+					current_poly_pts[i] = x;
+					current_poly_pts[i+1] = y;
+
+					// reset the path's d attribute using current_poly_pts
+					var oldd = current_poly.getAttribute("d");
+					var closedPath = (oldd[oldd.length-1] == 'z' || oldd[oldd.length-1] == 'Z');
+					var len = current_poly_pts.length/2;
+					var arr = new Array(len+1);
+					var curx = current_poly_pts[0],
+						cury = current_poly_pts[1];
+					arr[0] = ["M", curx, ",", cury].join('');
+					for (var j = 1; j < len; ++j) {
+						var px = current_poly_pts[j*2], py = current_poly_pts[j*2+1];
+						arr[j] = ["l", parseInt(px-curx), ",", parseInt(py-cury)].join('');
+						curx = px;
+						cury = py;
+					}
+					if (closedPath) {
+						arr[len] = "z";
+					}
+					current_poly.setAttribute("d", arr.join(' '));
+
+					// move the point grip
+					var grip = document.getElementById("polypointgrip_" + current_poly_pt_drag);
+					if (grip) {
+						grip.setAttribute("cx", x);
+						grip.setAttribute("cy", y);
+					}
+				}
+				break;
+			default:
+				break;
+		}
+		// TODO: should we fire the change event here?  I'm thinking only fire
+		// this event when the user mouses up.  That's when the action (create,
+		// move, resize, draw) has finished
+		// Only question is whether in Wave Gadget mode whether we want to see the 
+		// person live-dragging the element around (for instance)
+//		call("changed", selected);
+	};
+
+	var removeAllPointGripsFromPoly = function() {
+		// loop through and hide all pointgrips
+		var i = current_poly_pts.length/2;
+		while(i--) {
+			document.getElementById("polypointgrip_"+i).setAttribute("display", "none");
+		}
+		document.getElementById("poly_stretch_line").setAttribute("display", "none");
+	};
+
+	var addAllPointGripsToPoly = function() {
+		// loop through and hide all pointgrips
+		var i = current_poly_pts.length;
+		while(i) {
+			i -= 2;
+			var grip = document.getElementById("polypointgrip_"+i/2);
+			grip.setAttribute("cx", current_poly_pts[i]);
+			grip.setAttribute("cy", current_poly_pts[i+1]);
+			grip.setAttribute("display", "inline");
+		}
+	};
+
+	var addPointGripToPoly = function(x,y) {
+		// create the container of all the point grips
+		var pointGripContainer = document.getElementById("polypointgrip_container");
+		if (!pointGripContainer) {
+			var parent = document.getElementById("selectorParentGroup");
+			pointGripContainer = parent.appendChild(document.createElementNS(svgns, "g"));
+			pointGripContainer.id = "polypointgrip_container";
+		}
+
+		// get index of this point
+		var index = current_poly_pts.length/2 - 1;
+
+		var pointGrip = document.getElementById("polypointgrip_"+index);
+		// create it
+		if (!pointGrip) {
+			pointGrip = document.createElementNS(svgns, "circle");
+			pointGrip.id = "polypointgrip_" + index;
+			pointGrip.setAttribute("display", "none");
+			pointGrip.setAttribute("r", 4);
+			pointGrip.setAttribute("fill", "#0F0");
+			pointGrip.setAttribute("stroke", "#00F");
+			pointGrip.setAttribute("stroke-width", 2);
+			pointGrip.setAttribute("cursor", "move");
+			pointGrip.setAttribute("pointer-events", "all");
+			pointGrip = pointGripContainer.appendChild(pointGrip);
+
+			var grip = $('#polypointgrip_'+index);
+			grip.mouseover( function() { this.setAttribute("stroke", "#F00"); } );
+			grip.mouseout( function() {this.setAttribute("stroke", "#00F"); } );
+		}
+
+		// set up the point grip element and display it
+		pointGrip.setAttribute("cx", x);
+		pointGrip.setAttribute("cy", y);
+		pointGrip.setAttribute("display", "inline");
+	};
+
+	// - in create mode, the element's opacity is set properly, we create an InsertElementCommand
+	//   and store it on the Undo stack
+	// - in move/resize mode, the element's attributes which were affected by the move/resize are
+	//   identified, a ChangeElementCommand is created and stored on the stack for those attrs
+	//   this is done in when we recalculate the selected dimensions()
+	var mouseUp = function(evt)
+	{
+		if (!started) return;
+
+		var x = evt.pageX - container.parentNode.offsetLeft + container.parentNode.scrollLeft;
+		var y = evt.pageY - container.parentNode.offsetTop + container.parentNode.scrollTop;
+
+		started = false;
+		var element = svgdoc.getElementById(getId());
+		var keep = false;
+		switch (current_mode)
+		{
+			// intentionally fall-through to select here
+			case "resize":
+			case "multiselect":
+				if (rubberBox != null) {
+					rubberBox.setAttribute("display", "none");
+				}
+				current_mode = "select";
+			case "select":
+				if (selectedElements[0] != null) {
+					// if we only have one selected element
+					if (selectedElements[1] == null) {
+						// set our current stroke/fill properties to the element's
+						var selected = selectedElements[0];
+						current_fill = selected.getAttribute("fill");
+						current_fill_opacity = selected.getAttribute("fill-opacity");
+						current_stroke = selected.getAttribute("stroke");
+						current_stroke_opacity = selected.getAttribute("stroke-opacity");
+						current_stroke_width = selected.getAttribute("stroke-width");
+						current_stroke_style = selected.getAttribute("stroke-dasharray");
+						if (selected.tagName == "text") {
+							current_font_size = selected.getAttribute("font-size");
+							current_font_family = selected.getAttribute("font-family");
+						}
+
+						selectorManager.requestSelector(selected).showGrips(selected.tagName != "text");
+					}
+					// if it was being dragged/resized
+					if (x != start_x || y != start_y) {
+						recalculateAllSelectedDimensions();
+						var len = selectedElements.length;
+						for	(var i = 0; i < len; ++i) {
+							if (selectedElements[i] == null) break;
+							selectorManager.requestSelector(selectedElements[i]).resize(selectedBBoxes[i]);
+						}
+					}
+					// no change in position/size, so maybe we should move to polyedit
+					else {
+						// TODO: this causes a poly that was just goi