EZProxy authentication via Cocoon and OpenSRF feature/ezproxy-authentication
authorDan Scott <dan@coffeecode.net>
Mon, 30 May 2011 20:04:23 +0000 (16:04 -0400)
committerDan Scott <dan@coffeecode.net>
Mon, 30 May 2011 20:04:23 +0000 (16:04 -0400)
Another great Art Rhyno joint

Signed-off-by: Dan Scott <dscott@laurentian.ca>
243 files changed:
Open-ILS/src/extras/authcon/README [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/content/auth.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/content/kickoff.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/content/opensrf.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/flow/auth.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/flow/md5.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/flow/opensrf.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/flow/util.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/forms/auth.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/forms/auth_template.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/images/Thumbs.db [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/images/bback.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/images/booking.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/images/button.jpg [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/images/cal.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/images/cancel.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/images/delete.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/images/eiu.jpg [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/images/end.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/images/help.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/images/loginwin.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/images/move_down.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/images/move_up.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/images/new.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/images/ok.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/images/start.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/images/status.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/images/update.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/images/zap.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/blank_btn.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/cal.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/close.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/close.gif.old [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/def2binding.xsl [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/delete.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/forms-advanced-field-styling.xsl [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/forms-calendar-styling.xsl [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/forms-calendar.css [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/forms-field-styling.xsl [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/forms-htmlarea-styling.xsl [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/forms-lib.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/forms-page-styling.xsl [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/forms-samples-styling.xsl [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/forms.css [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/help.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/.project [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/ChangeLog [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/dialog.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/htmlarea.css [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/htmlarea.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_about.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_align_center.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_align_justify.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_align_left.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_align_right.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_blank.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_charmap.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_color_bg.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_color_fg.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_copy.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_custom.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_cut.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_delete.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_bold.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_italic.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_strike.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_sub.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_sup.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_underline.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_help.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_hr.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_html.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_image.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_indent_less.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_indent_more.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_left_to_right.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_link.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_list_bullet.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_list_num.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_paste.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_redo.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_right_to_left.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_save.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_save.png [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_show_border.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_splitcel.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_undo.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/fullscreen_maximize.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/fullscreen_minimize.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/insert_table.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/makefile.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/index.html [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/b5.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/cz.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/da.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/de.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/ee.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/el.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/en.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/es.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/fi.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/fr.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/gb.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/he.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/hu.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/it.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/ja-euc.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/ja-jis.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/ja-sjis.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/ja-utf8.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/lt.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/lv.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/makefile.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/nb.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/nl.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/no.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/pl.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/pt_br.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/ro.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/ru.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/se.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/si.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/vn.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/license.txt [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/make-release.pl [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/makefile.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/CSS/css.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/CSS/lang/en.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/CSS/lang/makefile.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/CSS/makefile.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/1.pl [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/context-menu.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/lang/de.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/lang/el.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/lang/en.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/lang/makefile.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/lang/nl.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/makefile.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/menu.css [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/full-page.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/img/docprop.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/img/makefile.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/lang/en.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/lang/makefile.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/lang/ro.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/makefile.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/popups/docprop.html [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/popups/makefile.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/test.html [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/img/makefile.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/img/spell-check.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/cz.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/da.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/de.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/en.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/hu.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/it.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/makefile.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/ro.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/makefile.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/readme-tech.html [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/spell-check-logic.cgi [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/spell-check-style.css [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/spell-check-ui.html [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/spell-check-ui.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/spell-checker.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-delete.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-insert-after.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-insert-before.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-merge.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-prop.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-split.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/col-delete.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/col-insert-after.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/col-insert-before.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/col-split.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/makefile.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/row-delete.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/row-insert-above.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/row-insert-under.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/row-prop.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/row-split.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/table-prop.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/cz.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/da.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/de.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/el.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/en.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/fi.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/hu.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/it.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/makefile.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/nl.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/no.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/ro.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/makefile.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/table-operations.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/makefile.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/popupdiv.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/about.html [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/blank.html [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/custom2.html [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/editor_help.html [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/fullscreen.html [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/insert_image.html [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/insert_table.html [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/link.html [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/makefile.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/old-fullscreen.html [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/old_insert_image.html [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/popup.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/select_color.html [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/popupwin.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/project-config.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/reference.html [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/htmlarea/release-notes.html [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib/AnchorPosition.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib/CalendarPopup.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib/OptionTransfer.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib/PopupWindow.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib/README.txt [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib/date.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib/selectbox.js [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/move_down.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/move_up.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/resources/new.gif [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/scripts/ip_check.xsp [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/sitemap.xmap [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/stylesheets/as_is.xsl [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/stylesheets/opensrf.xsl [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/stylesheets/reportstatus.xsl [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/stylesheets/response2json.xsl [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/stylesheets/seth1.xsl [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/stylesheets/seth2.xsl [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/stylesheets/seth3.xsl [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/stylesheets/sethfinal.xsl [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/stylesheets/simple-page2html.xsl [new file with mode: 0644]
Open-ILS/src/extras/authcon/auth/stylesheets/xml2html.xslt [new file with mode: 0644]
Open-ILS/src/extras/authcon/seth/build.xml [new file with mode: 0644]
Open-ILS/src/extras/authcon/seth/src/EasySSLProtocolSocketFactory.java [new file with mode: 0644]
Open-ILS/src/extras/authcon/seth/src/EasyX509TrustManager.java [new file with mode: 0644]
Open-ILS/src/extras/authcon/seth/src/sethTransformer.java [new file with mode: 0644]

diff --git a/Open-ILS/src/extras/authcon/README b/Open-ILS/src/extras/authcon/README
new file mode 100644 (file)
index 0000000..6fa2838
--- /dev/null
@@ -0,0 +1,80 @@
+README - Sept. 2010
+
+This is an implementation of OpenSRF support for authentication using
+Cocoon. You have to get Cocoon directly at:
+
+ http://cocoon.apache.org/mirror.cgi
+
+The version we have worked with is 2.1.11, Cocoon must be compiled directly
+for the target machine and for that you need the JDK. Once the JDK is
+installed, set an environmental variable called JAVA_HOME to the root of
+the directory for the JDK. You can usually tell what this is by the location 
+of "lib/tools.jar", for example, on my version of ubuntu, JAVA_HOME is set to:
+
+ /usr/lib/jvm/java-6-sun
+
+and this is verified by the existence of tools.jar:
+
+ /usr/lib/jvm/java-6-sun/lib/tools.jar
+
+While you are setting the JAVA_HOME variable, it is a good time to set 2 
+other variables:
+
+ JAVA_OPTIONS="-Xms512M -Xmx512M"
+ JETTY_PORT=8080
+
+Jetty has a weird port by default, and "JETTY_PORT" should be set to
+whatever port is ok with your firewall setup. Both Jetty and Tomcat
+typically are set to max out at 64M of memory so the "JAVA_OPTIONS" bumps
+this up quite a bit. Reduce the numbers if your machine is very tight for
+RAM but this will help ensure that Jetty won't fall over.
+
+Cocoon uses a very old version of httpclient, so replace it with version
+3.1, it can be found here, for example:
+
+ http://apache.parentinginformed.com/httpcomponents/commons-httpclient/binary/commons-httpclient-3.1.zip 
+
+Unzip it and copy it to the lib directory of Cocoon, located at:
+
+ cocoon-2.1.11/build/webapp/WEB-INF/lib
+
+also remove the older version:
+
+ rm commons-httpclient-2.0.2.jar
+
+OpenSRF requires https and we use some special workarounds in case OpenSRF is on 
+a machine that has a temporary certificate. The component that pulls in
+httpclient to do the network interactions is called "seth" and it is installed
+by going into the "seth" directory and editing "build.xml". Look for this line:
+
+ <property name="cocoon.home"   value="/authcon/cocoon-2.1.11/build/webapp"/>
+
+Adjust the path to reflect where Cocoon has been installed. The application is
+compiled with Ant so go into the "seth" directory and issue a:
+
+ ant deploy
+
+This should compile and install the component. Now copy the "auth" directory to
+"build/webapp" directory of Cocoon. The "sitemap.xmap" file in "auth" contains
+the parameters for an ezproxy installation. Modify these to reflect your environment
+and start Cocoon by going to the "cocoon-2.1.11" directory and using either "cocoon.sh"
+or "cocoon.bat". Note that the files won't be set to be executable by default:
+
+ chmod +x *.sh
+ ./cocoon.sh
+
+If it looks like Cocoon started ok, try out the setup with a URL like:
+
+ http://test.library.org:8080/auth/check?url=http://www.jstor.org
+
+You should see an authentication form, and be able to use a valid opac account
+to be passed on to ezproxy. The form can be modified and styled in the "auth/forms"
+directory. Cocoon featured an early implementation of XForms, and it's kind 
+of quirky.
+
+If all of this seems to work, specify the network location of Cocoon in the "ezproxy.usr"
+file that EZproxy uses.
+
+And that's it! Feel free to contact me with any questions.
+
+Art Rhyno <artrhyno@uwindsor.ca>
diff --git a/Open-ILS/src/extras/authcon/auth/content/auth.xml b/Open-ILS/src/extras/authcon/auth/content/auth.xml
new file mode 100644 (file)
index 0000000..c004df7
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<page id="page" xmlns:c="http://apache.org/cocoon/templates/jx/1.0">
+       <barcode>
+               ${barcode}
+       </barcode>
+       <pin>
+               ${pin}
+       </pin>
+</page>
diff --git a/Open-ILS/src/extras/authcon/auth/content/kickoff.xml b/Open-ILS/src/extras/authcon/auth/content/kickoff.xml
new file mode 100644 (file)
index 0000000..8cc7d0c
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+
+<!-- kickoff.xml: kickoff a sitemap pipeline 
+                @author <a href="http://librarycog.uwindsor.ca">art rhyno</a>
+-->
+
+<content>
+       <dynamic-query/>
+</content>
diff --git a/Open-ILS/src/extras/authcon/auth/content/opensrf.xml b/Open-ILS/src/extras/authcon/auth/content/opensrf.xml
new file mode 100644 (file)
index 0000000..b94c589
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<opensrf id="osrf" xmlns:jx="http://apache.org/cocoon/templates/jx/1.0">\r
+       <service>\r
+               ${service}\r
+       </service>\r
+       <method>\r
+               ${method}\r
+       </method>\r
+       <parms>\r
+       <jx:forEach select="#{parms}" var="parm">\r
+               <parm>\r
+                       ${parm}\r
+               </parm>\r
+       </jx:forEach> \r
+       </parms>\r
+</opensrf>
\ No newline at end of file
diff --git a/Open-ILS/src/extras/authcon/auth/flow/auth.js b/Open-ILS/src/extras/authcon/auth/flow/auth.js
new file mode 100644 (file)
index 0000000..deac0e2
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+        auth.js - basic authentication support
+
+        (c) Copyright GNU General Public License (GPL)
+        @author <a href="http://projectconifer.ca">art rhyno</a>
+
+        Revised:
+*/
+cocoon.load("resource://org/apache/cocoon/forms/flow/javascript/Form.js");
+
+function authorization() {
+
+       var barcode;
+       var upassword;
+
+       var theurl = cocoon.parameters["thisurl"];
+       if (theurl.indexOf("url=") != -1) {
+               if (theurl.length > 4)
+                       theurl = theurl.substring(4);
+       }
+
+       var referer = cocoon.request.getHeader('Referer');
+
+       var theIP = cocoon.request.getRemoteAddr();
+       var theDomain = cocoon.parameters["ipdomain"];
+       var theOrg = cocoon.parameters["coniferorg"];
+
+       var probList = cocoon.parameters["problist"];
+       var banList = cocoon.parameters["banlist"];
+       if (banList == null)
+               banList="zipnada";
+       if (probList == null)
+               probList="zipnada";
+
+       var ezHost = cocoon.parameters["ezhost"];
+       var ezUser = cocoon.parameters["ezuser"];
+       var ezPassword = cocoon.parameters["ezpassword"];
+       var localAddr = false;
+
+       if (theIP.startsWith(theDomain))
+               localAddr = true;
+
+       //basic cleanup of urls
+       var jsurl= new String(theurl);
+       jsurl = jsurl.replace(/\&/gi,'%26');
+       jsurl = jsurl.replace(/%3F/gi,'?');
+
+       if (jsurl.length <= 1) {
+               print("zero length - redirecting");
+               cocoon.sendPage("willnotmatchsoredirect");
+               return;
+       }
+
+       if (!localAddr) {
+               var form = new Form("forms/auth.xml");
+               form.showForm("auth-display-pipeline");
+
+               var model = form.getModel();
+               barcode = model.barcode.replace(' ','');
+               barcode = barcode.replace('-','');
+
+               upassword = model.pin.replace(' ','');
+               if (probList.indexOf(theIP) != -1 || banList.indexOf(barcode) != -1) {
+                       cocoon.sendPage("willnotmatchsoredirect");
+                       return;
+               }//if
+       } else {
+               cocoon.sendPage("pass-on?url=" + theurl);
+               return;
+       }//if   
+
+       /*
+               OpenSRF support
+       */
+       var authToken = setUpSession(barcode, upassword, "opac", 
+                               theOrg, "");
+                       
+       var authFlag = false;
+       if (authToken != null) {
+               authFlag = true;
+               //clean up connection
+               sessionDelete(authToken);
+       }
+               
+       if (!authFlag) {
+               cocoon.sendPage("authenticate.jx?flag=" + 
+                       authFlag + "&url=" +
+                       theurl);
+       } else {
+               var passedUrl = ezHost + "/login%3Fuser=" + ezUser + 
+                       "%26pass=" + ezPassword + "%26url=" + jsurl;
+               cocoon.sendPage("pass-on?url=" + passedUrl);
+
+       }//if 
+}
diff --git a/Open-ILS/src/extras/authcon/auth/flow/md5.js b/Open-ILS/src/extras/authcon/auth/flow/md5.js
new file mode 100644 (file)
index 0000000..9d1ad24
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
+ * Digest Algorithm, as defined in RFC 1321.
+ * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for more info.
+ */
+
+var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
+var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
+var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
+function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
+function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
+function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
+function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
+function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
+function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
+function md5_vm_test()
+{
+  return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
+}
+function core_md5(x, len)
+{
+  /* append padding */
+  x[len >> 5] |= 0x80 << ((len) % 32);
+  x[(((len + 64) >>> 9) << 4) + 14] = len;
+
+  var a =  1732584193;
+  var b = -271733879;
+  var c = -1732584194;
+  var d =  271733878;
+
+  for(var i = 0; i < x.length; i += 16)
+  {
+    var olda = a;
+    var oldb = b;
+    var oldc = c;
+    var oldd = d;
+
+    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
+    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
+    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
+    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
+    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
+    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
+    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
+    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
+    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
+    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
+    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
+    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
+    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
+    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
+    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
+    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
+
+    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
+    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
+    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
+    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
+    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
+    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
+    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
+    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
+    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
+    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
+    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
+    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
+    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
+    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
+    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
+    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
+
+    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
+    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
+    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
+    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
+    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
+    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
+    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
+    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
+    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
+    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
+    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
+    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
+    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
+    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
+    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
+    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
+
+    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
+    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
+    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
+    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
+    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
+    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
+    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
+    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
+    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
+    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
+    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
+    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
+    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
+    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
+    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
+    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
+
+    a = safe_add(a, olda);
+    b = safe_add(b, oldb);
+    c = safe_add(c, oldc);
+    d = safe_add(d, oldd);
+  }
+  return Array(a, b, c, d);
+
+}
+function md5_cmn(q, a, b, x, s, t)
+{
+  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
+}
+function md5_ff(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
+}
+function md5_gg(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
+}
+function md5_hh(a, b, c, d, x, s, t)
+{
+  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
+}
+function md5_ii(a, b, c, d, x, s, t)
+{
+  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
+}
+function core_hmac_md5(key, data)
+{
+  var bkey = str2binl(key);
+  if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
+
+  var ipad = Array(16), opad = Array(16);
+  for(var i = 0; i < 16; i++)
+  {
+    ipad[i] = bkey[i] ^ 0x36363636;
+    opad[i] = bkey[i] ^ 0x5C5C5C5C;
+  }
+
+  var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
+  return core_md5(opad.concat(hash), 512 + 128);
+}
+function safe_add(x, y)
+{
+  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+  return (msw << 16) | (lsw & 0xFFFF);
+}
+function bit_rol(num, cnt)
+{
+  return (num << cnt) | (num >>> (32 - cnt));
+}
+function str2binl(str)
+{
+  var bin = Array();
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < str.length * chrsz; i += chrsz)
+    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
+  return bin;
+}
+function binl2str(bin)
+{
+  var str = "";
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < bin.length * 32; i += chrsz)
+    str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
+  return str;
+}
+function binl2hex(binarray)
+{
+  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i++)
+  {
+    str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
+           hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
+  }
+  return str;
+}
+function binl2b64(binarray)
+{
+  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  var str = "";
+  for(var i = 0; i < binarray.length * 4; i += 3)
+  {
+    var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
+                | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
+                |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
+    for(var j = 0; j < 4; j++)
+    {
+      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
+      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
+    }
+  }
+  return str;
+}
+
diff --git a/Open-ILS/src/extras/authcon/auth/flow/opensrf.js b/Open-ILS/src/extras/authcon/auth/flow/opensrf.js
new file mode 100644 (file)
index 0000000..e1aa4d6
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+       opensrf.js - opensrf convenience functions
+       (c) Copyright GNU General Public License (GPL)
+       @author <a href="http://projectconifer.ca">art rhyno</a>
+       Revised:
+*/
+
+
+function setUpSession(userid, password, sessionType, org, workstation)
+{
+       var parms = [];
+       var authToken=null;
+       var osrfdata;
+
+       parms[0] = "\"" + userid +"\"";
+       osrfdata = {
+                       "service" : "open-ils.auth",
+                       "method"  : "open-ils.auth.authenticate.init",
+                       "parms"   : parms }
+
+       var osrf = jsonify("opensrf",osrfdata);
+       print("init: " + osrf.status);
+
+       if (parseInt(osrf.status) == 200) {             
+               print("-> " + osrf.payload);
+               var md5Password = hex_md5(osrf.payload + hex_md5(password));
+               print("-> " + md5Password);
+               parms[0] = "{\"password\":\"" + md5Password + "\",\"type\":\"" + sessionType + "\",\"org\":";
+               if (sessionType == 'opac') { 
+                       parms[0] += ("\"" + org + "\",\"username\":\"" + userid + "\"}");
+               } else {
+                       parms[0] += (
+                       "\"" + org + "\",\"username\":\"" + userid +"\",\"workstation\":\"" +
+                       workstation + "\"}");
+               }
+               print("-> " + parms[0]);
+               osrfdata = {
+                       "service" : "open-ils.auth",
+                       "method"  : "open-ils.auth.authenticate.complete",
+                       "parms"   : parms }
+
+               osrf = jsonify("opensrf",osrfdata);
+               try {
+               authToken = osrf.payload[0].payload.authtoken;
+               } catch (er) {
+                       //print("error " + er);
+               }
+       }//if
+
+       return authToken;
+}//setUpSession
+
+function patronUpdate(authToken, patronInfo) {
+       var parms = [];
+       var osrfdata;
+
+       try {
+               parms[0] = "\"" + authToken + "\"";
+               parms[1] = patronInfo;
+               osrfdata = {
+                       "service" : "open-ils.actor",
+                       "method"  : "open-ils.actor.patron.update",
+                       "parms"   : parms }
+               var osrf = jsonify("opensrf",osrfdata);
+               if (parseInt(osrf.status) == 200)
+                       return true;
+       } catch (ex) {
+               print("problem with patron update: " + ex);
+       }//try
+
+       return false;
+}//patronUpdate
+
+function retrieveUsrByBarcode(authToken, barcode) {
+       var osrfstr = "";
+       var parms = [];
+
+       //check barcode
+       print(authToken + " - about to search");
+       parms[0] = "\"" + authToken + "\"";
+       parms[1] = "\"" + barcode + "\"";
+       var osrfdata = {
+               "service" : "open-ils.actor",
+               "method"  : "open-ils.actor.user.fleshed.retrieve_by_barcode",
+               "parms"   : parms }
+
+       //we don't want a json object in this case
+       osrfstr = dejsonify("opensrf",osrfdata);
+
+       return osrfstr;
+}//retrieveByBarcode
+
+/*
+       checkBarcode
+
+       - return true if barcode is found, false if not
+*/
+function checkBarcode(authToken, barcode) {
+       var found = true;
+       var parms = [];
+
+       //check barcode
+       print(authToken + " - about to search");
+       parms[0] = "\"" + authToken + "\"";
+       parms[1] = "\"" + barcode + "\"";
+       var osrfdata = {
+               "service" : "open-ils.actor",
+               "method"  : "open-ils.actor.user.retrieve_id_by_barcode_or_username",
+               "parms"   : parms }
+       var osrf = jsonify("opensrf",osrfdata);
+
+       //this will be a string if found
+       if(typeof(osrf.payload[0].textcode) != "undefined")
+               found = false;
+
+       //print("-> " + typeof(osrf.payload[0].textcode));
+
+       return found;
+}//checkBarcode
+
+/*
+       checkOrgId
+
+       - return true if ord id is found, false if not
+*/
+function checkOrgId(authToken, orgId) {
+       var found = true;
+       var parms = [];
+
+       parms[0] = "\"" + authToken + "\"";
+       //Group 2 are phone numbers and ID values.
+       parms[1] = "{\"ident\":{\"value\":\"" + orgId + "\",\"group\":2}}";
+
+       var osrfdata = {
+               "service" : "open-ils.actor",
+               "method"  : "open-ils.actor.patron.search.advanced",
+               "parms"   : parms }
+       var osrf = jsonify("opensrf",osrfdata);
+
+       //this will be the db id if found
+       if((osrf.payload[0] + "").length == 0)
+               found = false;
+
+       return found;
+}//checkOrgId
+
+/*
+       sortOutVal
+       
+       - put value in opensrf-friendly syntax, e.g., "foo", null, "fee"
+*/
+function sortOutVal(theVal) {
+       var newVal = theVal;
+       newVal = newVal.replace (/^\s+|\s+$/g,'');
+       if (newVal.length == 0)
+               return "null";
+
+       return "\"" + newVal + "\"";
+}//sortOutVal
+
+/*
+       sessionDelete
+       
+       - delete existing session
+*/
+function sessionDelete(authToken) {
+       var parms = [];
+       
+       try {
+               parms[0] = authToken;
+               var osrfdata = {
+                       "service" : "open-ils.auth",
+                       "method"  : "open-ils.auth.session.delete",
+                       "parms"   : parms }
+               var osrf = jsonify("opensrf",osrfdata);
+               print("delete: " + osrf.status);
+               if (parseInt(osrf.status) == 200)
+                       return true;
+       } catch (ex) {
+               print("problem with session delete: " + ex);
+       }
+
+       return false;
+}//sessionDelete
diff --git a/Open-ILS/src/extras/authcon/auth/flow/util.js b/Open-ILS/src/extras/authcon/auth/flow/util.js
new file mode 100644 (file)
index 0000000..cd171ef
--- /dev/null
@@ -0,0 +1,277 @@
+/*\r
+ *             util.js - generic help functions\r
+ *\r
+ *              Art Rhyno (arhyno@uwindsor.ca), August 2006\r
+ *              (c) Copyright GNU General Public License (GPL)\r
+ *\r
+ *              Revised:\r
+*/\r
+\r
+var prob1 = ", {}]}{}";\r
+var prob2 = "{}";\r
+var prob3 = "\",{\"url";\r
+\r
+/*\r
+       sleep() - the rhino implementation doesn't have a setTimeout\r
+               function, but this is a better approach anyway since\r
+               javascript still consumes CPU. Java has a true sleep\r
+               function and that is what we use here.\r
+*/\r
+\r
+function sleep (secs)\r
+{\r
+       //bump up to seconds\r
+       var theSecs = secs * 1000;\r
+       java.lang.Thread.sleep(theSecs);\r
+}//sleep\r
+\r
+function endsWith(theStr, theEnd) {\r
+       var theStrEnd = theStr.substring(theStr.length - theEnd.length);\r
+       print("comparing " + theStrEnd + " to " + theEnd);\r
+       if (theStrEnd == theEnd)\r
+               return true;\r
+\r
+       return false;\r
+}\r
+\r
+                \r
+function extractAttribute(attribute, attrStr) {\r
+       var attrVal = attrStr.replace(/\s+=/,'=') + "";\r
+       attrVal = attrVal.replace(/=\s+/,'=');\r
+       var attrLoc = attribute + "=";\r
+       var attrPos = attrVal.indexOf(attrLoc);\r
+                        \r
+       if (attrPos != -1) {\r
+               attrVal = attrVal.substring(attrPos +\r
+                       attrLoc.length);\r
+               attrPos = attrVal.indexOf(",");\r
+                                \r
+               if (attrPos != -1) {\r
+                       attrVal = attrVal.substring(0,\r
+                               attrPos);\r
+                                \r
+               }//if attrPos\r
+                        \r
+       }//if\r
+                        \r
+       return attrVal;\r
+}\r
+\r
+\r
+function figureOutPath(theBase, theApp, theFile) {\r
+        var fullFile = theFile;\r
+         var fullBase = theBase;\r
+         if (!endsWith(fullBase,'/'))\r
+               fullBase = fullBase + "/";\r
+       \r
+        if (theFile.indexOf("/") != 0)\r
+                fullFile = fullBase + theApp + "/" +\r
+                        fullFile;\r
+\r
+        print("returning " + fullFile);\r
+\r
+        return fullFile;\r
+}\r
+\r
+function fixQuote(theVal) {\r
+       var retVal = theVal.replace(/\'/g,"\\\'");\r
+\r
+       return retVal;\r
+}\r
+\r
+function countInstances(theVal, theChar) {\r
+  var substrings = theVal.split(theChar);\r
+  return substrings.length - 1;\r
+}\r
+\r
+function fixCollection(theStr,theProb) {\r
+       var collStr = "collection\":{";\r
+       var newStr = theStr;\r
+\r
+       var thispos = theStr.indexOf(collStr);\r
+\r
+       if (thispos != -1) {\r
+               newStr = theStr.substring(0,thispos) + "collection\":" +\r
+                       "[{" + theStr.substring(thispos+collStr.length);\r
+       }\r
+\r
+       thispos = newStr.indexOf(theProb);\r
+       if (thispos != -1) \r
+               newStr = newStr.substring(0,thispos) + "]}]}";\r
+\r
+\r
+       return newStr;\r
+}\r
+\r
+function sortOutDate(dateStr, dashed) {\r
+       print("dateStr - " + dateStr);\r
+       var theDate = new Date();\r
+       if (dashed)\r
+               dateStr.match(/(\d{4})\-(\d{2})\-(\d{2})/);\r
+       else\r
+               dateStr.match(/(\d{4})\.(\d{2})\.(\d{2})/);\r
+\r
+       print(RegExp.$1 + " - " + RegExp.$2 + " - " + RegExp.$3)\r
+       theDate.setYear(RegExp.$1);\r
+       theDate.setMonth(RegExp.$2);\r
+       theDate.setDate(RegExp.$3);\r
+\r
+       print("returning " + theDate);\r
+\r
+       return theDate;\r
+}//sortOutDate\r
+\r
+function jsonEval(inStr) {\r
+       //print("starts " + inStr + " - " + countInstances(inStr,"}") + " - " + countInstances(inStr,"{"));\r
+       var theStr = inStr;\r
+       if (countInstances(theStr,"}") < countInstances(theStr,"{")) {\r
+               //theStr = theStr.substring(0,theStr.length - 1);\r
+               theStr += "}";\r
+               //print("modified");\r
+       }\r
+               \r
+       var evalObj = null;\r
+       try {\r
+               evalObj = eval('(' + theStr + ')');\r
+       } catch (evalProb) {\r
+               print("jsonify can't convert: " + evalObj);\r
+               print("jsonify can't convert - " + evalProb);\r
+       }\r
+\r
+        \r
+        return evalObj; \r
+}\r
+\r
+//jsonify - put results of pipeline into JSON format\r
+function jsonify(pipeline, pipeinfo) {\r
+\r
+        //print("json pipeline is " + pipeline);\r
+        var stream = new java.io.ByteArrayOutputStream();\r
+        cocoon.processPipelineTo( pipeline, pipeinfo, stream );\r
+        var theVal = stream.toString() + "";\r
+       //print("serviceVal is " + theVal);\r
+        var checkpos = -1;\r
+       /*      this probably doesn't have to be in a try/catch block\r
+               but i had a problem with one range where it was an odd\r
+               character. i couldn't replicate it again.\r
+       */      \r
+       try {\r
+               checkpos = theVal.indexOf(prob1);\r
+               if (checkpos != -1)\r
+                       theVal = fixCollection(theVal,prob1);\r
+               checkpos = theVal.indexOf(prob2);\r
+               if (checkpos != -1)\r
+                       theVal = theVal.substring(0,checkpos);\r
+               checkpos = theVal.indexOf(prob3);\r
+               if (checkpos != -1) {\r
+                       theVal = theVal.replace(/,\{\"url/g,'},{\"url') + "";\r
+                       theVal = theVal.replace(/\"\]/g,'\"}]');\r
+                       //print("now -> " + theVal + "<-");\r
+               }\r
+       } catch (problem) {\r
+               print("nasty char issue " + problem);\r
+       }\r
+\r
+       var theEval = jsonEval(theVal);\r
\r
+       //cocoon.dispose(stream);\r
+\r
+       return theEval;\r
+\r
+}//jsonify\r
+\r
+//jsonify - get json results but leave in string format\r
+function dejsonify(pipeline, pipeinfo) {\r
+\r
+        //print("json pipeline is " + pipeline);\r
+        var stream = new java.io.ByteArrayOutputStream();\r
+        cocoon.processPipelineTo( pipeline, pipeinfo, stream );\r
+        return stream.toString() + "";\r
+\r
+}//dejsonify\r
+\r
+//reportStatus - send message to status pipeline\r
+function reportStatus(theReason) {\r
+       print("thereason is " + theReason);\r
+        var reason = {  \r
+                "reason" : theReason\r
+        }       \r
+        cocoon.sendPage("wagger-status-pipeline", reason);\r
+}//reportStatus  \r
+\r
+function reportStatusInJson(theReason) {\r
+       //print("sending " + theReason);\r
+        var reason = {  \r
+                "reason" : theReason\r
+        }       \r
+        cocoon.sendPage("wagger-status-pipeline-json", reason);\r
+}//reportStatusInJson  \r
+\r
+function Mod10(ccNumb) {  // v2.0\r
+var valid = "0123456789"  // Valid digits in a credit card number\r
+var len = ccNumb.length;  // The length of the submitted cc number\r
+var iCCN = parseInt(ccNumb);  // integer of ccNumb\r
+var sCCN = ccNumb.toString();  // string of ccNumb\r
+sCCN = sCCN.replace (/^\s+|\s+$/g,'');  // strip spaces\r
+var iTotal = 0;  // integer total set at zero\r
+var bNum = true;  // by default assume it is a number\r
+var bResult = false;  // by default assume it is NOT a valid cc\r
+var temp;  // temp variable for parsing string\r
+var calc;  // used for calculation of each digit\r
+\r
+// Determine if the ccNumb is in fact all numbers\r
+for (var j=0; j<len; j++) {\r
+  temp = "" + sCCN.substring(j, j+1);\r
+  if (valid.indexOf(temp) == "-1"){bNum = false;}\r
+}\r
+\r
+// if it is NOT a number, you can either alert to the fact, or just pass a failure\r
+if(!bNum){\r
+  /*alert("Not a Number");*/bResult = false;\r
+}\r
+\r
+// Determine if it is the proper length \r
+if((len == 0)&&(bResult)){  // nothing, field is blank AND passed above # check\r
+  bResult = false;\r
+} else{  // ccNumb is a number and the proper length - let's see if it is a valid card number\r
+  if(len == 14){  // 15 or 16 for Amex or V/MC\r
+    for(var i=len;i>0;i--){  // LOOP throught the digits of the card\r
+      calc = parseInt(iCCN) % 10;  // right most digit\r
+      calc = parseInt(calc);  // assure it is an integer\r
+      iTotal += calc;  // running total of the card number as we loop - Do Nothing to first digit\r
+      i--;  // decrement the count - move to the next digit in the card\r
+      iCCN = iCCN / 10;                               // subtracts right most digit from ccNumb\r
+      calc = parseInt(iCCN) % 10 ;    // NEXT right most digit\r
+      calc = calc *2;                                 // multiply the digit by two\r
+      // Instead of some screwy method of converting 16 to a string and then parsing 1 and 6 and then adding them to make 7,\r
+      // I use a simple switch statement to change the value of calc2 to 7 if 16 is the multiple.\r
+      switch(calc){\r
+        case 10: calc = 1; break;       //5*2=10 & 1+0 = 1\r
+        case 12: calc = 3; break;       //6*2=12 & 1+2 = 3\r
+        case 14: calc = 5; break;       //7*2=14 & 1+4 = 5\r
+        case 16: calc = 7; break;       //8*2=16 & 1+6 = 7\r
+        case 18: calc = 9; break;       //9*2=18 & 1+8 = 9\r
+        default: calc = calc;           //4*2= 8 &   8 = 8  -same for all lower numbers\r
+      }                                               \r
+    iCCN = iCCN / 10;  // subtracts right most digit from ccNum\r
+    iTotal += calc;  // running total of the card number as we loop\r
+  }  // END OF LOOP\r
+  if ((iTotal%10)==0){  // check to see if the sum Mod 10 is zero\r
+    bResult = true;  // This IS (or could be) a valid credit card number.\r
+  } else {\r
+    bResult = false;  // This could NOT be a valid credit card number\r
+    }\r
+  }\r
+}\r
+  return bResult; // Return the results\r
+}\r
+\r
+function listProperties(obj) {\r
+   var propList = "";\r
+   for(var propName in obj) {\r
+      if(typeof(obj[propName]) != "undefined") {\r
+         propList += (propName + ", " + typeof(obj[propName]));\r
+      }\r
+   }\r
+   print("--> " + propList);\r
+}
\ No newline at end of file
diff --git a/Open-ILS/src/extras/authcon/auth/forms/auth.xml b/Open-ILS/src/extras/authcon/auth/forms/auth.xml
new file mode 100644 (file)
index 0000000..4c82da6
--- /dev/null
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<!--
+        (c) Copyright GNU General Public License (GPL)
+        @author <a href="http://projectconifer.ca">art rhyno</a>
+
+-->
+<fd:form
+  xmlns:fd="http://apache.org/cocoon/forms/1.0#definition"
+  xmlns:i18n="http://apache.org/cocoon/i18n/2.1">
+
+       <fd:widgets>
+               <fd:field id="barcode" required="true">
+               <fd:label>Username or Barcode:</fd:label>
+
+               <fd:datatype base="string">
+                       <!--
+                       must be at least 3 characters
+                       -->
+                       <fd:validation>
+                               <fd:length min='3'/>
+                       </fd:validation>
+               </fd:datatype>
+               </fd:field>
+
+               <fd:field id="pin" required="true" readonly="true">
+               <fd:help>
+                       Barcodes can be entered in any of these formats:
+                       <ul>
+                               <strong>21862000111222</strong>
+                               <strong>21862-000-111-222</strong>
+                       </ul>
+               </fd:help>
+               <fd:label>Password:</fd:label>
+               <fd:datatype base="string"/>
+               </fd:field>
+       </fd:widgets>
+
+</fd:form>
diff --git a/Open-ILS/src/extras/authcon/auth/forms/auth_template.xml b/Open-ILS/src/extras/authcon/auth/forms/auth_template.xml
new file mode 100644 (file)
index 0000000..52d143c
--- /dev/null
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<!--
+        (c) Copyright GNU General Public License (GPL)
+        @author <a href="http://projectconifer.ca">art rhyno</a>
+-->
+<page xmlns:ft="http://apache.org/cocoon/forms/1.0#template"
+  xmlns:fi="http://apache.org/cocoon/forms/1.0#instance">
+  
+       <title>Library E-Resources</title>
+       <content>
+               <ft:form-template action="#{$continuation/id}.continue" method="POST">
+               <table align="left">
+               <tr>
+               <td width="95%">
+                       <fi:group>
+                       <fi:styling type="tabs"/>
+                       <fi:items>
+                               <fi:group>
+                               <fi:label>Authorization Information</fi:label>
+                               <fi:styling layout="columns"/>
+                               <fi:items>
+                               <ft:widget id="barcode"/>
+                               <ft:widget id="pin">
+                                       <fi:styling type="password"/>
+                               </ft:widget>
+                               <tr><td>
+                               <br><span class="forms-field-required"> * </span> - MUST be filled out.</br>
+                               </td></tr>
+                               <tr><td>
+                               <fi:action id="button">
+                                       <fi:label>Login</fi:label>                
+                               </fi:action>
+                               <input type="reset"/>
+                               </td></tr>
+                               </fi:items>
+                               </fi:group>
+                       </fi:items>
+                       </fi:group>
+               </td>
+               </tr>
+               </table>
+               </ft:form-template>
+       </content>
+</page>
diff --git a/Open-ILS/src/extras/authcon/auth/images/Thumbs.db b/Open-ILS/src/extras/authcon/auth/images/Thumbs.db
new file mode 100644 (file)
index 0000000..aaecadc
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/images/Thumbs.db differ
diff --git a/Open-ILS/src/extras/authcon/auth/images/bback.gif b/Open-ILS/src/extras/authcon/auth/images/bback.gif
new file mode 100644 (file)
index 0000000..7bd5769
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/images/bback.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/images/booking.gif b/Open-ILS/src/extras/authcon/auth/images/booking.gif
new file mode 100644 (file)
index 0000000..3aef2e7
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/images/booking.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/images/button.jpg b/Open-ILS/src/extras/authcon/auth/images/button.jpg
new file mode 100644 (file)
index 0000000..aebe00a
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/images/button.jpg differ
diff --git a/Open-ILS/src/extras/authcon/auth/images/cal.gif b/Open-ILS/src/extras/authcon/auth/images/cal.gif
new file mode 100644 (file)
index 0000000..681cd5d
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/images/cal.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/images/cancel.gif b/Open-ILS/src/extras/authcon/auth/images/cancel.gif
new file mode 100644 (file)
index 0000000..b022e06
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/images/cancel.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/images/delete.gif b/Open-ILS/src/extras/authcon/auth/images/delete.gif
new file mode 100644 (file)
index 0000000..a0f4891
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/images/delete.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/images/eiu.jpg b/Open-ILS/src/extras/authcon/auth/images/eiu.jpg
new file mode 100644 (file)
index 0000000..20deab4
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/images/eiu.jpg differ
diff --git a/Open-ILS/src/extras/authcon/auth/images/end.gif b/Open-ILS/src/extras/authcon/auth/images/end.gif
new file mode 100644 (file)
index 0000000..99a2c30
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/images/end.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/images/help.gif b/Open-ILS/src/extras/authcon/auth/images/help.gif
new file mode 100644 (file)
index 0000000..5a16b0b
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/images/help.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/images/loginwin.gif b/Open-ILS/src/extras/authcon/auth/images/loginwin.gif
new file mode 100644 (file)
index 0000000..07d96a6
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/images/loginwin.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/images/move_down.gif b/Open-ILS/src/extras/authcon/auth/images/move_down.gif
new file mode 100644 (file)
index 0000000..82ac5bf
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/images/move_down.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/images/move_up.gif b/Open-ILS/src/extras/authcon/auth/images/move_up.gif
new file mode 100644 (file)
index 0000000..c794d5d
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/images/move_up.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/images/new.gif b/Open-ILS/src/extras/authcon/auth/images/new.gif
new file mode 100644 (file)
index 0000000..df044bb
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/images/new.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/images/ok.gif b/Open-ILS/src/extras/authcon/auth/images/ok.gif
new file mode 100644 (file)
index 0000000..5bb323d
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/images/ok.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/images/start.gif b/Open-ILS/src/extras/authcon/auth/images/start.gif
new file mode 100644 (file)
index 0000000..789f70e
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/images/start.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/images/status.gif b/Open-ILS/src/extras/authcon/auth/images/status.gif
new file mode 100644 (file)
index 0000000..f202cc1
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/images/status.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/images/update.gif b/Open-ILS/src/extras/authcon/auth/images/update.gif
new file mode 100644 (file)
index 0000000..e5f294a
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/images/update.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/images/zap.gif b/Open-ILS/src/extras/authcon/auth/images/zap.gif
new file mode 100644 (file)
index 0000000..463a150
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/images/zap.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/blank_btn.gif b/Open-ILS/src/extras/authcon/auth/resources/blank_btn.gif
new file mode 100644 (file)
index 0000000..b41bab9
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/blank_btn.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/cal.gif b/Open-ILS/src/extras/authcon/auth/resources/cal.gif
new file mode 100644 (file)
index 0000000..681cd5d
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/cal.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/close.gif b/Open-ILS/src/extras/authcon/auth/resources/close.gif
new file mode 100644 (file)
index 0000000..807d354
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/close.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/close.gif.old b/Open-ILS/src/extras/authcon/auth/resources/close.gif.old
new file mode 100644 (file)
index 0000000..1974335
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/close.gif.old differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/def2binding.xsl b/Open-ILS/src/extras/authcon/auth/resources/def2binding.xsl
new file mode 100644 (file)
index 0000000..ac314a1
--- /dev/null
@@ -0,0 +1,82 @@
+<?xml version="1.0"?>
+<!--
+  Copyright 1999-2004 The Apache Software Foundation
+
+  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.
+-->
+<!--
+  Transforms a form definition file into a binding file. This is an attempt at merging
+  these two files in only one.
+  To use it, simply load the form bindings from a cocoon: pipeline that applies this stylesheet
+  on a form definition. Next step will by to rewrite this directly into Cocoon Forms binding system.
+  
+  The binding is created according to the following rules :
+  - fb:* attributes on widget definitions lead to the creation of
+    - <fb:context> if a @fb:context attribute is found
+    - <fb:simple-repeater> if a @fb:parent-path is found on a <fd:repeater>
+    - <fb:value> if a @fb:path is found on any fd:* element    
+  - if a <fd:binding> is present, its content is copied as is with the @id of the enclosing widget
+  
+  @author Sylvain Wallez
+  @version CVS $Id: def2binding.xsl 30932 2004-07-29 17:35:38Z vgritsenko $
+-->
+
+<xsl:stylesheet
+  version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:fd="http://apache.org/cocoon/forms/1.0#definition"
+  xmlns:fb="http://apache.org/cocoon/forms/1.0#binding">
+  
+<xsl:template match="fd:*[@fb:context]">
+  <fb:context path="{@fb:context}">
+    <xsl:for-each select="@*[(local-name(.) != 'context') and (namespace-uri() = 'http://apache.org/cocoon/forms/1.0#binding')]">
+      <xsl:attribute name="{local-name(.)}"><xsl:value-of select="."/></xsl:attribute>
+    </xsl:for-each>
+    <xsl:apply-templates/>
+  </fb:context>
+</xsl:template>
+
+<xsl:template match="fd:*[@fb:path]">
+  <fb:value id="{@id}">
+    <xsl:for-each select="@*[namespace-uri() = 'http://apache.org/cocoon/forms/1.0#binding']">
+      <xsl:attribute name="{local-name(.)}"><xsl:value-of select="."/></xsl:attribute>
+    </xsl:for-each>
+    <xsl:apply-templates/>
+  </fb:value>
+</xsl:template>
+
+<xsl:template match="fd:repeater[@fb:parent-path]">
+  <fb:simple-repeater id="{@id}">
+    <xsl:for-each select="@*[namespace-uri() = 'http://apache.org/cocoon/forms/1.0#binding']">
+      <xsl:attribute name="{local-name(.)}"><xsl:value-of select="."/></xsl:attribute>
+    </xsl:for-each>
+    <xsl:apply-templates/>
+  </fb:simple-repeater>
+</xsl:template>
+
+<xsl:template match="fd:*[fd:binding]">
+  <!-- copy the binding element -->
+  <xsl:variable name="binding" select="fd:binding/fb:*[1]"/>
+  <xsl:element name="{local-name($binding)}" namespace="{namespace-uri($binding)}">
+    <xsl:copy-of select="$binding/@*"/>
+    <xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute>
+    <xsl:copy-of select="$binding/node()"/>
+    <!-- and recurse in the widgets while in the binding element -->
+    <xsl:apply-templates/>
+  </xsl:element>
+</xsl:template>
+
+<!-- avoid copying text -->
+<xsl:template match="text()|@*"/>
+
+</xsl:stylesheet>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/delete.gif b/Open-ILS/src/extras/authcon/auth/resources/delete.gif
new file mode 100644 (file)
index 0000000..a0f4891
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/delete.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/forms-advanced-field-styling.xsl b/Open-ILS/src/extras/authcon/auth/resources/forms-advanced-field-styling.xsl
new file mode 100644 (file)
index 0000000..3552430
--- /dev/null
@@ -0,0 +1,184 @@
+<?xml version="1.0"?>
+<!--
+  Copyright 1999-2004 The Apache Software Foundation
+
+  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.
+-->
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:fi="http://apache.org/cocoon/forms/1.0#instance"
+                exclude-result-prefixes="fi">
+  <!--+
+      | This stylesheet is designed to be included by 'forms-samples-styling.xsl'.
+      | It extends the 'forms-field-styling.xsl' with additional stylings.
+      | The very specific advanced stylings as the calendar or htmlarea (both
+      | also need additional JS files) are separated out of this file.
+      +-->
+
+  <xsl:import href="forms-field-styling.xsl"/>
+  <xsl:include href="forms-calendar-styling.xsl"/>
+  <xsl:include href="forms-htmlarea-styling.xsl"/>
+  <!-- Location of the resources directory, where JS libs and icons are stored -->
+  <xsl:param name="resources-uri">resources</xsl:param>
+
+  <xsl:template match="head" mode="forms-field">
+    <xsl:apply-imports/>
+    <script src="{$resources-uri}/mattkruse-lib/AnchorPosition.js" type="text/javascript"/>
+    <script src="{$resources-uri}/mattkruse-lib/PopupWindow.js" type="text/javascript"/>
+    <script src="{$resources-uri}/mattkruse-lib/OptionTransfer.js" type="text/javascript"/>
+    <script src="{$resources-uri}/mattkruse-lib/selectbox.js" type="text/javascript"/>
+    <xsl:apply-templates select="." mode="forms-calendar"/>
+    <xsl:apply-templates select="." mode="forms-htmlarea"/>
+  </xsl:template>
+
+  <xsl:template match="body" mode="forms-field">
+    <xsl:apply-imports/>
+    <xsl:apply-templates select="." mode="forms-calendar"/>
+    <xsl:apply-templates select="." mode="forms-htmlarea"/>
+  </xsl:template>
+
+  <!--+ This template should not be necessary as this stylesheet "inherits"
+      | all templates from 'forms-field-styling.xsl', but without it, it does
+      | not work for me (using Xalan 2.5.1). It's like adding all methods of
+      | a superclass in a subclass and calling everywhere only the super
+      | implementation.
+      +-->
+  <xsl:template match="*">
+    <xsl:apply-imports/>
+  </xsl:template>
+
+  <!--+
+      | Add fi:help to the common stuff.
+      +-->
+  <xsl:template match="fi:*" mode="common">
+    <xsl:apply-imports/>
+    <xsl:apply-templates select="fi:help"/>
+  </xsl:template>
+
+  <!--+
+      | 
+      +-->
+  <xsl:template match="fi:help">
+    <xsl:variable name="id" select="generate-id()"/>
+    <div class="forms-help" id="help{$id}" style="visibility:hidden; position:absolute;">
+       <span style="float:right"><a href="#" onClick="helpWin{$id}.hidePopup();return false;"><img align="top" alt="close" src="{$resources-uri}/close.gif" height="6" width="6"/></a></span>
+      <xsl:apply-templates select="node()"/>
+    </div>
+    <script type="text/javascript">
+      var helpWin<xsl:value-of select="$id"/> = forms_createPopupWindow('help<xsl:value-of select="$id"/>');
+    </script>
+    <a id="{$id}" name="{$id}" href="#" onclick="helpWin{$id}.showPopup('{$id}');return false;">
+      <!-- TODO: i18n key for helppopup -->
+      <img src="{$resources-uri}/help.gif" alt="helppopup"/>
+    </a>
+  </xsl:template>
+
+  <!--+
+      | fi:multivaluefield with list-type='double-listbox' styling
+      +-->
+  <xsl:template match="fi:multivaluefield[fi:styling/@list-type='double-listbox']">
+    <xsl:variable name="id" select="@id"/>
+    <xsl:variable name="values" select="fi:values/fi:value/text()"/>
+
+    <div class="forms-doubleList" title="{fi:hint}">
+      <table>
+        <xsl:if test="fi:styling/fi:available-label|fi:styling/fi:selected-label">
+          <tr>
+            <th>
+              <xsl:copy-of select="fi:styling/fi:available-label/node()"/>
+            </th>
+            <th> </th>
+            <th>
+              <xsl:copy-of select="fi:styling/fi:selected-label/node()"/>
+            </th>
+          </tr>
+        </xsl:if>
+        <tr>
+          <td>
+            <!-- select for the unselected values -->
+            <select id="{@id}.unselected" name="{@id}.unselected" multiple="multiple"
+                    ondblclick="opt{generate-id()}.forms_transferRight()">
+              <xsl:apply-templates select="." mode="styling"/>
+              <xsl:for-each select="fi:selection-list/fi:item">
+                <xsl:variable name="value" select="@value"/>
+                <xsl:if test="not($values[. = $value])">
+                  <option value="{$value}">
+                    <xsl:copy-of select="fi:label/node()"/>
+                  </option>
+                </xsl:if>
+              </xsl:for-each>
+            </select>
+          </td>
+          <td>
+            <!-- command buttons -->
+            <!-- strangely, IE adds an extra blank line if there only a button on a line. So we surround it with nbsp -->
+            <xsl:text>&#160;</xsl:text>
+            <input type="button" value="&gt;" onclick="opt{generate-id()}.forms_transferRight()">
+              <xsl:if test="@state='disabled'">
+                <xsl:attribute name="disabled">disabled</xsl:attribute>
+              </xsl:if>
+            </input>
+            <xsl:text>&#160;</xsl:text>
+            <br/>
+            <xsl:text>&#160;</xsl:text>
+            <input type="button" value="&gt;&gt;" onclick="opt{generate-id()}.forms_transferAllRight()">
+              <xsl:if test="@state='disabled'">
+                <xsl:attribute name="disabled">disabled</xsl:attribute>
+              </xsl:if>
+            </input>
+            <xsl:text>&#160;</xsl:text>
+            <br/>
+            <xsl:text>&#160;</xsl:text>
+            <input type="button" value="&lt;" onclick="opt{generate-id()}.forms_transferLeft()">
+              <xsl:if test="@state='disabled'">
+                <xsl:attribute name="disabled">disabled</xsl:attribute>
+              </xsl:if>
+            </input>
+            <xsl:text>&#160;</xsl:text>
+            <br/>
+            <xsl:text>&#160;</xsl:text>
+            <input type="button" value="&lt;&lt;" onclick="opt{generate-id()}.forms_transferAllLeft()">
+              <xsl:if test="@state='disabled'">
+                <xsl:attribute name="disabled">disabled</xsl:attribute>
+              </xsl:if>
+            </input>
+            <xsl:text>&#160;</xsl:text>
+            <br/>
+            <xsl:apply-templates select="." mode="common"/>
+          </td>
+          <td>
+            <!-- select for the selected values -->
+            <select id="{@id}" name="{@id}" multiple="multiple"
+                    ondblclick="opt{generate-id()}.forms_transferLeft()" >
+              <xsl:apply-templates select="." mode="styling"/>
+              <xsl:for-each select="fi:selection-list/fi:item">
+                <xsl:variable name="value" select="@value"/>
+                <xsl:if test="$values[. = $value]">
+                  <option value="{$value}">
+                    <xsl:copy-of select="fi:label/node()"/>
+                  </option>
+                </xsl:if>
+              </xsl:for-each>
+            </select>
+          </td>
+        </tr>
+      </table>
+      <script type="text/javascript">
+        var opt<xsl:value-of select="generate-id()"/> = forms_createOptionTransfer('<xsl:value-of select="@id"/>', <xsl:value-of select="fi:styling/@submit-on-change = 'true'"/>);
+      </script>
+    </div>
+  </xsl:template>
+
+  <xsl:template match="fi:multivaluefield/fi:styling[@list-type='double-listbox']/@submit-on-change" mode="styling"/>
+
+</xsl:stylesheet>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/forms-calendar-styling.xsl b/Open-ILS/src/extras/authcon/auth/resources/forms-calendar-styling.xsl
new file mode 100644 (file)
index 0000000..43b0a7e
--- /dev/null
@@ -0,0 +1,99 @@
+<?xml version="1.0"?>
+<!--
+  Copyright 1999-2004 The Apache Software Foundation
+
+  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.
+-->
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:fi="http://apache.org/cocoon/forms/1.0#instance"
+                exclude-result-prefixes="fi">
+  <!--+
+      | This stylesheet is designed to be included by 'forms-advanced-styling.xsl'.
+      +-->
+
+  <!-- Location of the resources directory, where JS libs and icons are stored -->
+  <xsl:param name="resources-uri">resources</xsl:param>
+
+  <xsl:template match="head" mode="forms-calendar">
+    <script src="{$resources-uri}/mattkruse-lib/CalendarPopup.js" type="text/javascript"/>
+    <script src="{$resources-uri}/mattkruse-lib/date.js" type="text/javascript"/>
+    <script type="text/javascript">
+      // Setup calendar
+      var forms_calendar = CalendarPopup('forms_calendarDiv');
+      forms_calendar.setWeekStartDay(1);
+      forms_calendar.showYearNavigation();
+      forms_calendar.showYearNavigationInput();
+      forms_calendar.setCssPrefix("forms_");
+
+       function focusfirst() {
+       //set up first field
+        try {
+                document.getElementById('barcode').focus();
+        } catch (error) {
+                //just in case
+        }
+       }
+    </script>
+    <link rel="stylesheet" type="text/css" href="{$resources-uri}/forms-calendar.css"/>
+  </xsl:template>
+
+  <xsl:template match="body" mode="forms-calendar">
+    <div id="forms_calendarDiv"/>
+  </xsl:template>
+
+  <!--+
+      | fi:field with either
+      | - explicit styling @type = 'date' or
+      | - implicit if no styling @type is specified,
+      |   but datatype/@type = 'date' and datatype/convertor/@variant = 'date',
+      |   selection lists must be excluded here
+      +-->
+  <xsl:template match="fi:field[fi:styling/@type='date'] |
+                       fi:field[not(fi:styling/@type)][fi:datatype[@type='date'][fi:convertor/@variant='date']][not(fi:selection-list)]">
+    <xsl:variable name="id" select="generate-id()"/>
+    
+    <xsl:variable name="format">
+      <xsl:choose>
+        <xsl:when test="fi:datatype[@type='date']/fi:convertor/@pattern">
+          <xsl:value-of select="fi:datatype[@type='date']/fi:convertor/@pattern"/>
+        </xsl:when>
+        <xsl:otherwise>yyyy-MM-dd</xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    
+    <!-- regular input -->
+    <input id="{@id}" name="{@id}" value="{fi:value}" title="{normalize-space(fi:hint)}" type="text">
+      <xsl:apply-templates select="." mode="styling"/>
+    </input>
+    
+    <!-- calendar popup -->
+    <xsl:choose>
+      <xsl:when test="@state = 'disabled'">
+        <!-- TODO: i18n key for @alt -->
+        <img src="{$resources-uri}/cal.gif" alt="Calendar"/>
+      </xsl:when>
+      <xsl:otherwise>
+        <a href="#" name="{$id}" id="{$id}"
+           onclick="forms_calendar.select(forms_getForm(this)['{@id}'],'{$id}','{$format}'); return false;">
+          <!-- TODO: i18n key for @alt -->
+          <img src="{$resources-uri}/cal.gif" alt="Calendar"/>
+        </a>
+      </xsl:otherwise>
+    </xsl:choose>
+
+    <!-- common stuff -->
+    <xsl:apply-templates select="." mode="common"/>
+  </xsl:template>
+
+</xsl:stylesheet>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/forms-calendar.css b/Open-ILS/src/extras/authcon/auth/resources/forms-calendar.css
new file mode 100644 (file)
index 0000000..50703e9
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+* Copyright 1999-2004 The Apache Software Foundation
+*
+* 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.
+*/
+#forms_calendarDiv {
+    position: absolute;
+    visibility: hidden;
+    background-color: white;
+    layer-background-color: white;
+}
+
+.forms_cpYearNavigation, .forms_cpMonthNavigation {
+    background-color:#C0C0C0;
+    text-align:center;
+    vertical-align:center;
+    text-decoration:none;
+    color:#000000;
+    font-weight:bold;
+}
+  
+.forms_cpDayColumnHeader, .forms_cpYearNavigation, .forms_cpMonthNavigation, .forms_cpCurrentMonthDate, .forms_cpCurrentMonthDateDisabled, .forms_cpOtherMonthDate, .forms_cpOtherMonthDateDisabled, .forms_cpCurrentDate, .forms_cpCurrentDateDisabled, .forms_cpTodayText, .forms_cpTodayTextDisabled, .forms_cpText {
+    font-family:arial;
+    font-size:8pt;
+}
+  
+TD.forms_cpDayColumnHeader {
+    text-align:right;
+    border:solid thin #C0C0C0;
+    border-width:0 0 19 0;
+}
+  
+.forms_cpCurrentMonthDate, .forms_cpOtherMonthDate, .forms_cpCurrentDate  {
+    text-align:right;
+    text-decoration:none;
+}
+  
+.forms_cpCurrentMonthDateDisabled, .forms_cpOtherMonthDateDisabled, .forms_cpCurrentDateDisabled {
+    color:#D0D0D0;
+    text-align:right;
+    text-decoration:line-through;
+}
+  
+.forms_cpCurrentMonthDate, .forms_cpCurrentDate {
+    color:#000000;
+}
+  
+.forms_cpOtherMonthDate {
+    color:#808080;
+}
+  
+TD.forms_cpCurrentDate {
+    color:white; background-color: #C0C0C0;
+    border-width:1;
+    border:solid thin #800000;
+}
+  
+TD.forms_cpCurrentDateDisabled {
+    border-width:1;
+    border:solid thin #FFAAAA;
+}
+  
+TD.forms_cpTodayText, TD.forms_cpTodayTextDisabled {
+    border:solid thin #C0C0C0;
+    border-width:1 0 0 0;
+}
+  
+A.forms_cpTodayText, SPAN.forms_cpTodayTextDisabled {
+    height:20px;
+}
+  
+A.forms_cpTodayText {
+    color:black;
+}
+  
+.forms_cpTodayTextDisabled {
+    color:#D0D0D0;
+}
+  
+.forms_cpBorder {
+    border:solid thin #808080;
+}
diff --git a/Open-ILS/src/extras/authcon/auth/resources/forms-field-styling.xsl b/Open-ILS/src/extras/authcon/auth/resources/forms-field-styling.xsl
new file mode 100644 (file)
index 0000000..408967a
--- /dev/null
@@ -0,0 +1,554 @@
+<?xml version="1.0"?>
+<!--
+  Copyright 1999-2004 The Apache Software Foundation
+
+  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.
+-->
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:fi="http://apache.org/cocoon/forms/1.0#instance"
+                exclude-result-prefixes="fi">
+  <!--+
+      | This stylesheet is designed to be included by 'forms-samples-styling.xsl'.
+      | Version CVS $Id: forms-field-styling.xsl 57374 2004-11-10 21:19:51Z tim $
+      +-->
+
+  <!-- Location of the resources directory, where JS libs and icons are stored -->
+  <xsl:param name="resources-uri">resources</xsl:param>
+
+  <xsl:template match="head" mode="forms-field">
+    <script src="{$resources-uri}/forms-lib.js" type="text/javascript"/>
+    <link rel="stylesheet" type="text/css" href="{$resources-uri}/forms.css"/>
+  </xsl:template>
+
+  <xsl:template match="body" mode="forms-field">
+    <xsl:copy-of select="@*"/>
+    <xsl:attribute name="onload">forms_onload(); <xsl:value-of select="@onload"/> focusfirst();</xsl:attribute>
+  </xsl:template>
+
+  <!--+
+      | Generic fi:field : produce an <input>
+      +-->
+  <xsl:template match="fi:field">
+    <input name="{@id}" id="{@id}" value="{fi:value}" title="{fi:hint}" type="text">
+      <xsl:apply-templates select="." mode="styling"/>
+    </input>
+    <xsl:apply-templates select="." mode="common"/>
+  </xsl:template>
+
+  <!--+
+      | Common stuff like fi:validation-message, @required.
+      +-->
+  <xsl:template match="fi:*" mode="common">
+    <!-- validation message -->
+    <xsl:apply-templates select="fi:validation-message"/>
+    <!-- required mark -->
+    <xsl:if test="@required='true'">
+      <span class="forms-field-required"> * </span>
+    </xsl:if>
+  </xsl:template>
+
+  <!--+
+      | Handling the common styling. You may only add attributes to the output
+      | in this template as later processing might add attributes too, for
+      | example @checked or @selected
+      +-->
+  <xsl:template match="fi:*" mode="styling">
+    <xsl:apply-templates select="fi:styling/@*" mode="styling"/>
+
+       <xsl:if test="@state = 'disabled'">
+               <xsl:attribute name="disabled">disabled</xsl:attribute>
+       </xsl:if>
+
+    <!--+ 
+        | @listbox-size needs to be handled separately as even if it is not
+        | specified some output (@size) must be generated.
+        +-->
+    <xsl:if test="self::fi:field[fi:selection-list][fi:styling/@list-type = 'listbox'] or
+                  self::fi:multivaluefield[not(fi:styling/@list-type = 'checkbox')]">
+      <xsl:variable name="size">
+        <xsl:value-of select="fi:styling/@listbox-size"/>
+        <xsl:if test="not(fi:styling/@listbox-size)">5</xsl:if>
+      </xsl:variable>
+      <xsl:attribute name="size">
+        <xsl:value-of select="$size"/>
+      </xsl:attribute>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template match="fi:styling/@*" mode="styling">
+    <xsl:copy-of select="."/>
+  </xsl:template>
+
+  <xsl:template match="fi:styling/@submit-on-change" mode="styling">
+    <xsl:if test=". = 'true'">
+      <xsl:attribute name="onchange">forms_submitForm(this)</xsl:attribute>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template match="fi:styling/@list-type | fi:styling/@list-orientation |
+                       fi:styling/@listbox-size | fi:styling/@format | fi:styling/@layout"
+                mode="styling">
+    <!--+
+        | Ignore marker attributes so they don't go into the resuling HTML.
+        +-->
+  </xsl:template>
+
+  <xsl:template match="fi:styling/@type" mode="styling">
+    <!--+ 
+        | Do we have a duplicate semantic usage of @type?
+        | @type is only a marker for the stylesheet in general, but some of the
+        | types must/should be in the HTML output too.
+        +-->
+    <xsl:variable name="validHTMLTypes"
+                  select="'text hidden checkbox radio password image reset submit'"/>
+    <xsl:if test="normalize-space(.) and
+                  contains(concat(' ', $validHTMLTypes, ' '), concat(' ', ., ' '))">
+      <xsl:copy-of select="."/>
+    </xsl:if>
+  </xsl:template>
+
+  <!--+
+      |
+      +-->
+  <xsl:template match="fi:validation-message">
+    <a href="#" class="forms-validation-message" onclick="alert('{normalize-space(.)}');return false;">&#160;!&#160;</a>
+  </xsl:template>
+
+  <!--+
+      | Hidden fi:field : produce input with type='hidden'
+      +-->
+  <xsl:template match="fi:field[fi:styling/@type='hidden']" priority="2">
+    <input type="hidden" name="{@id}" id="{@id}" value="{fi:value}">
+      <xsl:apply-templates select="." mode="styling"/>
+    </input>
+  </xsl:template>
+
+  <!--+
+      | fi:field with a selection list and @list-type 'radio' : produce
+      | radio-buttons oriented according to @list-orientation
+      | ("horizontal" or "vertical" - default)
+      +-->
+  <xsl:template match="fi:field[fi:selection-list][fi:styling/@list-type='radio']" priority="2">
+    <xsl:variable name="id" select="@id"/>
+    <xsl:variable name="value" select="fi:value"/>
+    <xsl:variable name="vertical" select="string(fi:styling/@list-orientation) != 'horizontal'"/>
+    <xsl:choose>
+      <xsl:when test="$vertical">
+        <table cellpadding="0" cellspacing="0" border="0" title="{fi:hint}">
+          <xsl:for-each select="fi:selection-list/fi:item">
+            <tr>
+              <td>
+                <input type="radio" id="{generate-id()}" name="{$id}" value="{@value}">
+                  <xsl:if test="@value = $value">
+                    <xsl:attribute name="checked">checked</xsl:attribute>
+                  </xsl:if>
+                  <xsl:apply-templates select="../.." mode="styling"/>
+                </input>
+              </td>
+              <td>
+                <xsl:apply-templates select="." mode="label">
+                  <xsl:with-param name="id" select="generate-id()"/>
+                </xsl:apply-templates>
+              </td>
+              <xsl:if test="position() = 1">
+                <td rowspan="{count(../fi:item)}">
+                  <xsl:apply-templates select="../.." mode="common"/>
+                </td>
+              </xsl:if>
+            </tr>
+          </xsl:for-each>
+        </table>
+      </xsl:when>
+      <xsl:otherwise>
+        <span title="{fi:hint}">
+          <xsl:for-each select="fi:selection-list/fi:item">
+            <input type="radio" id="{generate-id()}" name="{$id}" value="{@value}">
+              <xsl:if test="@value = $value">
+                <xsl:attribute name="checked">checked</xsl:attribute>
+              </xsl:if>
+              <xsl:apply-templates select="../.." mode="styling"/>
+            </input>
+            <xsl:apply-templates select="." mode="label">
+              <xsl:with-param name="id" select="generate-id()"/>
+            </xsl:apply-templates>
+          </xsl:for-each>
+        </span>
+        <xsl:apply-templates select="." mode="common"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <!--+
+      | fi:field with a selection list (not 'radio' style)
+      | Rendering depends on the attributes of fi:styling :
+      | - if @list-type is "listbox" : produce a list box with @listbox-size visible
+      |   items (default 5)
+      | - otherwise, produce a dropdown menu
+      +-->
+  <xsl:template match="fi:field[fi:selection-list]" priority="1">
+    <xsl:variable name="value" select="fi:value"/>
+
+    <!-- dropdown or listbox -->
+    <select title="{fi:hint}" id="{@id}" name="{@id}">
+      <xsl:apply-templates select="." mode="styling"/>
+      <xsl:for-each select="fi:selection-list/fi:item">
+        <option value="{@value}">
+          <xsl:if test="@value = $value">
+            <xsl:attribute name="selected">selected</xsl:attribute>
+          </xsl:if>
+          <xsl:copy-of select="fi:label/node()"/>
+        </option>
+      </xsl:for-each>
+    </select>
+    <xsl:apply-templates select="." mode="common"/>
+  </xsl:template>
+
+  <!--+
+      | fi:field with a selection list and @type 'output'
+      +-->
+  <xsl:template match="fi:field[fi:selection-list][fi:styling/@type='output']" priority="3">
+    <xsl:variable name="value" select="fi:value"/>
+    <xsl:variable name="selected" select="fi:selection-list/fi:item[@value = $value]"/>
+    <xsl:choose>
+      <xsl:when test="$selected/fi:label">
+        <xsl:copy-of select="$selected/fi:label/node()"/>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:value-of select="$value"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <!--+
+      | fi:field with @type 'textarea'
+      +-->
+  <xsl:template match="fi:field[fi:styling/@type='textarea']">
+    <textarea id="{@id}" name="{@id}" title="{fi:hint}">
+      <xsl:apply-templates select="." mode="styling"/>
+      <!-- remove carriage-returns (occurs on certain versions of IE and doubles linebreaks at each submit) -->
+      <xsl:copy-of select="translate(fi:value/node(), '&#13;', '')"/>
+    </textarea>
+    <xsl:apply-templates select="." mode="common"/>
+  </xsl:template>
+
+  <!--+
+      | fi:field with @type 'output' and fi:output are both rendered as text
+      +-->
+  <xsl:template match="fi:output | fi:field[fi:styling/@type='output']" priority="2">
+    <xsl:copy-of select="fi:value/node()"/>
+  </xsl:template>
+
+  <!--+
+      | Labels for form elements.
+      +-->
+  <xsl:template match="fi:*" mode="label">
+    <xsl:param name="id" select="@id"/>
+    <label for="{$id}" title="{fi:hint}">
+      <xsl:copy-of select="fi:label/node()"/>
+    </label>
+  </xsl:template>
+
+  <!--+
+      | Labels for pure outputs must not contain <label/> as there is no element to point to.
+      +-->
+  <xsl:template match="fi:output | fi:field[fi:styling/@type='output'] | fi:messages | fi:field[fi:selection-list][fi:styling/@list-type='radio']" mode="label">
+    <xsl:copy-of select="fi:label/node()"/>
+  </xsl:template>
+
+  <!--+
+      | fi:booleanfield : produce a checkbox
+      | A hidden booleanfield is not a checkbox, so 'value' contains 
+      | the value and not the checked attribute
+      +-->
+  <xsl:template match="fi:booleanfield">
+    <input id="{@id}" type="checkbox" value="true" name="{@id}" title="{fi:hint}">
+      <xsl:apply-templates select="." mode="styling"/>
+      <xsl:choose>
+        <xsl:when test="./fi:styling[@type='hidden']">
+          <xsl:if test="fi:value = 'false'">
+            <xsl:attribute name="value">false</xsl:attribute>
+          </xsl:if>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:if test="fi:value = 'true'">
+            <xsl:attribute name="checked">checked</xsl:attribute>
+          </xsl:if>
+        </xsl:otherwise>
+      </xsl:choose>
+    </input>
+    <xsl:apply-templates select="." mode="common"/>
+  </xsl:template>
+
+  <!--+
+      | fi:booleanfield with @type 'output' : rendered as text
+      +-->
+  <xsl:template match="fi:booleanfield[fi:styling/@type='output']">
+    <xsl:choose>
+      <xsl:when test="fi:value = 'true'">
+        yes
+      </xsl:when>
+      <xsl:otherwise>
+        no
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <!--+
+      | fi:action
+      +-->
+  <xsl:template match="fi:action">
+    <input id="{@id}" type="submit" name="{@id}" title="{fi:hint}">
+      <xsl:attribute name="value"><xsl:value-of select="fi:label/node()"/></xsl:attribute>
+      <xsl:apply-templates select="." mode="styling"/>
+    </input>
+  </xsl:template>
+
+  <!--+
+      | fi:continuation-id : produce a hidden "continuation-id" input
+      +-->
+  <xsl:template match="fi:continuation-id">
+    <xsl:variable name="name">
+      <xsl:value-of select="@name"/>
+      <xsl:if test="not(@name)">continuation-id</xsl:if>
+    </xsl:variable>
+    <div style="display: none;">
+      <input name="{$name}" type="hidden" value="{.}"/>
+    </div>
+  </xsl:template>
+
+  <!--+
+      | fi:multivaluefield : produce a list of checkboxes
+      +-->
+  <xsl:template match="fi:multivaluefield[fi:styling/@list-type='checkbox']">
+    <xsl:variable name="id" select="@id"/>
+    <xsl:variable name="values" select="fi:values/fi:value/text()"/>
+
+    <span title="{fi:hint}">
+      <xsl:for-each select="fi:selection-list/fi:item">
+        <xsl:variable name="value" select="@value"/>
+        <input id="{generate-id()}" type="checkbox" value="{@value}" name="{$id}">
+          <xsl:if test="$values[. = $value]">
+            <xsl:attribute name="checked">checked</xsl:attribute>
+          </xsl:if>
+        </input>
+        <xsl:apply-templates select="." mode="label">
+          <xsl:with-param name="id" select="generate-id()"/>
+        </xsl:apply-templates>
+        <br/>
+      </xsl:for-each>
+    </span>
+    <xsl:apply-templates select="." mode="common"/>
+  </xsl:template>
+
+  <!--+
+      | fi:multivaluefield : produce a multiple-selection list
+      +-->
+  <xsl:template match="fi:multivaluefield">
+    <xsl:variable name="id" select="@id"/>
+    <xsl:variable name="values" select="fi:values/fi:value/text()"/>
+
+    <span title="{fi:hint}">
+      <select id="{@id}" name="{$id}" multiple="multiple">
+        <xsl:apply-templates select="." mode="styling"/>
+        <xsl:for-each select="fi:selection-list/fi:item">
+          <xsl:variable name="value" select="@value"/>
+          <option value="{$value}">
+            <xsl:if test="$values[. = $value]">
+              <xsl:attribute name="selected">selected</xsl:attribute>
+            </xsl:if>
+            <xsl:copy-of select="fi:label/node()"/>
+          </option>
+        </xsl:for-each>
+      </select>
+    </span>
+    <xsl:apply-templates select="." mode="common"/>
+  </xsl:template>
+
+  <!--+
+      | fi:upload
+      +-->
+  <xsl:template match="fi:upload">
+    <xsl:choose>
+      <xsl:when test="fi:value">
+        <!-- Has a value (filename): display it with a change button -->
+        <span title="{fi:hint}">
+          <xsl:text>[</xsl:text>
+          <xsl:value-of select="fi:value"/>
+          <xsl:text>] </xsl:text>
+          <input type="button" id="{@id}" name="{@id}" value="..." onclick="forms_submitForm(this)"/>
+        </span>
+      </xsl:when>
+      <xsl:otherwise>
+        <input type="file" id="{@id}" name="{@id}" title="{fi:hint}" accept="{@mime-types}">
+          <xsl:apply-templates select="." mode="styling"/>
+        </input>
+      </xsl:otherwise>
+    </xsl:choose>
+    <xsl:apply-templates select="." mode="common"/>
+  </xsl:template>
+
+  <!--+
+      | fi:repeater
+      +-->
+  <xsl:template match="fi:repeater">
+    <input type="hidden" name="{@id}.size" value="{@size}"/>
+    <table border="1">
+      <tr>
+        <xsl:for-each select="fi:headings/fi:heading">
+          <th><xsl:value-of select="."/></th>
+        </xsl:for-each>
+      </tr>
+      <xsl:apply-templates select="fi:repeater-row"/>
+    </table>
+  </xsl:template>
+
+  <!--+
+      | fi:repeater-row
+      +-->
+  <xsl:template match="fi:repeater-row">
+    <tr>
+      <xsl:for-each select="*">
+        <td>
+          <xsl:apply-templates select="."/>
+        </td>
+      </xsl:for-each>
+    </tr>
+  </xsl:template>
+
+  <!--+
+      | fi:repeater-size
+      +-->
+  <xsl:template match="fi:repeater-size">
+    <input type="hidden" name="{@id}.size" value="{@size}"/>
+  </xsl:template>
+
+  <!--+
+      | fi:form-template|fi:form-generated 
+      +-->
+  <xsl:template match="fi:form-template|fi:form-generated">
+    <form>
+      <xsl:copy-of select="@*"/>
+      <xsl:attribute name="onsubmit">forms_onsubmit(); <xsl:value-of select="@onsubmit"/></xsl:attribute>
+      <!-- hidden field to store the submit id -->
+      <div><input type="hidden" name="forms_submit_id"/></div>
+      <xsl:apply-templates/>
+      
+      <!-- TODO: consider putting this in the xml stream from the generator? -->
+      <xsl:if test="self::fi:form-generated">
+        <input type="submit"/>
+      </xsl:if>
+    </form>
+  </xsl:template>
+
+  <!--+
+      | fi:form
+      +-->
+  <xsl:template match="fi:form">
+    <table border="1">
+      <xsl:for-each select="fi:widgets/*">
+        <tr>
+          <xsl:choose>
+            <xsl:when test="self::fi:repeater">
+              <td colspan="2">
+                <xsl:apply-templates select="."/>
+              </td>
+            </xsl:when>
+            <xsl:when test="self::fi:booleanfield">
+              <td>&#160;</td>
+              <td>
+                <xsl:apply-templates select="."/>
+                <xsl:text> </xsl:text>
+                <xsl:apply-templates select="." mode="label"/>
+              </td>
+            </xsl:when>
+            <xsl:otherwise>
+              <td>
+                <xsl:apply-templates select="." mode="label"/>
+              </td>
+              <td>
+                <xsl:apply-templates select="."/>
+              </td>
+            </xsl:otherwise>
+          </xsl:choose>
+        </tr>
+      </xsl:for-each>
+    </table>
+  </xsl:template>
+
+  <xsl:template match="fi:aggregatefield">
+    <input id="{@id}" name="{@id}" value="{fi:value}" title="{fi:hint}">
+      <xsl:apply-templates select="." mode="styling"/>
+    </input>
+    <xsl:apply-templates select="." mode="common"/>
+  </xsl:template>
+
+  <xsl:template match="fi:messages">
+    <xsl:if test="fi:message">
+      <xsl:apply-templates select="." mode="label"/>:
+      <ul>
+        <xsl:for-each select="fi:message">
+          <li><xsl:apply-templates/></li>
+        </xsl:for-each>
+      </ul>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template match="fi:validation-errors">
+    <xsl:variable name="header">
+      <xsl:choose>
+        <xsl:when test="header">
+          <xsl:copy-of select="header"/>
+        </xsl:when>
+        <xsl:otherwise>
+          <p class="forms-validation-errors">The following errors have been detected (marked with !):</p>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <xsl:variable name="footer">
+      <xsl:choose>
+        <xsl:when test="footer">
+          <xsl:copy-of select="footer"/>
+        </xsl:when>
+        <xsl:otherwise>
+          <p class="forms-validation-errors">Please, correct them and re-submit the form.</p>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <xsl:variable name="messages" select="ancestor::fi:form-template//fi:validation-message"/>
+    <xsl:if test="$messages">
+      <xsl:copy-of select="$header"/>
+      <ul>
+        <xsl:for-each select="$messages">
+          <li class="forms-validation-error">
+            <xsl:variable name="label">
+              <xsl:apply-templates select=".." mode="label"/>
+            </xsl:variable>
+            <xsl:if test="$label">
+              <xsl:copy-of select="$label"/><xsl:text>: </xsl:text>
+            </xsl:if>
+            <xsl:value-of select="."/>
+          </li>
+        </xsl:for-each>
+      </ul>
+      <xsl:copy-of select="$footer"/>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template match="@*|node()" priority="-1">
+    <xsl:copy>
+      <xsl:apply-templates select="@*|node()"/>
+    </xsl:copy>
+  </xsl:template>
+
+</xsl:stylesheet>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/forms-htmlarea-styling.xsl b/Open-ILS/src/extras/authcon/auth/resources/forms-htmlarea-styling.xsl
new file mode 100644 (file)
index 0000000..c832925
--- /dev/null
@@ -0,0 +1,69 @@
+<?xml version="1.0"?>
+<!--
+  Copyright 1999-2004 The Apache Software Foundation
+
+  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.
+-->
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:fi="http://apache.org/cocoon/forms/1.0#instance"
+                exclude-result-prefixes="fi">
+  <!--+
+      | This stylesheet is designed to be included by 'forms-advanced-styling.xsl'.
+      +-->
+
+  <!-- Location of the resources directory, where JS libs and icons are stored -->
+  <xsl:param name="resources-uri">resources</xsl:param>
+  <xsl:param name="htmlarea-lang">en</xsl:param>
+
+  <xsl:template match="head" mode="forms-htmlarea">
+    <script type="text/javascript">
+      _editor_url = "<xsl:value-of select="concat($resources-uri, '/htmlarea/')"/>";
+      _editor_lang = "<xsl:value-of select="$htmlarea-lang"/>";
+    </script>
+    <script type="text/javascript" src="{$resources-uri}/htmlarea/htmlarea.js"></script>
+  </xsl:template>
+
+  <xsl:template match="body" mode="forms-htmlarea"/>
+
+  <!--+
+      | fi:field with @type 'htmlarea'
+      +-->
+  <xsl:template match="fi:field[fi:styling[@type='htmlarea']]">
+    <textarea id="{@id}" name="{@id}" title="{fi:hint}">
+      <xsl:apply-templates select="." mode="styling"/>
+      <!-- remove carriage-returns (occurs on certain versions of IE and doubles linebreaks at each submit) -->
+      <xsl:apply-templates select="fi:value/node()" mode="htmlarea-copy"/>
+    </textarea>
+    <xsl:apply-templates select="." mode="common"/>
+    <xsl:choose>
+      <xsl:when test="fi:styling/initFunction">
+        <script language="JavaScript"><xsl:value-of select="fi:styling/initFunction"/>('<xsl:value-of select="@id"/>');</script>
+      </xsl:when>
+      <xsl:otherwise>
+        <script type="text/javascript">HTMLArea.replace('<xsl:value-of select="@id"/>');</script>        
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="@*|*" mode="htmlarea-copy">
+    <xsl:copy>
+      <xsl:apply-templates select="@*|node()" mode="htmlarea-copy"/>
+    </xsl:copy>
+  </xsl:template>
+
+  <xsl:template match="text()" mode="htmlarea-copy">
+    <xsl:copy-of select="translate(., '&#13;', '')"/>
+  </xsl:template>
+
+</xsl:stylesheet>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/forms-lib.js b/Open-ILS/src/extras/authcon/auth/resources/forms-lib.js
new file mode 100644 (file)
index 0000000..6b7340a
--- /dev/null
@@ -0,0 +1,195 @@
+/*\r
+* Copyright 1999-2004 The Apache Software Foundation\r
+*\r
+* Licensed under the Apache License, Version 2.0 (the "License");\r
+* you may not use this file except in compliance with the License.\r
+* You may obtain a copy of the License at\r
+*\r
+*     http://www.apache.org/licenses/LICENSE-2.0\r
+*\r
+* Unless required by applicable law or agreed to in writing, software\r
+* distributed under the License is distributed on an "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+* See the License for the specific language governing permissions and\r
+* limitations under the License.\r
+*/\r
+/**\r
+ * Runtime JavaScript library for Cocoon forms.\r
+ *\r
+ * @author <a href="http://www.apache.org/~sylvain/">Sylvain Wallez</a>\r
+ * @version CVS $Id: forms-lib.js 57536 2004-11-12 18:33:30Z sylvain $\r
+ */\r
+\r
+// Handlers that are to be called in the document's "onload" event\r
+var forms_onloadHandlers = new Array();\r
+\r
+function forms_onload() {\r
+    for (var i = 0; i < forms_onloadHandlers.length; i++) {\r
+        forms_onloadHandlers[i].forms_onload();\r
+    }\r
+    // Clear it (we no more need them)\r
+    forms_onloadHandlers = null;\r
+}\r
+\r
+// Handlers that are to be called in form's "onsubmit" event\r
+//FIXME: this single var implies only one form per page, and needs to be\r
+//       visited if we decide to support several forms per page.\r
+var forms_onsubmitHandlers = new Array();\r
+\r
+function forms_onsubmit() {\r
+    if (forms_onsubmitHandlers == null) {\r
+        //alert("onsubmit called twice!");\r
+    }\r
+\r
+    for (var i = 0; i < forms_onsubmitHandlers.length; i++) {\r
+        forms_onsubmitHandlers[i].forms_onsubmit();\r
+    }\r
+    // clear it\r
+    forms_onsubmitHandlers = null;\r
+}\r
+\r
+/**\r
+ * Submit the form containing an element, also storing in the hidden\r
+ * 'forms_submit_id' field the name of the element which triggered the submit.\r
+ */\r
+function forms_submitForm(element, name) {\r
+    if (name == undefined) {\r
+        name = element.name;\r
+    }\r
+    \r
+    var form = forms_getForm(element);\r
+    if (form == null) {\r
+        alert("Cannot find form for " + element);\r
+    } else {\r
+        form["forms_submit_id"].value = name;\r
+        // FIXME: programmatically submitting the form doesn't trigger onsubmit ? (both in IE and Moz)\r
+        forms_onsubmit();\r
+        form.submit();\r
+    }\r
+}\r
+\r
+/**\r
+ * Crawl the parents of an element up to finding a form.\r
+ */\r
+function forms_getForm(element) {\r
+    while(element != null && element.tagName != "FORM") {\r
+        element = element.parentNode;\r
+    }\r
+    return element;\r
+}\r
+\r
+/**\r
+ * Move a named element as an immediate child of the <body> element.\r
+ * This is required for help popups inside <wi:group> tabs. The reason is that CSS positioning\r
+ * properties ("left" and "top") on a block with a "position: absolute" are actually relative to\r
+ * the nearest ancestor that has a position of "absolute", "relative" or "fixed".\r
+ * See http://www.w3.org/TR/CSS21/visudet.html#containing-block-details $4\r
+ */\r
+\r
+function forms_moveInBody(element) {\r
+    element.parentNode.removeChild(element);\r
+    document.body.appendChild(element);\r
+}\r
+\r
+/**\r
+ * Create a popup window for a named element.\r
+ *\r
+ * @param id the ID of the element to make a popup with.\r
+ */\r
+function forms_createPopupWindow(id) {\r
+    var result = new PopupWindow(id);\r
+    result.autoHide();\r
+    // add to onload handlers\r
+    result.forms_id = id;\r
+    result.forms_onload = function() {\r
+        forms_moveInBody(document.getElementById(this.forms_id));\r
+    }\r
+    forms_onloadHandlers.push(result);\r
+    return result;\r
+}\r
+\r
+\r
+function forms_createOptionTransfer(id, submitOnChange) {\r
+    var result = new OptionTransfer(id + ".unselected", id);\r
+    result.setAutoSort(true);\r
+    // add to onload handlers\r
+    result.forms_id = id;\r
+    result.forms_onload = function() {\r
+        var form = forms_getForm(document.getElementById(this.forms_id));\r
+        this.init(form);\r
+        sortSelect(this.left);\r
+        sortSelect(this.right);\r
+    }\r
+    result.submitOnChange = submitOnChange;\r
+    result.forms_transferLeft = function() {\r
+        this.transferLeft();\r
+        if (this.submitOnChange) {\r
+            forms_submitForm(document.getElementById(this.forms_id));\r
+        }\r
+    }\r
+    result.forms_transferRight = function() {\r
+        this.transferRight();\r
+        if (this.submitOnChange) {\r
+            forms_submitForm(document.getElementById(this.forms_id));\r
+        }\r
+    }\r
+    result.forms_transferAllLeft = function() {\r
+        this.transferAllLeft();\r
+        if (this.submitOnChange) {\r
+            forms_submitForm(document.getElementById(this.forms_id));\r
+        }\r
+    };\r
+    result.forms_transferAllRight = function() {\r
+        this.transferAllRight();\r
+        if (this.submitOnChange) {\r
+            forms_submitForm(document.getElementById(this.forms_id));\r
+        }\r
+    };\r
+    forms_onloadHandlers.push(result);\r
+    \r
+    // add to onsubmit handlers\r
+    result.forms_onsubmit = function() {\r
+        // Select all options in the "selected" list to that\r
+        // its values are sent.\r
+        selectAllOptions(this.right);\r
+    }\r
+    forms_onsubmitHandlers.push(result);\r
+    return result;\r
+}\r
+\r
+\r
+/**\r
+ * Show a tab in a <wi:group>\r
+ *\r
+ * @param tabgroup (string) name of the <wi:group>\r
+ * @param idx (integer) index of the selected tab\r
+ * @param length (integer) total number of tabs\r
+ * @param state (string, optional) name of the input storing the tabgroup state\r
+ */\r
+function forms_showTab(tabgroup, idx, length, state) {\r
+    // Change state value\r
+    if (state.length > 0) {\r
+        document.forms[0][state].value = idx;\r
+    }\r
+    for (var i = 0; i < length; i++) {\r
+        // Change tab status (selected/unselected)\r
+        var tab = document.getElementById(tabgroup + "_tab_" + i);\r
+        if (tab != null) {\r
+            tab.className = (i == idx) ? 'forms-tab forms-activeTab': 'forms-tab';\r
+        }\r
+        // Change tab content visibilty\r
+        var tabitems = document.getElementById(tabgroup + "_items_" + i);\r
+        if (tabitems != null) {\r
+            tabitems.style.display = (i == idx) ? '' : 'none';\r
+            // execute event handler if any\r
+            if (i == idx &&\r
+                    window.onTabShownHandlers != null &&\r
+                    window.onTabShownHandlers[tabgroup] != null) {\r
+                var onShowHandler = window.onTabShownHandlers[tabgroup][tabgroup + "_items_" + i];\r
+                if (onShowHandler != null) {\r
+                    eval(onShowHandler);\r
+                }\r
+            }\r
+        }\r
+    }\r
+}
\ No newline at end of file
diff --git a/Open-ILS/src/extras/authcon/auth/resources/forms-page-styling.xsl b/Open-ILS/src/extras/authcon/auth/resources/forms-page-styling.xsl
new file mode 100644 (file)
index 0000000..de66576
--- /dev/null
@@ -0,0 +1,353 @@
+<?xml version="1.0"?>
+<!--
+  Copyright 1999-2004 The Apache Software Foundation
+
+  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.
+-->
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:fi="http://apache.org/cocoon/forms/1.0#instance"
+                exclude-result-prefixes="fi">
+  <!--+
+      | This stylesheet is designed to be included by 'forms-samples-styling.xsl'.
+      +-->
+  <xsl:template match="head" mode="forms-page">
+    <!--+ 'forms-page-styling.xsl' relies on 'forms-field-styling.xsl' for the
+        | inclusion of the correct JS and CSS files. To fix it, we have to
+        | separate the page specific parts into their own files.
+        +-->
+  </xsl:template>
+
+  <xsl:template match="body" mode="forms-page"/>
+
+  <!--
+    fi:group : default is to enclose items in a div
+  -->
+  <xsl:template match="fi:group">
+    <div title="{fi:hint}">
+      <xsl:copy-of select="@*"/>
+      <xsl:apply-templates mode="group-layout" select="."/>
+    </div>
+  </xsl:template>
+
+  <!--
+    fi:group of type tabs
+  -->
+  <xsl:template match="fi:group[fi:styling/@type='tabs']">
+    <!-- find the currently selected tab.
+         Thoughts still needed here, such as autogenerating a field in the
+         forms transformer to hold this state.
+    -->
+    <xsl:variable name="active">
+      <xsl:variable name="value" select="normalize-space(fi:state/fi:*/fi:value)"/>
+      <xsl:choose>
+        <xsl:when test="$value">
+          <xsl:value-of select="$value"/>
+        </xsl:when>
+        <xsl:otherwise>0</xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <!-- copy the "state-widget" attribute for use in for-each -->
+    <xsl:variable name="state-widget" select="fi:state/fi:*/@id"/>
+    <xsl:variable name="id" select="generate-id()"/>
+
+    <div id="{$id}" title="{fi:hint}">
+      <!-- add an hidden input for the state -->
+      <xsl:if test="$state-widget">
+        <input type="hidden" name="{$state-widget}" value="{$active}"/>
+      </xsl:if>
+      <!-- div containing the tabs -->
+      <div class="forms-tabArea">
+        <xsl:for-each select="fi:items/fi:*">
+          <xsl:variable name="pos" select="position() - 1"/>
+          <span id="{$id}_tab_{$pos}" onclick="forms_showTab('{$id}', {$pos}, {last()}, '{$state-widget}')">
+            <xsl:attribute name="class">
+              <xsl:text>forms-tab</xsl:text>
+              <xsl:if test="$active = $pos"> forms-activeTab</xsl:if>
+            </xsl:attribute>
+            <xsl:copy-of select="fi:label/node()"/>
+            <xsl:if test="fi:items/*//fi:validation-message">
+              <span class="forms-validation-message">&#160;!&#160;</span>
+            </xsl:if>
+          </span>
+        </xsl:for-each>
+      </div>
+      <!-- a div for each of the items -->
+      <xsl:for-each select="fi:items/fi:*">
+        <xsl:variable name="pos" select="position() - 1"/>
+        <div class="forms-tabContent" id="{$id}_items_{$pos}">
+          <xsl:if test="$active != $pos">
+            <xsl:attribute name="style">display:none</xsl:attribute>
+          </xsl:if>
+          <xsl:apply-templates select="."/>
+        </div>
+      </xsl:for-each>
+    </div>
+    <!-- The tabbed elements can have an attribute formsOnShow containing some javascript to be executed
+         when a tab gets shown. -->
+    <script type="text/javascript">
+      if (window.onTabShownHandlers == undefined)
+        window.onTabShownHandlers = new Object();
+      var currentHandlers = new Object();
+      var initialHandler = null;
+      window.onTabShownHandlers["<xsl:value-of select="$id"/>"] = currentHandlers;
+      <xsl:for-each select="fi:items/fi:*">
+        <xsl:variable name="pos" select="position() - 1"/>
+          <xsl:if test="@formsOnShow">
+            currentHandlers["<xsl:value-of select="concat($id, '_items_', $pos)"/>"] = "<xsl:value-of select="@formsOnShow"/>";
+            <xsl:if test="$active = $pos">
+               initialHandler = "<xsl:value-of select="@formsOnShow"/>";
+            </xsl:if>
+          </xsl:if>
+      </xsl:for-each>
+      if (initialHandler != null) {
+        eval(initialHandler);
+        initialHandler = null;
+      }
+    </script>
+  </xsl:template>
+
+  <!--
+    fi:group of type choice : a popup is used instead of tabs
+  -->
+  <xsl:template match="fi:group[fi:styling/@type='choice']">
+    <!-- find the currently selected tab.
+         Thoughts still needed here, such as autogenerating a field in the formstransformer
+         to hold this state.
+    -->
+    <xsl:variable name="active">
+      <xsl:variable name="value" select="normalize-space(fi:state/fi:*/fi:value)"/>
+      <xsl:choose>
+        <xsl:when test="$value">
+          <xsl:value-of select="$value"/>
+        </xsl:when>
+        <xsl:otherwise>0</xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <!-- copy the "state-widget" attribute for use in for-each -->
+    <xsl:variable name="state-widget" select="fi:state/fi:*/@id"/>
+    <xsl:variable name="id" select="generate-id()"/>
+
+    <fieldset id="{$id}">
+      <legend title="{fi:hint}">
+        <xsl:apply-templates select="fi:label/node()"/>
+        <select name="{$state-widget}" onchange="forms_showTab('{$id}', this.selectedIndex, {count(fi:items/*)}, '{$state-widget}')">
+          <xsl:for-each select="fi:items/fi:*">
+            <xsl:variable name="pos" select="position() - 1"/>
+            <option>
+              <xsl:attribute name="value">
+                <xsl:choose>
+                  <xsl:when test="fi:value">
+                    <xsl:value-of select="fi:value"/>
+                  </xsl:when>
+                  <xsl:otherwise>
+                    <xsl:value-of select="$pos"/>
+                  </xsl:otherwise>
+                </xsl:choose>
+              </xsl:attribute>
+              <xsl:if test="$active = $pos">
+                <xsl:attribute name="selected">selected</xsl:attribute>
+              </xsl:if>
+              <xsl:copy-of select="fi:label/node()"/>
+            </option>
+          </xsl:for-each>
+        </select>
+        <xsl:if test="fi:items/*//fi:validation-message">
+          <span class="forms-validation-message">&#160;!&#160;</span>
+        </xsl:if>
+      </legend>
+      <!-- a div for each of the items -->
+      <xsl:for-each select="fi:items/fi:*">
+        <xsl:variable name="pos" select="position() - 1"/>
+        <div id="{$id}_items_{$pos}">
+          <xsl:if test="$active != $pos">
+            <xsl:attribute name="style">display:none</xsl:attribute>
+          </xsl:if>
+          <xsl:apply-templates select="."/>
+        </div>
+      </xsl:for-each>
+    </fieldset>
+  </xsl:template>
+
+  <!--
+    fi:group of type fieldset : enclose items in a fieldset frame
+  -->
+  <xsl:template match="fi:group[fi:styling/@type='fieldset']">
+    <fieldset>
+      <xsl:apply-templates select="." mode="styling"/>
+      <legend title="{fi:hint}"><xsl:copy-of select="fi:label/node()"/></legend>
+      <xsl:apply-templates mode="group-layout" select="."/>
+    </fieldset>
+  </xsl:template>
+
+  <!--
+    Group items layout : default is no layout
+  -->
+  <xsl:template match="fi:group" mode="group-layout">
+    <xsl:apply-templates select="fi:items/*"/>
+  </xsl:template>
+
+  <!--
+    Column group items layout
+  -->
+  <xsl:template match="fi:group[fi:styling/@layout='column']" mode="group-layout">
+    <table border="0" summary="{fi:hint}">
+      <tbody>
+        <xsl:apply-templates select="fi:items/*" mode="group-column-content"/>
+      </tbody>
+    </table>
+  </xsl:template>
+
+  <!--
+    Default column layout : label above and input below
+  -->
+  <xsl:template match="fi:*" mode="group-column-content">
+    <tr>
+      <td><xsl:apply-templates select="." mode="label"/></td>
+    </tr>
+    <tr>
+      <td><xsl:apply-templates select="."/></td>
+    </tr>
+  </xsl:template>
+
+  <xsl:template match="fi:action" mode="group-column-content">
+    <tr>
+      <td><xsl:apply-templates select="."/></td>
+    </tr>
+  </xsl:template>
+
+  <!--
+    Columns group items layout
+  -->
+  <xsl:template match="fi:group[fi:styling/@layout='columns']" mode="group-layout">
+    <table border="0" summary="{fi:hint}">
+      <tbody>
+        <xsl:apply-templates select="fi:items/*" mode="group-columns-content"/>
+      </tbody>
+    </table>
+  </xsl:template>
+
+  <!--
+    Default columns layout : label left and input right
+  -->
+  <xsl:template match="fi:*" mode="group-columns-content">
+    <tr>
+      <td><xsl:apply-templates select="." mode="label"/></td>
+      <td><xsl:apply-templates select="."/></td>
+    </tr>
+  </xsl:template>
+
+  <!--
+    Row group items layout
+  -->
+  <xsl:template match="fi:group[fi:styling/@layout='row']" mode="group-layout">
+    <table border="0" summary="{fi:hint}">
+      <tbody>
+        <tr>
+          <xsl:apply-templates select="fi:items/*" mode="group-row-content"/>
+        </tr>
+      </tbody>
+    </table>
+  </xsl:template>
+
+  <!--
+    Default row layout : label left and input right
+  -->
+  <xsl:template match="fi:*" mode="group-row-content">
+    <td><xsl:apply-templates select="." mode="label"/></td>
+    <td><xsl:apply-templates select="."/></td>
+  </xsl:template>
+
+  <xsl:template match="fi:action" mode="group-row-content">
+    <td><xsl:apply-templates select="."/></td>
+  </xsl:template>
+  <!--
+    Rows group items layout
+  -->
+  <xsl:template match="fi:group[fi:styling/@layout='rows']" mode="group-layout">
+    <table border="0" summary="{fi:hint}">
+      <tbody>
+        <tr>
+          <xsl:apply-templates select="fi:items/*" mode="group-rows-labels"/>
+        </tr>
+        <tr>
+          <xsl:apply-templates select="fi:items/*" mode="group-rows-content"/>
+        </tr>
+      </tbody>
+    </table>
+  </xsl:template>
+
+  <!--
+    Default rows layout : label above and input below
+  -->
+  <xsl:template match="fi:*" mode="group-rows-labels">
+    <td><xsl:apply-templates select="." mode="label"/></td>
+  </xsl:template>
+
+  <xsl:template match="fi:action" mode="group-rows-labels">
+    <td>&#160;</td>
+  </xsl:template>
+
+  <xsl:template match="fi:*" mode="group-rows-content">
+    <td><xsl:apply-templates select="."/></td>
+  </xsl:template>
+
+  <!-- boolean field : checkbox and label on a single line -->
+  <xsl:template match="fi:booleanfield" mode="group-columns-content">
+    <tr>
+      <td colspan="2">
+        <xsl:apply-templates select="."/>
+        <xsl:apply-templates select="." mode="label"/>
+      </td>
+    </tr>
+  </xsl:template>
+
+  <!-- action : on a single line -->
+  <xsl:template match="fi:action" mode="group-columns-content">
+    <tr>
+      <td colspan="2"><xsl:apply-templates select="."/></td>
+    </tr>
+  </xsl:template>
+
+  <!-- any other element : on a single line -->
+  <xsl:template match="*" mode="group-columns-content">
+    <tr>
+      <td colspan="2"><xsl:apply-templates select="."/></td>
+    </tr>
+  </xsl:template>
+
+  <!-- double-list multivaluefield : lists under the label -->
+  <xsl:template match="fi:multivaluefield[fi:styling/@list-type='double-listbox']"
+                mode="group-columns-content">
+    <tr>
+      <td colspan="2"><xsl:apply-templates select="." mode="label"/></td>
+    </tr>
+    <tr>
+      <td colspan="2"><xsl:apply-templates select="."/></td>
+    </tr>
+  </xsl:template>
+
+  <!-- nested group -->
+  <xsl:template match="fi:group" mode="group-columns-content">
+    <tr>
+      <td colspan="2"><xsl:apply-templates select="."/></td>
+    </tr>
+  </xsl:template>
+
+  <xsl:template match="@*|node()" priority="-1">
+    <xsl:copy>
+      <xsl:apply-templates select="@*|node()"/>
+    </xsl:copy>
+  </xsl:template>
+
+</xsl:stylesheet>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/forms-samples-styling.xsl b/Open-ILS/src/extras/authcon/auth/resources/forms-samples-styling.xsl
new file mode 100644 (file)
index 0000000..67d8ec1
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+<!--
+  Copyright 1999-2004 The Apache Software Foundation
+
+  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.
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+  <!--+ Include styling stylesheets, one for the widgets, the other one for the
+      | page. As 'forms-advanced-field-styling.xsl' is a specialization of
+      | 'forms-field-styling.xsl' the latter one is imported there. If you don't
+      | want advanced styling of widgets, change it here!
+      | See xsl:include as composition and xsl:import as extension/inheritance.
+      +-->
+  <xsl:include href="forms-page-styling.xsl"/>
+  <xsl:include href="forms-advanced-field-styling.xsl"/>
+
+  <xsl:template match="head">
+    <head>
+      <xsl:apply-templates/>
+      <xsl:apply-templates select="." mode="forms-page"/>
+      <xsl:apply-templates select="." mode="forms-field"/>
+    </head>
+  </xsl:template>
+
+  <xsl:template match="body">
+    <body>
+      <!--+ !!! If template with mode 'forms-page' adds text or elements
+          |        template with mode 'forms-field' can no longer add attributes!!!
+          +-->
+      <xsl:apply-templates select="." mode="forms-page"/>
+      <xsl:apply-templates select="." mode="forms-field"/>
+      <xsl:apply-templates/>
+    </body>
+  </xsl:template>
+
+</xsl:stylesheet>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/forms.css b/Open-ILS/src/extras/authcon/auth/resources/forms.css
new file mode 100644 (file)
index 0000000..3a23ade
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+* Copyright 1999-2004 The Apache Software Foundation
+*
+* 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.
+*/
+.forms-tab {
+    background-color: white;
+    border: 1px solid black;
+    border-bottom-width: 0px;
+    padding: 2px 1em 2px 1em;
+    margin-right: 5px;
+    position: relative;
+    text-decoration: none;
+    top: -1px;
+    z-index: 1;
+    cursor: pointer;
+}
+
+.forms-tab.forms-activeTab {
+    font-weight: bold;
+    padding-top: 5px;
+    cursor: default;
+    z-index: 3;
+}
+
+.forms-tabContent {
+    background-color: white;
+    border: 1px solid black;
+    padding: 1em;
+    position: relative;
+    z-index: 2;
+}
+
+.forms-validation-message, a.forms-validation-message:link {
+    color: red;
+    font-weight: bold;
+}
+
+.forms-validation-errors {
+}
+
+.forms-validation-error {
+}
+
+.forms-field-required {
+       color:blue;
+    font-weight: bold;
+}
+
+.forms-help {
+    border-style: dotted;
+    border-width: 1px;
+    padding: 5px;
+    background-color:#FFFFC0; /* light yellow */
+    width: 200px; /* otherwise IE does a weird layout */
+    z-index:1000; /* must be higher than forms-tabContent */
+}
+
+.forms-doubleList select {
+    width: 150px;
+}
+
+.forms-doubleList input {
+    width: 40px;
+}
diff --git a/Open-ILS/src/extras/authcon/auth/resources/help.gif b/Open-ILS/src/extras/authcon/auth/resources/help.gif
new file mode 100644 (file)
index 0000000..5a16b0b
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/help.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/.project b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/.project
new file mode 100644 (file)
index 0000000..aea9a89
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>htmlarea</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+       </buildSpec>
+       <natures>
+       </natures>
+</projectDescription>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/ChangeLog b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/ChangeLog
new file mode 100644 (file)
index 0000000..8e18577
--- /dev/null
@@ -0,0 +1,1185 @@
+2004-02-17  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/el.js, plugins/ContextMenu/lang/el.js, plugins/TableOperations/lang/el.js:
+       updated headers
+
+       * lang/no.js: updated (thanks havardw)
+
+2004-02-09  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/EnterParagraphs/enter-paragraphs.js:
+       Plugin that enables Mozilla to create a <p> instead of <br /> at ENTER.
+       Code contributed by Adam Wright.
+
+       * htmlarea.js: code to call onKeyPress for plugins that define it
+       code that keeps single spaces as &nbsp;
+       (thanks to hipikat @ IT forums (Adam Wright))
+
+       * ChangeLog:
+       ChangeLog is acutally automatically generated so there's no point keep it in CVS
+
+2004-02-08  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: fixed possible bug
+
+       * images/ed_align_center.gif, images/ed_align_justify.gif, images/ed_align_left.gif, images/ed_align_right.gif, images/ed_blank.gif, images/ed_charmap.gif, images/ed_color_bg.gif, images/ed_color_fg.gif, images/ed_copy.gif, images/ed_custom.gif, images/ed_cut.gif, images/ed_delete.gif, images/ed_format_bold.gif, images/ed_format_italic.gif, images/ed_format_strike.gif, images/ed_format_sub.gif, images/ed_format_sup.gif, images/ed_format_underline.gif, images/ed_help.gif, images/ed_hr.gif, images/ed_html.gif, images/ed_image.gif, images/ed_indent_less.gif, images/ed_indent_more.gif, images/ed_left_to_right.gif, images/ed_link.gif, images/ed_list_bullet.gif, images/ed_list_num.gif, images/ed_paste.gif, images/ed_redo.gif, images/ed_right_to_left.gif, images/ed_save.gif, images/ed_show_border.gif, images/ed_splitcel.gif, images/ed_undo.gif, images/fullscreen_maximize.gif, images/fullscreen_minimize.gif, images/insert_table.gif, images/ed_about.gif:
+       optimized images (thanks to Alexander Kandzior and OpenCMS group)
+
+2004-02-01  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * project-config.xml: release candidate 1
+
+       * release-notes.html: updated release notes
+
+       * examples/index.html, examples/makefile.xml:
+       added examples directory index
+
+       * release-notes.html: fix
+
+2004-01-31  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * makefile.xml: ensure correct file permissions
+
+       * plugins/SpellChecker/spell-check-logic.cgi, plugins/SpellChecker/spell-check-ui.html, plugins/SpellChecker/spell-check-ui.js:
+       spell checker now reports some document information (such as total number of
+       words, number of mispelled words, number of suggestions, etc)
+
+       * htmlarea.js: removed some custom attributes
+
+       * plugins/SpellChecker/spell-check-ui.js:
+       fixed bug (frame scroll in IE)
+
+2004-01-30  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * ChangeLog, release-notes.html: updated release notes, changelog
+
+       * plugins/SpellChecker/readme-tech.html:
+       updated text about Aspell Unicode support
+
+       * plugins/SpellChecker/spell-check-style.css: - lorem ipsum
+
+       * plugins/SpellChecker/spell-check-logic.cgi: - optimization
+
+       * plugins/SpellChecker/spell-check-logic.cgi:
+       - bugfix (removed <spellchecker> tags)
+
+       * plugins/SpellChecker/spell-check-logic.cgi:
+       bleah.. this version seems to be safer; no mo' HTML::Parser; DOM rulz.
+
+       * plugins/SpellChecker/spell-check-logic.cgi:
+       seems to be better now :-\  hell knows how perl & unicode works :-/
+
+       * plugins/SpellChecker/spell-check-logic.cgi, plugins/SpellChecker/spell-check-ui.js:
+       - big performance improvement (suggestion is now passed only once for each
+         mispelled word)
+       - bugs fixed (text already corrected in Unicode is now correctly decoded)
+
+       * plugins/SpellChecker/lang/en.js: - added word "Revert"
+
+       * plugins/SpellChecker/spell-checker.js: - lorem ipsum
+       - window is a bit higher now (450px)
+
+       * plugins/SpellChecker/spell-check-ui.js:
+       - fixed IE bug ("undefined is undefined or undefined", or something..)
+       - the highlighted word will now remain in view (window scrolls if necessary)
+       - functionality for "Revert"
+       - (tried to) eliminate some of the screen blinking in Mozilla
+       - select the current dictionary on first display
+
+       * plugins/SpellChecker/spell-check-ui.html:
+       added "Revert" button (reverts the current word to the mispelled original)
+
+       * plugins/SpellChecker/spell-check-style.css: *** empty log message ***
+
+       * plugins/SpellChecker/spell-check-logic.cgi:
+       - fixed (hopefully) unicode support (by the way, it seems that Aspell _does_
+         in fact know Unicode!!)
+       - remembers the selected dictionary in a cookie
+       - removed debug code
+
+2004-01-28  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * index.html: updated main page
+
+       * release-notes.html: updated release notes
+
+       * htmlarea.js: jscrunch-safe
+
+       * popups/about.html:
+       stop tab click event so that they don't get selected
+
+       * reference.html: some parts updated
+
+       * popups/about.html, examples/2-areas.html, examples/context-menu.html, examples/core.html, examples/css.html, examples/full-page.html, examples/fully-loaded.html, examples/spell-checker.html, examples/table-operations.html, plugins/SpellChecker/readme-tech.html, ChangeLog, dialog.js, htmlarea.js, index.html, license.txt, popupwin.js, release-notes.html:
+       ChangeLog updated; copyright years/info updated
+
+2004-01-27  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js:
+       Included an workaround for a strange IE problem: IE's getElementById can
+       return a field having the _name_ attribute equal to the searched ID, even if
+       it's not having any ID at all.  This can sometimes lead to taking a
+       different field (even if it's not a textarea) as the replacement field which
+       trashes the whole layout, look, feel, and functionality :-(  Need to say it
+       again, IE SUCKS.
+
+       Thanks goes to Mike Dick for the bug report and for the patch ;-)
+
+2004-01-18  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/SpellChecker/spell-check-ui.js:
+       fixed bug (thanks Bill Sechrist for report):
+       when you "ignore"-ed the last mispelled word, no changes were applied
+
+2004-01-16  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: border: 0px on body,html in pageStyle
+
+       * popups/about.html: report userAgent in plugins tab
+
+2004-01-12  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/ru.js: updated (thanks to Yulya Shtyryakova)
+
+2004-01-03  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/ContextMenu/lang/de.js: updated
+
+2004-01-02  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/ContextMenu/lang/de.js:
+       DE translation, thanks to Martin Jaggi
+
+2003-12-22  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/ee.js: Estonian translation
+
+2003-12-05  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: word cleaner: now it actually works ;-)
+
+       * plugins/ContextMenu/lang/el.js, lang/el.js, plugins/TableOperations/lang/el.js:
+       added Greek translation (thanks to Dimitris Glezos)
+
+       * htmlarea.js:
+       call an onGenerate handler, if found on the editor object
+
+       * popups/about.html, popups/popup.js: updated about box
+
+       * plugins/SpellChecker/spell-check-ui.js: *** empty log message ***
+
+       * plugins/ContextMenu/context-menu.js:
+       open the normal insert_link dialog on modify link
+
+2003-11-28  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.css: -moz-opacity got back
+
+       * popups/about.html: *** empty log message ***
+
+       * htmlarea.js: added Word cleaner code (thanks weeezl)
+       fixed the bug concerning the url of relative link/images
+
+2003-11-24  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/CSS/css.js:
+       allows updation of parent element's class (no span).  thanks goes to Michael (pepl @ IT forums)
+
+2003-11-22  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/ContextMenu/lang/nl.js, plugins/TableOperations/lang/nl.js:
+       translation thanks to mmcw /IT forums
+
+       * lang/nl.js: updated (thanks to mmcw /IT forums)
+
+2003-11-21  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * makefile.xml: added ChangeLog to project dist
+
+       * ChangeLog: Updated ChangeLog
+
+       * examples/context-menu.html, examples/fully-loaded.html, examples/pieng.png, index.html, plugins/ContextMenu/1.pl, plugins/ContextMenu/context-menu.js, plugins/ContextMenu/lang/en.js, plugins/ContextMenu/lang/makefile.xml, plugins/ContextMenu/makefile.xml, plugins/ContextMenu/menu.css, plugins/makefile.xml:
+       Added ContextMenu plugin (work sponsored by American Bible Society)
+
+2003-11-11  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/en.js, lang/ro.js: support for the link dialog
+
+       * plugins/FullPage/popups/docprop.html, popups/popup.js:
+       support for I18N of core dialogs, added function to select a value in a <select>, all dialogs close on ESC
+
+       * htmlarea.js:
+       support for insert link popup, minor bug-fix in Mozilla (catch exception)
+
+       * examples/fully-loaded.html:
+       workaround some IE problems (it appears that it's definitely better to wait half a second before generate()-ing the editor
+
+       * popups/link.html: allow ling target, title, edit link
+
+       * plugins/TableOperations/lang/no.js, lang/no.js:
+       Norwegian translation (thanks to Svein Sando)
+
+2003-11-10  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/es.js: fixed (thanks to Jorge)
+
+2003-11-07  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * popups/about.html:
+       changed to Unix encoding; Credits page needs to be redesigned
+
+2003-11-06  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/lt.js: Lithuanian translation, thanks to Jaroslav Satkevic
+
+2003-11-05  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/he.js: Hebrew language definition (thanks to Liron Newman)
+
+2003-11-04  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/vn.js: updated vietnamese translation, thanks to Nguyen Dinh Nam
+
+2003-11-03  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/nl.js: updated (thanks to ephemeros)
+
+       * images/ed_left_to_right.gif, images/ed_right_to_left.gif:
+       text direction icons
+
+       * htmlarea.js, lang/en.js:
+       implemented text direction support (LTR or RTL)
+       workaround for a serious bug in IE (looses selection? bleah..)
+
+2003-10-31  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * examples/2-areas.cgi, examples/2-areas.html:
+       added sample that demonstrates how to create more editors in the same page and form
+
+       * htmlarea.js:
+       - increased the initial timeout after creating the iframe
+       - apply the timeout to IE too (actually we need a better idea that will only
+         create the editor _after_ all images are loaded; it seems that IE has
+         serious problems about it: if HTMLArea is initialized while loading images,
+         the rest of images will never be loaded and functionality will miss [IE only])
+       - custom undo queue disabled by default as it's still buggy
+
+2003-10-28  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * popups/about.html: only loaded plugins
+
+       * plugins/CSS/css.js: copyright notices updated
+
+       * examples/core.html, examples/css.html, examples/full-page.html, examples/spell-checker.html, examples/table-operations.html:
+       updated to new style (load only htmlarea.js, define _editor_lang)
+
+       * dialog.js, htmlarea.js, popups/popup.js, popupwin.js:
+       copyright notices updated
+
+       * htmlarea.js: Text "Path: " back in the status bar
+
+       * popups/fullscreen.html:
+       correctly loads all scripts and registers plugins
+
+       * plugins/SpellChecker/spell-checker.js:
+       dropped config.editorURL in favor if _editor_url
+
+       * lang/en.js:
+       - IE sucks in full screen message (not yet used but might be if users
+         complain; I'm sick of IE, that sick that I will start charging 4 times more
+         for IE compatibility; I might get a ulcer because of it... no kiddin')
+
+       * htmlarea.js: - support _editor_lang
+       - loads all required files
+       - correct loading of plugins in full-screen mode
+       - config.editorURL was permanently dropped in favor of _editor_url
+
+       * popups/fullscreen.html, htmlarea.js:
+       config.editorURL removed, better handling of _editor_url
+
+2003-10-27  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * popups/fullscreen.html:
+       bugfix: setting the BASE tag to the caller document's URL so we have no other
+       problems like editor or button images not loading.  Ha HA! >:-)
+
+       * plugins/CSS/css.js:
+       CSS plugin drop-down boxes appear on the second toolbar line by default
+
+       * popupwin.js: added position for the opening window
+
+       * lang/en.js: Insert Image ==> Insert/Modify Image
+
+       * htmlarea.js:
+       - Insert Image command patched to allow modification of a current image, if
+         it's selected
+       - Correct handling of selection for IE (test for ControlRange object) which
+         fixes a lot of bugs (IMG elements is now present in Path, no more table
+         props failures when an IMG or floating element is selected, etc.)
+
+2003-10-25  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * popups/insert_image.html, htmlarea.js:
+       insert image can now modify the properties of an existing image
+
+       * htmlarea.js:
+       Cut/copy/paste -- show hint of where to find information to enable it in Gecko
+
+       * examples/core.html, examples/css.html, examples/full-page.html, examples/fully-loaded.html, examples/spell-checker.html, examples/table-operations.html:
+       removed @import url(../htmlarea.css) -- HTMLArea takes care of loading the CSS by itself how
+
+       * htmlarea.js:
+       bugfix: catched some exceptions that otherwise would have led Mozilla to crash
+       removed Path text from the statusbar
+
+       * htmlarea.js:
+       call onGenerate() for plugins that implement it; added loadStyle helper for easier stylesheet loading
+
+2003-10-24  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/FullPage/test.html, examples/css.html, examples/full-page.html:
+       removed unused code
+
+       * plugins/makefile.xml, plugins/CSS/lang/makefile.xml, plugins/CSS/makefile.xml:
+       CSS plugin added to distribution
+
+       * examples/custom.css, htmlarea.js: removed default styles
+
+       * popups/about.html:
+       fixed resizable window (Moz fix only, IE worked fine)
+
+       * plugins/CSS/css.js, plugins/CSS/lang/en.js, plugins/FullPage/full-page.js, examples/css.html, examples/custom.css, examples/fully-loaded.html:
+       added the CSS plugin (sponsored by www.miro.com.au)
+
+       * htmlarea.js:
+       bugfix: sometimes getHTML failed as root.tagName was undefined (for DocumentFragment nodes)
+
+       * project-config.xml: switching to CVS snapshot releases
+
+2003-10-23  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * examples/test.cgi: moved from ../
+
+       * test.cgi: moved to examples/
+
+       * makefile.xml: added examples subdir
+
+       * examples/makefile.xml: distribute example files
+
+       * examples/full-page.html: FullPage plugin demo
+
+       * examples/fully-loaded.html: added FullPage plugin
+
+       * index.html: added link to FullPage plugin demo
+
+       * examples/core.html, examples/fully-loaded.html, examples/spell-checker.html, examples/table-operations.html, popups/fullscreen.html, index.html:
+       fixed example files, added _editor_url (REQUIREDcvs -q update -d .), fixed problems with the full-screen editor
+
+       * examples/core.html, examples/fully-loaded.html, examples/spell-checker.html, examples/table-operations.html:
+       examples previously found in ../
+
+       * example-fully-loaded.html, example-spell-checker.html, example-table-operations.html, example.html:
+       moved to examples/
+
+       * popups/about.html: minor
+
+2003-10-18  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/si.js: Slovenian translation (thanks to Tomaz Kregar)
+
+2003-10-15  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/fr.js: updated French translation (thanks to Jonathan Ernst)
+
+2003-10-07  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/FullPage/full-page.js, plugins/FullPage/img/docprop.gif, plugins/FullPage/img/makefile.xml, plugins/FullPage/lang/en.js, plugins/FullPage/lang/makefile.xml, plugins/FullPage/lang/ro.js, plugins/FullPage/makefile.xml, plugins/FullPage/popups/docprop.html, plugins/FullPage/popups/makefile.xml, plugins/FullPage/test.html, plugins/makefile.xml:
+       FullPage plugin (allows configuring document properties)
+
+       * lang/en.js: fixed typo
+
+2003-10-06  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * popups/about.html: Released=>Compiled
+
+       * popups/about.html: plugins credits only in plugins page
+
+       * popups/popup.js: added ability to translate popup dialogs
+
+       * htmlarea.css:
+       small fix for Mozilla/XHTML mode (buttons have now correct size)
+
+       * plugins/SpellChecker/spell-checker.js, plugins/TableOperations/table-operations.js:
+       fixed plugin images paths
+
+       * htmlarea.js: fixed doctype support
+       fixed support for full page editing (did I mention that IE sucks?)
+       avoids retrieving the contenteditable tag for body (IE only)
+       fixed _colorToRgb function (returns '' for empty or null color)
+       fixed editor/plugin images paths
+
+       * popups/popup.js:
+       allow __dlg_init to resize the window to cover a certain element
+
+       * popups/fullscreen.html: save the doctype too in the new editor
+
+       * popupwin.js:
+       fixed bug: now functions correctly for absolute _editor_url
+
+2003-10-05  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js:
+       full page editing facility; better interface for plugins popup dialogs
+
+2003-10-03  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: calls the plugin update function, if supplied
+
+       * popups/insert_image.html:
+       added nice image preview (submitted by rickroot on the interactivetools
+       forums, thanks!)
+
+2003-10-02  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: implemented proprietary undo/redo system (still buggy)
+
+       * popups/about.html: no bold on tabs
+
+2003-10-01  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: undo/redo are removed only if IE and config.statusBar
+
+       * popups/about.html: larger about box
+
+       * htmlarea.js: registers the plugin instance too (where was my head?)
+
+       * htmlarea.js: registers the plugin instance too
+
+       * htmlarea.js: fixed bug: opening the help window from the right place
+
+       * htmlarea.js:
+       don't use eval to register new plugins (allows better plugin arguments handling)
+
+2003-09-29  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * project-config.xml: beta+CVS
+
+       * popups/about.html: more "space" between tabs
+
+       * popups/about.html: the coolest about box ;-)
+
+       * dialog.js, popups/insert_image.html, popups/insert_table.html, popups/popup.js, popups/select_color.html:
+       fixed popups display under IE/Win
+
+       * plugins/SpellChecker/spell-checker.js, plugins/TableOperations/table-operations.js, htmlarea.js:
+       plugins will now register information about themselves
+
+       * popups/popup.js:
+       fixed an infantile mistake ;-) (popup windows are now centered correctly in
+       Moz too)
+
+2003-09-28  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * makefile.xml: mason args not needed
+
+       * popups/about.html: better about box ;-)
+
+       * project-config.xml: version beta+
+
+       * htmlarea.js: support passing parameters to plugins
+
+       * plugins/TableOperations/lang/en.js, plugins/TableOperations/lang/ro.js, popups/about.html, lang/en.js, lang/lv.js, lang/ro.js, plugins/SpellChecker/lang/en.js, plugins/SpellChecker/lang/ro.js, plugins/SpellChecker/readme-tech.html, plugins/SpellChecker/spell-check-logic.cgi, plugins/SpellChecker/spell-check-ui.html, plugins/SpellChecker/spell-check-ui.js, plugins/SpellChecker/spell-checker.js, plugins/TableOperations/table-operations.js, release-notes.html, example-spell-checker.html, htmlarea.js, index.html, make-release.pl, reference.html:
+       updated links
+
+2003-09-27  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * popups/fullscreen.html: dont load null scripts ;-)
+
+       * htmlarea.js: undo/redo buttons removed for IE
+
+2003-09-25  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * images/ed_save.gif, images/ed_save.png: added save icon
+
+       * plugins/SpellChecker/lang/da.js: Danish translation available
+
+2003-09-19  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/SpellChecker/lang/de.js:
+       DE translation added (thanks to broxx.com)
+
+       * plugins/TableOperations/lang/da.js:
+       danish translation provided by Steen Sønderup
+
+       * plugins/TableOperations/lang/de.js:
+       DE translation provided by broxx.com
+
+       * lang/de.js: up-to-date by broxx.com
+
+2003-09-16  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/SpellChecker/lang/hu.js:
+       added Hungarian translation for the SpellChecker plugin
+
+2003-09-15  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/hu.js, plugins/TableOperations/lang/hu.js:
+       added Hungarian translation (thanks to Miklós Somogyi)
+
+2003-09-14  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/lv.js: added Latvian translation (thanks to Janis Klavins)
+
+2003-09-02  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js:
+       added helper function for removing stuff from the configuration toolbar
+
+       * popupwin.js:
+       fixed bug that prevented TableOperation popups to show up in IE
+
+2003-08-25  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: fixed status-bar behavior (can be hidden if desired)
+
+       * lang/es.js: fixed structure
+
+2003-08-21  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * popupwin.js:
+       bugfix: use _editor_url to allow the editor to be some place else
+
+2003-08-14  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/SpellChecker/lang/it.js: utf-8-ified
+
+       * lang/it.js: Italian translation updated (thanks to Fabio Rotondo)
+
+       * plugins/TableOperations/lang/it.js:
+       Italian translation, thanks to Fabio Rotondo
+
+2003-08-13  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/SpellChecker/lang/it.js:
+       Added Italian translation (thanks to Fabio Rotondo)
+
+2003-08-12  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/SpellChecker/lang/cz.js, plugins/TableOperations/lang/cz.js, lang/cz.js:
+       CZ translation
+
+       * htmlarea.js:
+       fixed bug when more HTMLAreas were present in the same <FORM> -- get each
+       one's text onsubmit. (thanks Fabio Rotondo for report and test case)
+
+2003-08-11  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * index.html: added brief installation notes
+
+2003-08-10  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * index.html, makefile.xml, release-notes.html:
+       added version/release to index.html
+
+       * lang/da.js, lang/de.js, lang/en.js, lang/es.js, lang/fi.js, lang/fr.js, lang/gb.js, lang/it.js, lang/ja-euc.js, lang/ja-jis.js, lang/ja-sjis.js, lang/ja-utf8.js, lang/makefile.xml, lang/nb.js, lang/nl.js, lang/pl.js, lang/pt_br.js, lang/ro.js, lang/ru.js, lang/se.js, lang/vn.js, plugins/SpellChecker/img/makefile.xml, plugins/SpellChecker/img/spell-check.gif, plugins/SpellChecker/lang/en.js, plugins/SpellChecker/lang/makefile.xml, plugins/SpellChecker/lang/ro.js, plugins/SpellChecker/makefile.xml, plugins/SpellChecker/readme-tech.html, plugins/SpellChecker/spell-check-logic.cgi, plugins/SpellChecker/spell-check-style.css, plugins/SpellChecker/spell-check-ui.html, plugins/SpellChecker/spell-check-ui.js, plugins/SpellChecker/spell-checker.js, plugins/TableOperations/img/cell-delete.gif, plugins/TableOperations/img/cell-insert-after.gif, plugins/TableOperations/img/cell-insert-before.gif, plugins/TableOperations/img/cell-merge.gif, plugins/TableOperations/img/cell-prop.gif, plugins/TableOperations/img/cell-split.gif, plugins/TableOperations/img/col-delete.gif, plugins/TableOperations/img/col-insert-after.gif, plugins/TableOperations/img/col-insert-before.gif, plugins/TableOperations/img/col-split.gif, plugins/TableOperations/img/makefile.xml, plugins/TableOperations/img/row-delete.gif, plugins/TableOperations/img/row-insert-above.gif, plugins/TableOperations/img/row-insert-under.gif, plugins/TableOperations/img/row-prop.gif, plugins/TableOperations/img/row-split.gif, plugins/TableOperations/img/table-prop.gif, plugins/TableOperations/lang/en.js, plugins/TableOperations/lang/fi.js, plugins/TableOperations/lang/makefile.xml, plugins/TableOperations/lang/ro.js, plugins/TableOperations/makefile.xml, plugins/TableOperations/table-operations.js, plugins/makefile.xml, popups/about.html, popups/fullscreen.html, popups/makefile.xml, example-fully-loaded.html, example-spell-checker.html, example-table-operations.html, example.html, htmlarea-lang-b5.js, htmlarea-lang-da.js, htmlarea-lang-de.js, htmlarea-lang-en.js, htmlarea-lang-es.js, htmlarea-lang-fr.js, htmlarea-lang-gb.js, htmlarea-lang-it.js, htmlarea-lang-ja-euc.js, htmlarea-lang-ja-jis.js, htmlarea-lang-ja-sjis.js, htmlarea-lang-ja-utf8.js, htmlarea-lang-nb.js, htmlarea-lang-nl.js, htmlarea-lang-pl.js, htmlarea-lang-pt_br.js, htmlarea-lang-ru.js, htmlarea-lang-se.js, htmlarea-lang-vn.js, htmlarea.css, htmlarea.js, images/ed_paste.gif, images/ed_show_border.gif, images/ed_splitcel.gif, images/makefile.xml, index.html, lang/b5.js, make-release.pl, makefile.xml, popupdiv.js, popupwin.js, project-config.xml, readme.html, reference.html, release-notes.html:
+       Merged from table-devel branch.  Development back on main trunk.
+
+       * plugins/SpellChecker/readme-tech.html: added I18N file to description
+
+       * plugins/SpellChecker/spell-check-ui.html, plugins/SpellChecker/spell-check-ui.js:
+       internationalization now supported
+
+       * plugins/TableOperations/table-operations.js:
+       fixed bug icons inside dialogs
+
+       * popups/about.html:
+       nicer dialog, + automatic version/release management
+
+       * htmlarea.js, lang/en.js, plugins/SpellChecker/lang/en.js, plugins/TableOperations/lang/en.js:
+       I18N for some messages that were left out, small IMG bug fixed, added loadPlugin static function
+
+       * example-fully-loaded.html, example-spell-checker.html, example-table-operations.html, example.html:
+       UTF-8 charset by default
+
+       * lang/ro.js, plugins/SpellChecker/lang/ro.js, plugins/TableOperations/lang/ro.js:
+       New file.
+
+       * lang/ro.js, plugins/SpellChecker/lang/ro.js, plugins/TableOperations/lang/ro.js:
+       Romanian translation (thanks to My Self)
+
+       * release-notes.html: New file.
+
+       * release-notes.html: release notes
+
+       * lang/makefile.xml, plugins/SpellChecker/img/makefile.xml, plugins/SpellChecker/lang/makefile.xml, plugins/SpellChecker/makefile.xml, plugins/TableOperations/img/makefile.xml, plugins/TableOperations/lang/makefile.xml, plugins/TableOperations/makefile.xml, plugins/makefile.xml, popups/makefile.xml:
+       New file.
+
+       * lang/makefile.xml, plugins/SpellChecker/img/makefile.xml, plugins/SpellChecker/lang/makefile.xml, plugins/SpellChecker/makefile.xml, plugins/TableOperations/img/makefile.xml, plugins/TableOperations/lang/makefile.xml, plugins/TableOperations/makefile.xml, plugins/makefile.xml, popups/makefile.xml:
+       automatic release management (a la makefile)
+
+       * images/makefile.xml, make-release.pl, makefile.xml, project-config.xml:
+       New file.
+
+       * images/makefile.xml, make-release.pl, makefile.xml, project-config.xml:
+       automatic release management (a la makefile)
+
+2003-08-03  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/fi.js, plugins/TableOperations/lang/fi.js:
+       Finnish translation added (thanks bestis)
+
+       * lang/fi.js, plugins/TableOperations/lang/fi.js, index.html: New file.
+
+       * index.html: short description, copyright, links
+
+       * reference.html:
+       LAST VERSION OF THIS DOCUMENT.  IT WILL BE SOON DELETED.
+
+       * lang/b5.js, lang/da.js, lang/de.js, lang/en.js, lang/es.js, lang/fr.js, lang/gb.js, lang/it.js, lang/ja-euc.js, lang/ja-jis.js, lang/ja-sjis.js, lang/ja-utf8.js, lang/nb.js, lang/nl.js, lang/pl.js, lang/pt_br.js, lang/ru.js, lang/se.js, lang/vn.js:
+       added lang in I18N, so that we can load automatically plugin's lang file
+
+       * example-fully-loaded.html: New file.
+
+       * example-fully-loaded.html: loads all plugins
+
+       * example-spell-checker.html: removed TableOperations from this example
+
+2003-08-01  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * readme.html: documentation for 2.x is heavily outdated... removed.
+
+       * example-spell-checker.html, plugins/SpellChecker/img/spell-check.gif, plugins/SpellChecker/lang/en.js, plugins/SpellChecker/readme-tech.html, plugins/SpellChecker/spell-check-logic.cgi, plugins/SpellChecker/spell-check-style.css, plugins/SpellChecker/spell-check-ui.html, plugins/SpellChecker/spell-check-ui.js, plugins/SpellChecker/spell-checker.js:
+       New file.
+
+       * example-spell-checker.html, plugins/SpellChecker/img/spell-check.gif, plugins/SpellChecker/lang/en.js, plugins/SpellChecker/readme-tech.html, plugins/SpellChecker/spell-check-logic.cgi, plugins/SpellChecker/spell-check-style.css, plugins/SpellChecker/spell-check-ui.html, plugins/SpellChecker/spell-check-ui.js, plugins/SpellChecker/spell-checker.js:
+       added the SpellChecker plugin (sponsored by www.AmericanBible.org)
+
+       * example.html, example-table-operations.html:
+       * moved lang files to separate directory
+
+       * htmlarea-lang-en.js, htmlarea-lang-es.js, htmlarea-lang-fr.js, htmlarea-lang-gb.js, htmlarea-lang-it.js, htmlarea-lang-ja-euc.js, htmlarea-lang-ja-jis.js, htmlarea-lang-ja-sjis.js, htmlarea-lang-ja-utf8.js, htmlarea-lang-nb.js, htmlarea-lang-nl.js, htmlarea-lang-pl.js, htmlarea-lang-pt_br.js, htmlarea-lang-ru.js, htmlarea-lang-se.js, htmlarea-lang-vn.js, htmlarea-lang-b5.js, htmlarea-lang-da.js, htmlarea-lang-de.js:
+       moved to lang/
+
+       * lang/b5.js, lang/da.js, lang/de.js, lang/en.js, lang/es.js, lang/fr.js, lang/gb.js, lang/it.js, lang/ja-euc.js, lang/ja-jis.js, lang/ja-sjis.js, lang/ja-utf8.js, lang/nb.js, lang/nl.js, lang/pl.js, lang/pt_br.js, lang/ru.js, lang/se.js, lang/vn.js:
+       New file.
+
+       * lang/b5.js, lang/da.js, lang/de.js, lang/en.js, lang/es.js, lang/fr.js, lang/gb.js, lang/it.js, lang/ja-euc.js, lang/ja-jis.js, lang/ja-sjis.js, lang/ja-utf8.js, lang/nb.js, lang/nl.js, lang/pl.js, lang/pt_br.js, lang/ru.js, lang/se.js, lang/vn.js:
+       lang files separated
+
+       * htmlarea.js, htmlarea.css:
+       * added registerDropdown -- for adding custom drop-down boxes to the toolbar
+       * registerDropdown and registerButton verify for existing ID-s first (alert
+         if that's the case)
+       * support for text labels in the toolbar
+       * fixed some bugs in insertHTML (Mozilla specific)
+
+2003-07-16  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * example-table-operations.html:
+       TableOperations lang file moved to 'lang' directory
+
+       * plugins/TableOperations/lang/en.js: New file.
+
+       * plugins/TableOperations/lang/en.js, plugins/TableOperations/table-operations-lang-en.js:
+       lang files in dedicated directory [lang]
+
+       * htmlarea.js: [IE] no status bar on fullscreen editor
+
+2003-07-15  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js:
+       [IE] fixed annoying bug: displacement of the separators within the toolbar;
+            IE assigns a random image width/height, if not explicitely stated ;-)
+
+2003-07-13  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * popups/fullscreen.html: moved plugin images to ../plugins
+       fixed bug that only applied to Moz-1.4 or newer Geckos (script.src is always
+       an absolute URL)
+
+       * htmlarea.js: restructuration concerning images
+
+       * plugins/TableOperations/table-operations.js:
+       images moved to the plugin directory
+
+       * plugins/TableOperations/img/cell-delete.gif, plugins/TableOperations/img/cell-insert-after.gif, plugins/TableOperations/img/cell-insert-before.gif, plugins/TableOperations/img/cell-merge.gif, plugins/TableOperations/img/cell-prop.gif, plugins/TableOperations/img/cell-split.gif, plugins/TableOperations/img/col-delete.gif, plugins/TableOperations/img/col-insert-after.gif, plugins/TableOperations/img/col-insert-before.gif, plugins/TableOperations/img/col-split.gif, plugins/TableOperations/img/row-delete.gif, plugins/TableOperations/img/row-insert-above.gif, plugins/TableOperations/img/row-insert-under.gif, plugins/TableOperations/img/row-prop.gif, plugins/TableOperations/img/row-split.gif, plugins/TableOperations/img/table-prop.gif:
+       New file.
+
+       * plugins/TableOperations/img/cell-delete.gif, plugins/TableOperations/img/cell-insert-after.gif, plugins/TableOperations/img/cell-insert-before.gif, plugins/TableOperations/img/cell-merge.gif, plugins/TableOperations/img/cell-prop.gif, plugins/TableOperations/img/cell-split.gif, plugins/TableOperations/img/col-delete.gif, plugins/TableOperations/img/col-insert-after.gif, plugins/TableOperations/img/col-insert-before.gif, plugins/TableOperations/img/col-split.gif, plugins/TableOperations/img/row-delete.gif, plugins/TableOperations/img/row-insert-above.gif, plugins/TableOperations/img/row-insert-under.gif, plugins/TableOperations/img/row-prop.gif, plugins/TableOperations/img/row-split.gif, plugins/TableOperations/img/table-prop.gif:
+       moved TableOperations icons here
+
+       * images/ed_splitcell.gif:
+       moved to ../plugins/TableOperations/img/cell-split.gif
+
+       * images/ed_mergecels.gif:
+       moved to ../plugins/TableOperations/img/cell-merge.gif
+
+       * images/ed_delcel.gif:
+       moved to ../plugins/TableOperations/img/cell-delete.gif
+
+       * images/ed_inscelrgt.gif:
+       moved to ../plugins/TableOperations/img/cell-insert-after.gif
+
+       * images/ed_inscellft.gif:
+       moved to ../plugins/TableOperations/img/cell-insert-before.gif
+
+       * images/ed_cellprop.gif:
+       moved to ../plugins/TableOperations/img/cell-prop.gif
+
+       * images/ed_splitcol.gif:
+       moved to ../plugins/TableOperations/img/col-split.gif
+
+       * images/ed_delcol.gif:
+       moved to ../plugins/TableOperations/img/col-delete.gif
+
+       * images/ed_insright.gif:
+       moved to ../plugins/TableOperations/img/col-insert-after.gif
+
+       * images/ed_insleft.gif:
+       moved to ../plugins/TableOperations/img/col-insert-before.gif
+
+       * images/ed_splitrow.gif:
+       moved to ../plugins/TableOperations/img/row-split.gif
+
+       * images/ed_delrow.gif:
+       moved to ../plugins/TableOperations/img/row-delete.gif
+
+       * images/ed_insunder.gif:
+       moved to ../plugins/TableOperations/img/row-insert-under.gif
+
+       * images/ed_insabove.gif:
+       moved to ../plugins/TableOperations/img/row-insert-above.gif
+
+       * images/ed_rowprop.gif:
+       moved to ../plugins/TableOperations/img/row-prop.gif
+
+       * images/ed_tableprop.gif:
+       moved to ../plugins/TableOperations/img/table-prop.gif
+
+2003-06-11  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/TableOperations/table-operations.js:
+       revamped code for table "border", "frame" and "rules" attributes
+
+2003-06-08  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/TableOperations/table-operations.js:
+       added focusEditor() calls (editor lost focus in IE after some operations)
+
+       * plugins/TableOperations/table-operations.js:
+       fixed 2 bugs (correct title in row/cell properties dialog, clear cell
+       contents when inserting new row in Internet Explorer)
+
+2003-06-02  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * popups/fullscreen.html:
+       [IE] fixed problem that caused toolbar buttons to be unusable
+
+       * popups/fullscreen.html:
+       [IE] fixed bug when copying the click handler.  Editor is now functional in
+       fullscreen.
+
+       * plugins/TableOperations/table-operations-lang-en.js, plugins/TableOperations/table-operations.js:
+       1. Removed code that selects the table/row/cell before displaying the
+       dialog.
+
+       2. Focus back the table after closing the dialog box (was causing some
+       problems in IE).
+
+       3. Implemented merge cells for IE (user will be prompted for number of
+       cols/rows to span the current cell).
+
+       * htmlarea.js:
+       1. Display an alert if cut/copy/paste is not supported, when one of the buttons
+       is clicked.  The button will also be removed from the toolbar.
+
+       2. Fixed bug when clicking on some table/image margin in IE.
+
+2003-05-31  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/TableOperations/table-operations.js:
+       [IE5.5] IE5.5 doesn't support createDocumentFragment; workarounded.
+
+       * htmlarea.css: Better looking dialogs
+
+       * htmlarea.js: Fixed IE5.5 compatibility issues.
+
+       * htmlarea.js: Now IE5.5 compatible.
+
+2003-05-27  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: workaround for a horrible bug (thanks Dror!)
+
+       * htmlarea.js: oops... ;-)
+
+       * htmlarea.js: workaround for a horrible bug (thanks Dror!)
+
+2003-05-18  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/TableOperations/table-operations-lang-en.js:
+       added some comment notes for translators
+
+       * plugins/TableOperations/table-operations.js: bugfix:
+         - border-style changes are updated correctly in Mozilla
+         - do not show Float for td, th, tr elements
+       feature (eye-candy)
+         - added small icons on each dialog
+
+       * popupwin.js: added baseURL to the object (useful in dialogs)
+
+       * plugins/TableOperations/table-operations-lang-en.js, plugins/TableOperations/table-operations.js:
+       modified dialogs (more css-friendly, trying to avoid deprecated HTML
+       attributes).  fixed some bugs.
+
+       * htmlarea.js:
+       added oncontextmenu for status-bar elements (displays inline style)
+       fixed problem with textindicator (background-color in Mozilla)
+
+       * htmlarea.css: tables in dialogs have border-collapse: collapse
+
+       * example-table-operations.html:
+       modified example HTML (more colorful, blah blah)
+
+2003-05-14  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/TableOperations/table-operations.js:
+       (trying to) force redraw after table/row/cell properties dialogs close with
+       OK
+
+2003-05-13  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/TableOperations/table-operations-lang-en.js, plugins/TableOperations/table-operations.js, popupwin.js:
+       some fixes for IE; implemented border-collapse style properties (tables only)
+
+2003-05-12  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/TableOperations/table-operations-lang-en.js, plugins/TableOperations/table-operations.js, example-table-operations.html, htmlarea.css, popupwin.js:
+       improvements of the color selector button, added row properties and cell properties dialogs, fixes, etc.
+
+2003-05-08  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/TableOperations/table-operations.js:
+       border properties now functional
+
+       * plugins/TableOperations/table-operations-lang-en.js:
+       CSS Style -> Style [CSS]
+
+       * popupwin.js: smaller padding.. looks better.
+
+       * htmlarea.css, plugins/TableOperations/table-operations-lang-en.js, plugins/TableOperations/table-operations.js:
+       added functionality (style properties, changed BUTTON to DIV for color
+       selection widget, added border properties [not completed yed])
+
+2003-05-07  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/TableOperations/table-operations.js:
+       fixed small bug; added some comments
+
+2003-05-06  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js:
+       fixed small bug (user might close the select_color dialog by pressing "X"
+       button, case in which the selection is now ignored)
+
+       * htmlarea.js: debug code can sometimes be annoying -- commented out.
+
+       * htmlarea.js: bug #730593 fixed
+
+       * plugins/TableOperations/table-operations-lang-en.js, plugins/TableOperations/table-operations.js:
+       added first dialog (table properties) + other useful stuff like generic style properties that should eventually make it into a separated plugin
+
+       * popupdiv.js, popupwin.js: New file.
+
+       * popupdiv.js, popupwin.js:
+       files for handling some popup dialogs generated from JS code
+
+       * example-table-operations.html: credit modified
+
+2003-05-05  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea-lang-en.js:
+       I18N for 2 very common text-s ("ok" and "cancel")
+
+       * htmlarea.css: style for new popups
+
+       * htmlarea.js:
+       added new variable (_mdoc which keeps a reference to the document that
+       contains the HTMLArea.  it's sometimes useful (mainly in popups))
+
+2003-04-25  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/TableOperations/table-operations.js:
+       modified credit (bloki.com instead of zapatec.com)
+
+2003-04-24  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/TableOperations/table-operations.js:
+       fixed code to work if editor used in fullscreen
+
+       * popups/fullscreen.html:
+       added nice code that automagically loads all scripts in the parent page (opener)
+
+       * plugins/TableOperations/table-operations.js:
+       - fixes for IE (IE doesn't need the BR inside empty TD-s)
+       - when called in fullscreen mode it doesn't update the toolbar
+
+       * htmlarea.js:
+       small fix for IE (getAllAncestors sometimes returned the HTML and Document element too)
+
+2003-04-23  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * popups/fullscreen.html: small bug fixed
+
+       * htmlarea.css:
+       changed bg for disabled buttons (this is for debug, I repeat ;-)
+
+       * htmlarea.js: - API support for external plugins
+       - support for context-enabled buttons
+       - performance improvement: cancelling updateToolbar requests if made in less
+         than 50ms -- in other words, only honor the last one
+
+       * example.html: test for context-enabled buttons
+
+       * plugins/TableOperations/table-operations.js: New file.
+
+       * plugins/TableOperations/table-operations.js:
+       added TableOperations plugin
+       several new toolbar buttons + fixes to some existent ones
+       file that demonstrate usage of the TableOperations plugin
+
+       * plugins/TableOperations/table-operations-lang-en.js: New file.
+
+       * plugins/TableOperations/table-operations-lang-en.js:
+       added TableOperations plugin
+       several new toolbar buttons + fixes to some existent ones
+       file that demonstrate usage of the TableOperations plugin
+
+       * images/ed_splitcell.gif, images/ed_splitcol.gif: New file.
+
+       * images/ed_splitcell.gif, images/ed_splitcol.gif, images/ed_splitrow.gif, images/ed_paste.gif, images/ed_insunder.gif, images/ed_mergecels.gif, images/ed_inscellft.gif, images/ed_inscelrgt.gif, images/ed_insleft.gif, images/ed_insright.gif, images/ed_insabove.gif, images/ed_delcol.gif, images/ed_delrow.gif:
+       added TableOperations plugin
+       several new toolbar buttons + fixes to some existent ones
+       file that demonstrate usage of the TableOperations plugin
+
+       * example-table-operations.html: New file.
+
+       * example-table-operations.html, images/ed_delcel.gif:
+       added TableOperations plugin
+       several new toolbar buttons + fixes to some existent ones
+       file that demonstrate usage of the TableOperations plugin
+
+2003-04-21  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: added status bar (cool B-)
+
+       * htmlarea.css: various improvements for the status bar
+
+       * example.html: minor fix (background-color instead of background)
+
+2003-04-20  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: fix: IE parsing problem
+
+       * htmlarea.css, htmlarea.js, popups/fullscreen.html: added statusbar
+
+       * images/ed_tableprop.gif: New file.
+
+       * images/ed_tableprop.gif: added images for table operations buttons
+
+       * images/ed_cellprop.gif, images/ed_delcel.gif, images/ed_delcol.gif, images/ed_delrow.gif, images/ed_insabove.gif, images/ed_inscellft.gif, images/ed_inscelrgt.gif, images/ed_insleft.gif, images/ed_insright.gif, images/ed_insunder.gif, images/ed_mergecels.gif, images/ed_paste.gif, images/ed_rowprop.gif, images/ed_show_border.gif, images/ed_splitcel.gif, images/ed_splitrow.gif:
+       New file.
+
+       * images/ed_cellprop.gif, images/ed_delcel.gif, images/ed_delcol.gif, images/ed_delrow.gif, images/ed_insabove.gif, images/ed_inscellft.gif, images/ed_inscelrgt.gif, images/ed_insleft.gif, images/ed_insright.gif, images/ed_insunder.gif, images/ed_mergecels.gif, images/ed_paste.gif, images/ed_rowprop.gif, images/ed_show_border.gif, images/ed_splitcel.gif, images/ed_splitrow.gif:
+       added images for table operations buttons
+
+       * example.html:
+       even more examples of customization, but commented out so that the example
+       page looks initially with the editor defaults
+
+       * htmlarea-lang-en.js:
+       Added tooltips for cut, copy, paste, undo, redo buttons
+
+       * htmlarea.js: new features:
+
+         - cut, copy, paste, undo, redo buttons
+         - added functions: getParentElement, getAllAncestors
+         - buttons can now be enabled/disabled function of the context (i.e. caret
+           is inside a table)
+         - iframe border removed on Mozilla (looks better)
+
+       * htmlarea.css:
+       minor fix [padding]; also contains some debugging stuff that needs to be
+       removed (disabled buttons have red background, that's because Mozilla
+       doesn't seem to support opacity any longer)
+
+2003-04-19  itools  <itools@mishoo>
+
+       * test.cgi: ..
+
+       * test.cgi: ...
+
+2003-04-15  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: added address: block-level element
+
+2003-04-02  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * popups/fullscreen.html: fixed small issue
+
+2003-03-24  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea-lang-pt_br.js: brasilian translation
+
+2003-03-19  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea-lang-nb.js: norwegian translation added
+
+       * reference.html: fixed typo
+
+2003-03-15  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js:
+       fixed bug (createlink needs UI -> true, otherwise we get a link to nowhere)
+
+2003-03-04  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea-lang-ja-euc.js, htmlarea-lang-ja-jis.js, htmlarea-lang-ja-sjis.js, htmlarea-lang-ja-utf8.js, htmlarea-lang-pl.js:
+       new translations: japanese and polish
+
+2003-03-03  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * example.html, htmlarea.js: example.html: now validates (hopefully)
+       htmlarea.js: opening help in a named window
+
+2003-03-02  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * reference.html:
+       minor fix: showing how to include the "dialog.js" file
+
+2003-02-27  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * reference.html: fixes, improvements
+       new sections on creating custom buttons
+
+       * example.html:
+       example on how to submit the form from something that's not a submit button
+
+       * htmlarea.js: added "onsubmit" handler with usual syntax.
+
+       * example.html: examples now using registerButton
+
+       * popups/fullscreen.html:
+       [fix] using now the new btnList layout; removed _textArea2
+
+       * htmlarea.js: - added helper function HTMLArea.Config.registerButton
+       - _editor_url is back
+       - fixed a problem that might disturb JS compressors ('"' character in
+       regexp)
+
+2003-02-26  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: iframe border back..
+
+       * example.html: fixes -- new btnList style
+
+       * htmlarea.js:
+       changed btnList order -- tooltip, icon, textmode, action.
+
+       * example.html: demo fix
+
+       * example.html: [minor] validity
+
+       * htmlarea.js:
+       BUG FIX: now it remembers textarea content on page reload.  Got rid of the
+                secondary textarea.
+
+       * htmlarea-lang-it.js: Italian translation -- from TeddyZ
+
+2003-02-24  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea-lang-vn.js: Vietnamese lang module
+
+2003-02-22  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js:
+       Reorganized the btnList.  Now it uses direct function calls.
+
+       * reference.html: minor: use replace() instead of replaceAll()
+
+       * htmlarea.js:
+       - fixed bug: HTMLArea.replace() needs to call generate() (thanks Dlo)
+       - adding the onsubmit handler -- check if the form is there first
+       - added onunload handler that saves the HTML content, just in case user
+         presses Back/Fwd or Refresh.
+
+       * htmlarea-lang-se.js: swedish translation
+
+2003-02-21  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: done some of the changes suggested by Dlo
+       bodyStyle -> pageStyle and allows other elements' styles too
+
+       * example.html: example: how to add a custom button
+
+       * reference.html: started documentation project
+
+2003-02-20  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea-lang-da.js, htmlarea-lang-gb.js, htmlarea-lang-b5.js:
+       added new lang files
+
+2003-02-19  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea-lang-de.js: added credits
+
+       * htmlarea-lang-nl.js: credit for redspider ;)
+
+       * htmlarea-lang-de.js: added german translation (from atk)
+
+       * htmlarea-lang-nl.js: dutch translation, from redspider
+
+       * htmlarea-lang-ru.js: RU translation (from Frol, itools forums)
+
+       * htmlarea-lang-es.js:
+       added ES translation from itools forums (thanks Luis)
+
+       * htmlarea-lang-fr.js:
+       added french translation, from Ronan (interactivetools.com forums)
+
+2003-02-17  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * images/.xvpics/ed_align_justify.gif: not needed
+
+       * htmlarea.js:
+       -- made HTMLArea constructor to work with object instead of ID (if type of
+          argument is not string)
+       -- a simpler "replaceAll" function (2 lines)
+       -- fixed a major bug that prevented IE6 to correctly retrieve the HTML (it
+          seems that it was ignoring attribute values and only displaying "")
+       -- used various techniques to reduce the code size (currently only 37K, 10K
+          less than the original editor.js code [v 2.03])
+
+       * htmlarea.js:
+       removed NodeIterator code -- was only used in one place and I found a
+       different way to accomplish that task; code smaller by about 5K
+
+       * dialog.js, images/.xvpics/ed_align_justify.gif, images/ed_about.gif, images/ed_align_center.gif, images/ed_align_justify.gif, images/ed_align_left.gif, images/ed_align_right.gif, images/ed_blank.gif, images/ed_charmap.gif, images/ed_color_bg.gif, images/ed_color_fg.gif, images/ed_copy.gif, images/ed_custom.gif, images/ed_cut.gif, images/ed_delete.gif, images/ed_format_bold.gif, images/ed_format_italic.gif, images/ed_format_strike.gif, images/ed_format_sub.gif, images/ed_format_sup.gif, images/ed_format_underline.gif, images/ed_help.gif, images/ed_hr.gif, images/ed_html.gif, images/ed_image.gif, images/ed_indent_less.gif, images/ed_indent_more.gif, images/ed_link.gif, images/ed_list_bullet.gif, images/ed_list_num.gif, images/ed_redo.gif, images/ed_undo.gif, images/fullscreen_maximize.gif, images/fullscreen_minimize.gif, images/insert_table.gif, popups/about.html, popups/blank.html, popups/custom2.html, popups/editor_help.html, popups/fullscreen.html, popups/insert_image.html, popups/insert_table.html, popups/old-fullscreen.html, popups/old_insert_image.html, popups/popup.js, popups/select_color.html:
+       New file.
+
+       * dialog.js, images/.xvpics/ed_align_justify.gif, images/ed_about.gif, images/ed_align_center.gif, images/ed_align_justify.gif, images/ed_align_left.gif, images/ed_align_right.gif, images/ed_blank.gif, images/ed_charmap.gif, images/ed_color_bg.gif, images/ed_color_fg.gif, images/ed_copy.gif, images/ed_custom.gif, images/ed_cut.gif, images/ed_delete.gif, images/ed_format_bold.gif, images/ed_format_italic.gif, images/ed_format_strike.gif, images/ed_format_sub.gif, images/ed_format_sup.gif, images/ed_format_underline.gif, images/ed_help.gif, images/ed_hr.gif, images/ed_html.gif, images/ed_image.gif, images/ed_indent_less.gif, images/ed_indent_more.gif, images/ed_link.gif, images/ed_list_bullet.gif, images/ed_list_num.gif, images/ed_redo.gif, images/ed_undo.gif, images/fullscreen_maximize.gif, images/fullscreen_minimize.gif, images/insert_table.gif, popups/about.html, popups/blank.html, popups/custom2.html, popups/editor_help.html, popups/fullscreen.html, popups/insert_image.html, popups/insert_table.html, popups/old-fullscreen.html, popups/old_insert_image.html, popups/popup.js, popups/select_color.html:
+       first moved to CVS (close to release 3.0-beta)
+
+       * htmlarea.js, test.cgi: New file.
+
+       * htmlarea.js, test.cgi: first moved to CVS (close to release 3.0-beta)
+
+       * htmlarea-lang-en.js, readme.html: New file.
+
+       * htmlarea-lang-en.js, readme.html:
+       first moved to CVS (close to release 3.0-beta)
+
+       * example.html, htmlarea.css, license.txt: New file.
+
+       * example.html, htmlarea.css, license.txt:
+       first moved to CVS (close to release 3.0-beta)
+
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/dialog.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/dialog.js
new file mode 100644 (file)
index 0000000..6a6ba07
--- /dev/null
@@ -0,0 +1,72 @@
+// htmlArea v3.0 - Copyright (c) 2003-2004 interactivetools.com, inc.
+// This copyright notice MUST stay intact for use (see license.txt).
+//
+// Portions (c) dynarch.com, 2003-2004
+//
+// A free WYSIWYG editor replacement for <textarea> fields.
+// For full source code and docs, visit http://www.interactivetools.com/
+//
+// Version 3.0 developed by Mihai Bazon.
+//   http://dynarch.com/mishoo
+//
+// $Id: dialog.js 30938 2004-07-29 19:08:16Z vgritsenko $
+
+// Though "Dialog" looks like an object, it isn't really an object.  Instead
+// it's just namespace for protecting global symbols.
+
+function Dialog(url, action, init) {
+       if (typeof init == "undefined") {
+               init = window;  // pass this window object by default
+       }
+       Dialog._geckoOpenModal(url, action, init);
+};
+
+Dialog._parentEvent = function(ev) {
+       if (Dialog._modal && !Dialog._modal.closed) {
+               Dialog._modal.focus();
+               HTMLArea._stopEvent(ev);
+       }
+};
+
+// should be a function, the return handler of the currently opened dialog.
+Dialog._return = null;
+
+// constant, the currently opened dialog
+Dialog._modal = null;
+
+// the dialog will read it's args from this variable
+Dialog._arguments = null;
+
+Dialog._geckoOpenModal = function(url, action, init) {
+       var dlg = window.open(url, "hadialog",
+                             "toolbar=no,menubar=no,personalbar=no,width=10,height=10," +
+                             "scrollbars=no,resizable=yes");
+       Dialog._modal = dlg;
+       Dialog._arguments = init;
+
+       // capture some window's events
+       function capwin(w) {
+               HTMLArea._addEvent(w, "click", Dialog._parentEvent);
+               HTMLArea._addEvent(w, "mousedown", Dialog._parentEvent);
+               HTMLArea._addEvent(w, "focus", Dialog._parentEvent);
+       };
+       // release the captured events
+       function relwin(w) {
+               HTMLArea._removeEvent(w, "click", Dialog._parentEvent);
+               HTMLArea._removeEvent(w, "mousedown", Dialog._parentEvent);
+               HTMLArea._removeEvent(w, "focus", Dialog._parentEvent);
+       };
+       capwin(window);
+       // capture other frames
+       for (var i = 0; i < window.frames.length; capwin(window.frames[i++]));
+       // make up a function to be called when the Dialog ends.
+       Dialog._return = function (val) {
+               if (val && action) {
+                       action(val);
+               }
+               relwin(window);
+               // capture other frames
+               for (var i = 0; i < window.frames.length; relwin(window.frames[i++]));
+               Dialog._modal = null;
+       };
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/htmlarea.css b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/htmlarea.css
new file mode 100644 (file)
index 0000000..0e034bf
--- /dev/null
@@ -0,0 +1,180 @@
+.htmlarea { background: #fff; }
+
+.htmlarea .toolbar {
+  cursor: default;
+  background: ButtonFace;
+  padding: 1px 1px 2px 1px;
+  border: 1px solid;
+  border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
+}
+.htmlarea .toolbar table { font-family: tahoma,verdana,sans-serif; font-size: 11px; }
+.htmlarea .toolbar img { border: none; }
+.htmlarea .toolbar .label { padding: 0px 3px; }
+
+.htmlarea .toolbar .button {
+  background: ButtonFace;
+  color: ButtonText;
+  border: 1px solid ButtonFace;
+  padding: 1px;
+  margin: 0px;
+  width: 18px;
+  height: 18px;
+}
+.htmlarea .toolbar .buttonHover {
+  border: 1px solid;
+  border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
+}
+.htmlarea .toolbar .buttonActive, .htmlarea .toolbar .buttonPressed {
+  padding: 2px 0px 0px 2px;
+  border: 1px solid;
+  border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;
+}
+.htmlarea .toolbar .buttonPressed {
+  background: ButtonHighlight;
+}
+.htmlarea .toolbar .indicator {
+  padding: 0px 3px;
+  overflow: hidden;
+  width: 20px;
+  text-align: center;
+  cursor: default;
+  border: 1px solid ButtonShadow;
+}
+
+.htmlarea .toolbar .buttonDisabled img {
+  filter: alpha(opacity = 25);
+  -moz-opacity: 0.25;
+}
+
+.htmlarea .toolbar .separator {
+  position: relative;
+  margin: 3px;
+  border-left: 1px solid ButtonShadow;
+  border-right: 1px solid ButtonHighlight;
+  width: 0px;
+  height: 16px;
+  padding: 0px;
+}
+
+.htmlarea .toolbar .space { width: 5px; }
+
+.htmlarea .toolbar select { font: 11px Tahoma,Verdana,sans-serif; }
+
+.htmlarea .toolbar select,
+.htmlarea .toolbar select:hover,
+.htmlarea .toolbar select:active { background: FieldFace; color: ButtonText; }
+
+.htmlarea .statusBar {
+  border: 1px solid;
+  border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;
+  padding: 2px 4px;
+  background-color: ButtonFace;
+  color: ButtonText;
+  font: 11px Tahoma,Verdana,sans-serif;
+}
+
+.htmlarea .statusBar .statusBarTree a {
+  padding: 2px 5px;
+  color: #00f;
+}
+
+.htmlarea .statusBar .statusBarTree a:visited { color: #00f; }
+.htmlarea .statusBar .statusBarTree a:hover {
+  background-color: Highlight;
+  color: HighlightText;
+  padding: 1px 4px;
+  border: 1px solid HighlightText;
+}
+
+
+/* Hidden DIV popup dialogs (PopupDiv) */
+
+.dialog {
+  color: ButtonText;
+  background: ButtonFace;
+}
+
+.dialog .content { padding: 2px; }
+
+.dialog, .dialog button, .dialog input, .dialog select, .dialog textarea, .dialog table {
+  font: 11px Tahoma,Verdana,sans-serif;
+}
+
+.dialog table { border-collapse: collapse; }
+
+.dialog .title {
+  background: #008;
+  color: #ff8;
+  border-bottom: 1px solid #000;
+  padding: 1px 0px 2px 5px;
+  font-size: 12px;
+  font-weight: bold;
+  cursor: default;
+}
+
+.dialog .title .button {
+  float: right;
+  border: 1px solid #66a;
+  padding: 0px 1px 0px 2px;
+  margin-right: 1px;
+  color: #fff;
+  text-align: center;
+}
+
+.dialog .title .button-hilite { border-color: #88f; background: #44c; }
+
+.dialog button {
+  width: 5em;
+  padding: 0px;
+}
+
+.dialog .buttonColor {
+  padding: 1px;
+  cursor: default;
+  border: 1px solid;
+  border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
+}
+
+.dialog .buttonColor-hilite {
+  border-color: #000;
+}
+
+.dialog .buttonColor .chooser, .dialog .buttonColor .nocolor {
+  height: 0.6em;
+  border: 1px solid;
+  padding: 0px 1em;
+  border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;
+}
+
+.dialog .buttonColor .nocolor { padding: 0px; }
+.dialog .buttonColor .nocolor-hilite { background-color: #fff; color: #f00; }
+
+.dialog .label { text-align: right; width: 6em; }
+.dialog .value input { width: 100%; }
+.dialog .buttons { text-align: right; padding: 2px 4px 0px 4px; }
+
+.dialog legend { font-weight: bold; }
+.dialog fieldset table { margin: 2px 0px; }
+
+.popupdiv {
+  border: 2px solid;
+  border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
+}
+
+.popupwin {
+  padding: 0px;
+  margin: 0px;
+}
+
+.popupwin .title {
+  background: #fff;
+  color: #000;
+  font-weight: bold;
+  font-size: 120%;
+  padding: 3px 10px;
+  margin-bottom: 10px;
+  border-bottom: 1px solid black;
+  letter-spacing: 2px;
+}
+
+form { margin: 0px; border: none; }
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/htmlarea.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/htmlarea.js
new file mode 100644 (file)
index 0000000..6e33789
--- /dev/null
@@ -0,0 +1,2175 @@
+// htmlArea v3.0 - Copyright (c) 2002-2004 interactivetools.com, inc.
+// This copyright notice MUST stay intact for use (see license.txt).
+//
+// Portions (c) dynarch.com, 2003-2004
+//
+// A free WYSIWYG editor replacement for <textarea> fields.
+// For full source code and docs, visit http://www.interactivetools.com/
+//
+// Version 3.0 developed by Mihai Bazon.
+//   http://dynarch.com/mishoo
+//
+// $Id: htmlarea.js 30938 2004-07-29 19:08:16Z vgritsenko $
+
+if (typeof _editor_url == "string") {
+       // Leave exactly one backslash at the end of _editor_url
+       _editor_url = _editor_url.replace(/\x2f*$/, '/');
+} else {
+       alert("WARNING: _editor_url is not set!  You should set this variable to the editor files path; it should preferably be an absolute path, like in '/htmlarea', but it can be relative if you prefer.  Further we will try to load the editor files correctly but we'll probably fail.");
+       _editor_url = '';
+}
+
+// make sure we have a language
+if (typeof _editor_lang == "string") {
+       _editor_lang = _editor_lang.toLowerCase();
+} else {
+       _editor_lang = "en";
+}
+
+// Creates a new HTMLArea object.  Tries to replace the textarea with the given
+// ID with it.
+function HTMLArea(textarea, config) {
+       if (HTMLArea.checkSupportedBrowser()) {
+               if (typeof config == "undefined") {
+                       this.config = new HTMLArea.Config();
+               } else {
+                       this.config = config;
+               }
+               this._htmlArea = null;
+               this._textArea = textarea;
+               this._editMode = "wysiwyg";
+               this.plugins = {};
+               this._timerToolbar = null;
+               this._timerUndo = null;
+               this._undoQueue = new Array(this.config.undoSteps);
+               this._undoPos = -1;
+               this._customUndo = false;
+               this._mdoc = document; // cache the document, we need it in plugins
+               this.doctype = '';
+       }
+};
+
+// load some scripts
+(function() {
+       var scripts = HTMLArea._scripts = [ _editor_url + "htmlarea.js",
+                                           _editor_url + "dialog.js",
+                                           _editor_url + "popupwin.js",
+                                           _editor_url + "lang/" + _editor_lang + ".js" ];
+       var head = document.getElementsByTagName("head")[0];
+       // start from 1, htmlarea.js is already loaded
+       for (var i = 1; i < scripts.length; ++i) {
+               var script = document.createElement("script");
+               script.src = scripts[i];
+               head.appendChild(script);
+       }
+})();
+
+// cache some regexps
+HTMLArea.RE_tagName = /(<\/|<)\s*([^ \t\n>]+)/ig;
+HTMLArea.RE_doctype = /(<!doctype((.|\n)*?)>)\n?/i;
+HTMLArea.RE_head    = /<head>((.|\n)*?)<\/head>/i;
+HTMLArea.RE_body    = /<body>((.|\n)*?)<\/body>/i;
+
+HTMLArea.Config = function () {
+       this.version = "3.0";
+
+       this.width = "auto";
+       this.height = "auto";
+
+       // enable creation of a status bar?
+       this.statusBar = true;
+
+       // maximum size of the undo queue
+       this.undoSteps = 20;
+
+       // the time interval at which undo samples are taken
+       this.undoTimeout = 500; // 1/2 sec.
+
+       // the next parameter specifies whether the toolbar should be included
+       // in the size or not.
+       this.sizeIncludesToolbar = true;
+
+       // if true then HTMLArea will retrieve the full HTML, starting with the
+       // <HTML> tag.
+       this.fullPage = false;
+
+       // style included in the iframe document
+       this.pageStyle = "";
+
+       // set to true if you want Word code to be cleaned upon Paste
+       this.killWordOnPaste = false;
+
+       // BaseURL included in the iframe document
+       this.baseURL = document.baseURI || document.URL;
+       if (this.baseURL && this.baseURL.match(/(.*)\/([^\/]+)/))
+               this.baseURL = RegExp.$1 + "/";
+
+       // URL-s
+       this.imgURL = "images/";
+       this.popupURL = "popups/";
+
+       /** CUSTOMIZING THE TOOLBAR
+        * -------------------------
+        *
+        * It is recommended that you customize the toolbar contents in an
+        * external file (i.e. the one calling HTMLArea) and leave this one
+        * unchanged.  That's because when we (InteractiveTools.com) release a
+        * new official version, it's less likely that you will have problems
+        * upgrading HTMLArea.
+        */
+       this.toolbar = [
+               [ "fontname", "space",
+                 "fontsize", "space",
+                 "formatblock", "space",
+                 "bold", "italic", "underline", "strikethrough", "separator",
+                 "subscript", "superscript", "separator",
+                 "copy", "cut", "paste", "space", "undo", "redo" ],
+
+               [ "justifyleft", "justifycenter", "justifyright", "justifyfull", "separator",
+                 "lefttoright", "righttoleft", "separator",
+                 "insertorderedlist", "insertunorderedlist", "outdent", "indent", "separator",
+                 "forecolor", "hilitecolor", "separator",
+                 "inserthorizontalrule", "createlink", "insertimage", "inserttable", "htmlmode", "separator",
+                 "popupeditor", "separator", "showhelp", "about" ]
+       ];
+
+       this.fontname = {
+               "Arial":           'arial,helvetica,sans-serif',
+               "Courier New":     'courier new,courier,monospace',
+               "Georgia":         'georgia,times new roman,times,serif',
+               "Tahoma":          'tahoma,arial,helvetica,sans-serif',
+               "Times New Roman": 'times new roman,times,serif',
+               "Verdana":         'verdana,arial,helvetica,sans-serif',
+               "impact":          'impact',
+               "WingDings":       'wingdings'
+       };
+
+       this.fontsize = {
+               "1 (8 pt)":  "1",
+               "2 (10 pt)": "2",
+               "3 (12 pt)": "3",
+               "4 (14 pt)": "4",
+               "5 (18 pt)": "5",
+               "6 (24 pt)": "6",
+               "7 (36 pt)": "7"
+       };
+
+       this.formatblock = {
+               "Heading 1": "h1",
+               "Heading 2": "h2",
+               "Heading 3": "h3",
+               "Heading 4": "h4",
+               "Heading 5": "h5",
+               "Heading 6": "h6",
+               "Normal": "p",
+               "Address": "address",
+               "Formatted": "pre"
+       };
+
+       this.customSelects = {};
+
+       function cut_copy_paste(e, cmd, obj) {
+               e.execCommand(cmd);
+       };
+
+       // ADDING CUSTOM BUTTONS: please read below!
+       // format of the btnList elements is "ID: [ ToolTip, Icon, Enabled in text mode?, ACTION ]"
+       //    - ID: unique ID for the button.  If the button calls document.execCommand
+       //          it's wise to give it the same name as the called command.
+       //    - ACTION: function that gets called when the button is clicked.
+       //              it has the following prototype:
+       //                 function(editor, buttonName)
+       //              - editor is the HTMLArea object that triggered the call
+       //              - buttonName is the ID of the clicked button
+       //              These 2 parameters makes it possible for you to use the same
+       //              handler for more HTMLArea objects or for more different buttons.
+       //    - ToolTip: default tooltip, for cases when it is not defined in the -lang- file (HTMLArea.I18N)
+       //    - Icon: path to an icon image file for the button (TODO: use one image for all buttons!)
+       //    - Enabled in text mode: if false the button gets disabled for text-only mode; otherwise enabled all the time.
+       this.btnList = {
+               bold: [ "Bold", "ed_format_bold.gif", false, function(e) {e.execCommand("bold");} ],
+               italic: [ "Italic", "ed_format_italic.gif", false, function(e) {e.execCommand("italic");} ],
+               underline: [ "Underline", "ed_format_underline.gif", false, function(e) {e.execCommand("underline");} ],
+               strikethrough: [ "Strikethrough", "ed_format_strike.gif", false, function(e) {e.execCommand("strikethrough");} ],
+               subscript: [ "Subscript", "ed_format_sub.gif", false, function(e) {e.execCommand("subscript");} ],
+               superscript: [ "Superscript", "ed_format_sup.gif", false, function(e) {e.execCommand("superscript");} ],
+               justifyleft: [ "Justify Left", "ed_align_left.gif", false, function(e) {e.execCommand("justifyleft");} ],
+               justifycenter: [ "Justify Center", "ed_align_center.gif", false, function(e) {e.execCommand("justifycenter");} ],
+               justifyright: [ "Justify Right", "ed_align_right.gif", false, function(e) {e.execCommand("justifyright");} ],
+               justifyfull: [ "Justify Full", "ed_align_justify.gif", false, function(e) {e.execCommand("justifyfull");} ],
+               insertorderedlist: [ "Ordered List", "ed_list_num.gif", false, function(e) {e.execCommand("insertorderedlist");} ],
+               insertunorderedlist: [ "Bulleted List", "ed_list_bullet.gif", false, function(e) {e.execCommand("insertunorderedlist");} ],
+               outdent: [ "Decrease Indent", "ed_indent_less.gif", false, function(e) {e.execCommand("outdent");} ],
+               indent: [ "Increase Indent", "ed_indent_more.gif", false, function(e) {e.execCommand("indent");} ],
+               forecolor: [ "Font Color", "ed_color_fg.gif", false, function(e) {e.execCommand("forecolor");} ],
+               hilitecolor: [ "Background Color", "ed_color_bg.gif", false, function(e) {e.execCommand("hilitecolor");} ],
+               inserthorizontalrule: [ "Horizontal Rule", "ed_hr.gif", false, function(e) {e.execCommand("inserthorizontalrule");} ],
+               createlink: [ "Insert Web Link", "ed_link.gif", false, function(e) {e.execCommand("createlink", true);} ],
+               insertimage: [ "Insert/Modify Image", "ed_image.gif", false, function(e) {e.execCommand("insertimage");} ],
+               inserttable: [ "Insert Table", "insert_table.gif", false, function(e) {e.execCommand("inserttable");} ],
+               htmlmode: [ "Toggle HTML Source", "ed_html.gif", true, function(e) {e.execCommand("htmlmode");} ],
+               popupeditor: [ "Enlarge Editor", "fullscreen_maximize.gif", true, function(e) {e.execCommand("popupeditor");} ],
+               about: [ "About this editor", "ed_about.gif", true, function(e) {e.execCommand("about");} ],
+               showhelp: [ "Help using editor", "ed_help.gif", true, function(e) {e.execCommand("showhelp");} ],
+               undo: [ "Undoes your last action", "ed_undo.gif", false, function(e) {e.execCommand("undo");} ],
+               redo: [ "Redoes your last action", "ed_redo.gif", false, function(e) {e.execCommand("redo");} ],
+               cut: [ "Cut selection", "ed_cut.gif", false, cut_copy_paste ],
+               copy: [ "Copy selection", "ed_copy.gif", false, cut_copy_paste ],
+               paste: [ "Paste from clipboard", "ed_paste.gif", false, cut_copy_paste ],
+               lefttoright: [ "Direction left to right", "ed_left_to_right.gif", false, function(e) {e.execCommand("lefttoright");} ],
+               righttoleft: [ "Direction right to left", "ed_right_to_left.gif", false, function(e) {e.execCommand("righttoleft");} ]
+       };
+       /* ADDING CUSTOM BUTTONS
+        * ---------------------
+        *
+        * It is recommended that you add the custom buttons in an external
+        * file and leave this one unchanged.  That's because when we
+        * (InteractiveTools.com) release a new official version, it's less
+        * likely that you will have problems upgrading HTMLArea.
+        *
+        * Example on how to add a custom button when you construct the HTMLArea:
+        *
+        *   var editor = new HTMLArea("your_text_area_id");
+        *   var cfg = editor.config; // this is the default configuration
+        *   cfg.btnList["my-hilite"] =
+        *      [ function(editor) { editor.surroundHTML('<span style="background:yellow">', '</span>'); }, // action
+        *        "Highlight selection", // tooltip
+        *        "my_hilite.gif", // image
+        *        false // disabled in text mode
+        *      ];
+        *   cfg.toolbar.push(["linebreak", "my-hilite"]); // add the new button to the toolbar
+        *
+        * An alternate (also more convenient and recommended) way to
+        * accomplish this is to use the registerButton function below.
+        */
+       // initialize tooltips from the I18N module and generate correct image path
+       for (var i in this.btnList) {
+               var btn = this.btnList[i];
+               btn[1] = _editor_url + this.imgURL + btn[1];
+               if (typeof HTMLArea.I18N.tooltips[i] != "undefined") {
+                       btn[0] = HTMLArea.I18N.tooltips[i];
+               }
+       }
+};
+
+/** Helper function: register a new button with the configuration.  It can be
+ * called with all 5 arguments, or with only one (first one).  When called with
+ * only one argument it must be an object with the following properties: id,
+ * tooltip, image, textMode, action.  Examples:
+ *
+ * 1. config.registerButton("my-hilite", "Hilite text", "my-hilite.gif", false, function(editor) {...});
+ * 2. config.registerButton({
+ *      id       : "my-hilite",      // the ID of your button
+ *      tooltip  : "Hilite text",    // the tooltip
+ *      image    : "my-hilite.gif",  // image to be displayed in the toolbar
+ *      textMode : false,            // disabled in text mode
+ *      action   : function(editor) { // called when the button is clicked
+ *                   editor.surroundHTML('<span class="hilite">', '</span>');
+ *                 },
+ *      context  : "p"               // will be disabled if outside a <p> element
+ *    });
+ */
+HTMLArea.Config.prototype.registerButton = function(id, tooltip, image, textMode, action, context) {
+       var the_id;
+       if (typeof id == "string") {
+               the_id = id;
+       } else if (typeof id == "object") {
+               the_id = id.id;
+       } else {
+               alert("ERROR [HTMLArea.Config::registerButton]:\ninvalid arguments");
+               return false;
+       }
+       // check for existing id
+       if (typeof this.customSelects[the_id] != "undefined") {
+               // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA dropdown with the same ID already exists.");
+       }
+       if (typeof this.btnList[the_id] != "undefined") {
+               // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA button with the same ID already exists.");
+       }
+       switch (typeof id) {
+           case "string": this.btnList[id] = [ tooltip, image, textMode, action, context ]; break;
+           case "object": this.btnList[id.id] = [ id.tooltip, id.image, id.textMode, id.action, id.context ]; break;
+       }
+};
+
+/** The following helper function registers a dropdown box with the editor
+ * configuration.  You still have to add it to the toolbar, same as with the
+ * buttons.  Call it like this:
+ *
+ * FIXME: add example
+ */
+HTMLArea.Config.prototype.registerDropdown = function(object) {
+       // check for existing id
+       if (typeof this.customSelects[object.id] != "undefined") {
+               // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA dropdown with the same ID already exists.");
+       }
+       if (typeof this.btnList[object.id] != "undefined") {
+               // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA button with the same ID already exists.");
+       }
+       this.customSelects[object.id] = object;
+};
+
+/** Call this function to remove some buttons/drop-down boxes from the toolbar.
+ * Pass as the only parameter a string containing button/drop-down names
+ * delimited by spaces.  Note that the string should also begin with a space
+ * and end with a space.  Example:
+ *
+ *   config.hideSomeButtons(" fontname fontsize textindicator ");
+ *
+ * It's useful because it's easier to remove stuff from the defaul toolbar than
+ * create a brand new toolbar ;-)
+ */
+HTMLArea.Config.prototype.hideSomeButtons = function(remove) {
+       var toolbar = this.toolbar;
+       for (var i in toolbar) {
+               var line = toolbar[i];
+               for (var j = line.length; --j >= 0; ) {
+                       if (remove.indexOf(" " + line[j] + " ") >= 0) {
+                               var len = 1;
+                               if (/separator|space/.test(line[j + 1])) {
+                                       len = 2;
+                               }
+                               line.splice(j, len);
+                       }
+               }
+       }
+};
+
+/** Helper function: replace all TEXTAREA-s in the document with HTMLArea-s. */
+HTMLArea.replaceAll = function(config) {
+       var tas = document.getElementsByTagName("textarea");
+       for (var i = tas.length; i > 0; (new HTMLArea(tas[--i], config)).generate());
+};
+
+/** Helper function: replaces the TEXTAREA with the given ID with HTMLArea. */
+HTMLArea.replace = function(id, config) {
+       var ta = HTMLArea.getElementById("textarea", id);
+       return ta ? (new HTMLArea(ta, config)).generate() : null;
+};
+
+// Creates the toolbar and appends it to the _htmlarea
+HTMLArea.prototype._createToolbar = function () {
+       var editor = this;      // to access this in nested functions
+
+       var toolbar = document.createElement("div");
+       this._toolbar = toolbar;
+       toolbar.className = "toolbar";
+       toolbar.unselectable = "1";
+       var tb_row = null;
+       var tb_objects = new Object();
+       this._toolbarObjects = tb_objects;
+
+       // creates a new line in the toolbar
+       function newLine() {
+               var table = document.createElement("table");
+               table.border = "0px";
+               table.cellSpacing = "0px";
+               table.cellPadding = "0px";
+               toolbar.appendChild(table);
+               // TBODY is required for IE, otherwise you don't see anything
+               // in the TABLE.
+               var tb_body = document.createElement("tbody");
+               table.appendChild(tb_body);
+               tb_row = document.createElement("tr");
+               tb_body.appendChild(tb_row);
+       }; // END of function: newLine
+       // init first line
+       newLine();
+
+       // updates the state of a toolbar element.  This function is member of
+       // a toolbar element object (unnamed objects created by createButton or
+       // createSelect functions below).
+       function setButtonStatus(id, newval) {
+               var oldval = this[id];
+               var el = this.element;
+               if (oldval != newval) {
+                       switch (id) {
+                           case "enabled":
+                               if (newval) {
+                                       HTMLArea._removeClass(el, "buttonDisabled");
+                                       el.disabled = false;
+                               } else {
+                                       HTMLArea._addClass(el, "buttonDisabled");
+                                       el.disabled = true;
+                               }
+                               break;
+                           case "active":
+                               if (newval) {
+                                       HTMLArea._addClass(el, "buttonPressed");
+                               } else {
+                                       HTMLArea._removeClass(el, "buttonPressed");
+                               }
+                               break;
+                       }
+                       this[id] = newval;
+               }
+       }; // END of function: setButtonStatus
+
+       // this function will handle creation of combo boxes.  Receives as
+       // parameter the name of a button as defined in the toolBar config.
+       // This function is called from createButton, above, if the given "txt"
+       // doesn't match a button.
+       function createSelect(txt) {
+               var options = null;
+               var el = null;
+               var cmd = null;
+               var customSelects = editor.config.customSelects;
+               var context = null;
+               switch (txt) {
+                   case "fontsize":
+                   case "fontname":
+                   case "formatblock":
+                       // the following line retrieves the correct
+                       // configuration option because the variable name
+                       // inside the Config object is named the same as the
+                       // button/select in the toolbar.  For instance, if txt
+                       // == "formatblock" we retrieve config.formatblock (or
+                       // a different way to write it in JS is
+                       // config["formatblock"].
+                       options = editor.config[txt];
+                       cmd = txt;
+                       break;
+                   default:
+                       // try to fetch it from the list of registered selects
+                       cmd = txt;
+                       var dropdown = customSelects[cmd];
+                       if (typeof dropdown != "undefined") {
+                               options = dropdown.options;
+                               context = dropdown.context;
+                       } else {
+                               alert("ERROR [createSelect]:\nCan't find the requested dropdown definition");
+                       }
+                       break;
+               }
+               if (options) {
+                       el = document.createElement("select");
+                       var obj = {
+                               name    : txt, // field name
+                               element : el,   // the UI element (SELECT)
+                               enabled : true, // is it enabled?
+                               text    : false, // enabled in text mode?
+                               cmd     : cmd, // command ID
+                               state   : setButtonStatus, // for changing state
+                               context : context
+                       };
+                       tb_objects[txt] = obj;
+                       for (var i in options) {
+                               var op = document.createElement("option");
+                               op.appendChild(document.createTextNode(i));
+                               op.value = options[i];
+                               el.appendChild(op);
+                       }
+                       HTMLArea._addEvent(el, "change", function () {
+                               editor._comboSelected(el, txt);
+                       });
+               }
+               return el;
+       }; // END of function: createSelect
+
+       // appends a new button to toolbar
+       function createButton(txt) {
+               // the element that will be created
+               var el = null;
+               var btn = null;
+               switch (txt) {
+                   case "separator":
+                       el = document.createElement("div");
+                       el.className = "separator";
+                       break;
+                   case "space":
+                       el = document.createElement("div");
+                       el.className = "space";
+                       break;
+                   case "linebreak":
+                       newLine();
+                       return false;
+                   case "textindicator":
+                       el = document.createElement("div");
+                       el.appendChild(document.createTextNode("A"));
+                       el.className = "indicator";
+                       el.title = HTMLArea.I18N.tooltips.textindicator;
+                       var obj = {
+                               name    : txt, // the button name (i.e. 'bold')
+                               element : el, // the UI element (DIV)
+                               enabled : true, // is it enabled?
+                               active  : false, // is it pressed?
+                               text    : false, // enabled in text mode?
+                               cmd     : "textindicator", // the command ID
+                               state   : setButtonStatus // for changing state
+                       };
+                       tb_objects[txt] = obj;
+                       break;
+                   default:
+                       btn = editor.config.btnList[txt];
+               }
+               if (!el && btn) {
+                       el = document.createElement("div");
+                       el.title = btn[0];
+                       el.className = "button";
+                       // let's just pretend we have a button object, and
+                       // assign all the needed information to it.
+                       var obj = {
+                               name    : txt, // the button name (i.e. 'bold')
+                               element : el, // the UI element (DIV)
+                               enabled : true, // is it enabled?
+                               active  : false, // is it pressed?
+                               text    : btn[2], // enabled in text mode?
+                               cmd     : btn[3], // the command ID
+                               state   : setButtonStatus, // for changing state
+                               context : btn[4] || null // enabled in a certain context?
+                       };
+                       tb_objects[txt] = obj;
+                       // handlers to emulate nice flat toolbar buttons
+                       HTMLArea._addEvent(el, "mouseover", function () {
+                               if (obj.enabled) {
+                                       HTMLArea._addClass(el, "buttonHover");
+                               }
+                       });
+                       HTMLArea._addEvent(el, "mouseout", function () {
+                               if (obj.enabled) with (HTMLArea) {
+                                       _removeClass(el, "buttonHover");
+                                       _removeClass(el, "buttonActive");
+                                       (obj.active) && _addClass(el, "buttonPressed");
+                               }
+                       });
+                       HTMLArea._addEvent(el, "mousedown", function (ev) {
+                               if (obj.enabled) with (HTMLArea) {
+                                       _addClass(el, "buttonActive");
+                                       _removeClass(el, "buttonPressed");
+                                       _stopEvent(is_ie ? window.event : ev);
+                               }
+                       });
+                       // when clicked, do the following:
+                       HTMLArea._addEvent(el, "click", function (ev) {
+                               if (obj.enabled) with (HTMLArea) {
+                                       _removeClass(el, "buttonActive");
+                                       _removeClass(el, "buttonHover");
+                                       obj.cmd(editor, obj.name, obj);
+                                       _stopEvent(is_ie ? window.event : ev);
+                               }
+                       });
+                       var img = document.createElement("img");
+                       img.src = btn[1];
+                       img.style.width = "18px";
+                       img.style.height = "18px";
+                       el.appendChild(img);
+               } else if (!el) {
+                       el = createSelect(txt);
+               }
+               if (el) {
+                       var tb_cell = document.createElement("td");
+                       tb_row.appendChild(tb_cell);
+                       tb_cell.appendChild(el);
+               } else {
+                       alert("FIXME: Unknown toolbar item: " + txt);
+               }
+               return el;
+       };
+
+       var first = true;
+       for (var i in this.config.toolbar) {
+               if (!first) {
+                       createButton("linebreak");
+               } else {
+                       first = false;
+               }
+               var group = this.config.toolbar[i];
+               for (var j in group) {
+                       var code = group[j];
+                       if (/^([IT])\[(.*?)\]/.test(code)) {
+                               // special case, create text label
+                               var l7ed = RegExp.$1 == "I"; // localized?
+                               var label = RegExp.$2;
+                               if (l7ed) {
+                                       label = HTMLArea.I18N.custom[label];
+                               }
+                               var tb_cell = document.createElement("td");
+                               tb_row.appendChild(tb_cell);
+                               tb_cell.className = "label";
+                               tb_cell.innerHTML = label;
+                       } else {
+                               createButton(code);
+                       }
+               }
+       }
+
+       this._htmlArea.appendChild(toolbar);
+};
+
+HTMLArea.prototype._createStatusBar = function() {
+       var statusbar = document.createElement("div");
+       statusbar.className = "statusBar";
+       this._htmlArea.appendChild(statusbar);
+       this._statusBar = statusbar;
+       // statusbar.appendChild(document.createTextNode(HTMLArea.I18N.msg["Path"] + ": "));
+       // creates a holder for the path view
+       div = document.createElement("span");
+       div.className = "statusBarTree";
+       div.innerHTML = HTMLArea.I18N.msg["Path"] + ": ";
+       this._statusBarTree = div;
+       this._statusBar.appendChild(div);
+       if (!this.config.statusBar) {
+               // disable it...
+               statusbar.style.display = "none";
+       }
+};
+
+// Creates the HTMLArea object and replaces the textarea with it.
+HTMLArea.prototype.generate = function () {
+       var editor = this;      // we'll need "this" in some nested functions
+       // get the textarea
+       var textarea = this._textArea;
+       if (typeof textarea == "string") {
+               // it's not element but ID
+               this._textArea = textarea = HTMLArea.getElementById("textarea", textarea);
+       }
+       this._ta_size = {
+               w: textarea.offsetWidth,
+               h: textarea.offsetHeight
+       };
+       textarea.style.display = "none";
+
+       // create the editor framework
+       var htmlarea = document.createElement("div");
+       htmlarea.className = "htmlarea";
+       this._htmlArea = htmlarea;
+
+       // insert the editor before the textarea.
+       textarea.parentNode.insertBefore(htmlarea, textarea);
+
+       if (textarea.form) {
+               // we have a form, on submit get the HTMLArea content and
+               // update original textarea.
+               var f = textarea.form;
+               if (typeof f.onsubmit == "function") {
+                       var funcref = f.onsubmit;
+                       if (typeof f.__msh_prevOnSubmit == "undefined") {
+                               f.__msh_prevOnSubmit = [];
+                       }
+                       f.__msh_prevOnSubmit.push(funcref);
+               }
+               f.onsubmit = function() {
+                       editor._textArea.value = editor.getHTML();
+                       var a = this.__msh_prevOnSubmit;
+                       // call previous submit methods if they were there.
+                       if (typeof a != "undefined") {
+                               for (var i in a) {
+                                       a[i]();
+                               }
+                       }
+               };
+       }
+
+       // add a handler for the "back/forward" case -- on body.unload we save
+       // the HTML content into the original textarea.
+       window.onunload = function() {
+               editor._textArea.value = editor.getHTML();
+       };
+
+       // creates & appends the toolbar
+       this._createToolbar();
+
+       // create the IFRAME
+       var iframe = document.createElement("iframe");
+       htmlarea.appendChild(iframe);
+
+       this._iframe = iframe;
+
+       // creates & appends the status bar, if the case
+       this._createStatusBar();
+
+       // remove the default border as it keeps us from computing correctly
+       // the sizes.  (somebody tell me why doesn't this work in IE)
+
+       if (!HTMLArea.is_ie) {
+               iframe.style.borderWidth = "1px";
+       // iframe.frameBorder = "1";
+       // iframe.marginHeight = "0";
+       // iframe.marginWidth = "0";
+       }
+
+       // size the IFRAME according to user's prefs or initial textarea
+       var height = (this.config.height == "auto" ? (this._ta_size.h + "px") : this.config.height);
+       height = parseInt(height);
+       var width = (this.config.width == "auto" ? (this._ta_size.w + "px") : this.config.width);
+       width = parseInt(width);
+
+       if (!HTMLArea.is_ie) {
+               height -= 2;
+               width -= 2;
+       }
+
+       iframe.style.width = width + "px";
+       if (this.config.sizeIncludesToolbar) {
+               // substract toolbar height
+               height -= this._toolbar.offsetHeight;
+               height -= this._statusBar.offsetHeight;
+       }
+       if (height < 0) {
+               height = 0;
+       }
+       iframe.style.height = height + "px";
+
+       // the editor including the toolbar now have the same size as the
+       // original textarea.. which means that we need to reduce that a bit.
+       textarea.style.width = iframe.style.width;
+       textarea.style.height = iframe.style.height;
+
+       // IMPORTANT: we have to allow Mozilla a short time to recognize the
+       // new frame.  Otherwise we get a stupid exception.
+       function initIframe() {
+               var doc = editor._iframe.contentWindow.document;
+               if (!doc) {
+                       // Try again..
+                       // FIXME: don't know what else to do here.  Normally
+                       // we'll never reach this point.
+                       if (HTMLArea.is_gecko) {
+                               setTimeout(initIframe, 100);
+                               return false;
+                       } else {
+                               alert("ERROR: IFRAME can't be initialized.");
+                       }
+               }
+               if (HTMLArea.is_gecko) {
+                       // enable editable mode for Mozilla
+                       doc.designMode = "on";
+               }
+               editor._doc = doc;
+               if (!editor.config.fullPage) {
+                       doc.open();
+                       var html = "<html>\n";
+                       html += "<head>\n";
+                       if (editor.config.baseURL)
+                               html += '<base href="' + editor.config.baseURL + '" />';
+                       html += "<style> html,body { border: 0px; } " +
+                               editor.config.pageStyle + "</style>\n";
+                       html += "</head>\n";
+                       html += "<body>\n";
+                       html += editor._textArea.value;
+                       html += "</body>\n";
+                       html += "</html>";
+                       doc.write(html);
+                       doc.close();
+               } else {
+                       var html = editor._textArea.value;
+                       if (html.match(HTMLArea.RE_doctype)) {
+                               editor.setDoctype(RegExp.$1);
+                               html = html.replace(HTMLArea.RE_doctype, "");
+                       }
+                       doc.open();
+                       doc.write(html);
+                       doc.close();
+               }
+
+               if (HTMLArea.is_ie) {
+                       // enable editable mode for IE.  For some reason this
+                       // doesn't work if done in the same place as for Gecko
+                       // (above).
+                       doc.body.contentEditable = true;
+               }
+
+               editor.focusEditor();
+               // intercept some events; for updating the toolbar & keyboard handlers
+               HTMLArea._addEvents
+                       (doc, ["keydown", "keypress", "mousedown", "mouseup", "drag"],
+                        function (event) {
+                                return editor._editorEvent(HTMLArea.is_ie ? editor._iframe.contentWindow.event : event);
+                        });
+
+               // check if any plugins have registered refresh handlers
+               for (var i in editor.plugins) {
+                       var plugin = editor.plugins[i].instance;
+                       if (typeof plugin.onGenerate == "function")
+                               plugin.onGenerate();
+               }
+
+               setTimeout(function() {
+                       editor.updateToolbar();
+               }, 250);
+
+               if (typeof editor.onGenerate == "function")
+                       editor.onGenerate();
+       };
+       setTimeout(initIframe, 100);
+};
+
+// Switches editor mode; parameter can be "textmode" or "wysiwyg".  If no
+// parameter was passed this function toggles between modes.
+HTMLArea.prototype.setMode = function(mode) {
+       if (typeof mode == "undefined") {
+               mode = ((this._editMode == "textmode") ? "wysiwyg" : "textmode");
+       }
+       switch (mode) {
+           case "textmode":
+               this._textArea.value = this.getHTML();
+               this._iframe.style.display = "none";
+               this._textArea.style.display = "block";
+               if (this.config.statusBar) {
+                       this._statusBar.innerHTML = HTMLArea.I18N.msg["TEXT_MODE"];
+               }
+               break;
+           case "wysiwyg":
+               if (HTMLArea.is_gecko) {
+                       // disable design mode before changing innerHTML
+                       try {
+                               this._doc.designMode = "off";
+                       } catch(e) {};
+               }
+               if (!this.config.fullPage)
+                       this._doc.body.innerHTML = this.getHTML();
+               else
+                       this.setFullHTML(this.getHTML());
+               this._iframe.style.display = "block";
+               this._textArea.style.display = "none";
+               if (HTMLArea.is_gecko) {
+                       // we need to refresh that info for Moz-1.3a
+                       try {
+                               this._doc.designMode = "on";
+                       } catch(e) {};
+               }
+               if (this.config.statusBar) {
+                       this._statusBar.innerHTML = '';
+                       this._statusBar.appendChild(document.createTextNode(HTMLArea.I18N.msg["Path"] + ": "));
+                       this._statusBar.appendChild(this._statusBarTree);
+               }
+               break;
+           default:
+               alert("Mode <" + mode + "> not defined!");
+               return false;
+       }
+       this._editMode = mode;
+       this.focusEditor();
+};
+
+HTMLArea.prototype.setFullHTML = function(html) {
+       var save_multiline = RegExp.multiline;
+       RegExp.multiline = true;
+       if (html.match(HTMLArea.RE_doctype)) {
+               this.setDoctype(RegExp.$1);
+               html = html.replace(HTMLArea.RE_doctype, "");
+       }
+       RegExp.multiline = save_multiline;
+       if (!HTMLArea.is_ie) {
+               if (html.match(HTMLArea.RE_head))
+                       this._doc.getElementsByTagName("head")[0].innerHTML = RegExp.$1;
+               if (html.match(HTMLArea.RE_body))
+                       this._doc.getElementsByTagName("body")[0].innerHTML = RegExp.$1;
+       } else {
+               var html_re = /<html>((.|\n)*?)<\/html>/i;
+               html = html.replace(html_re, "$1");
+               this._doc.open();
+               this._doc.write(html);
+               this._doc.close();
+               this._doc.body.contentEditable = true;
+               return true;
+       }
+};
+
+/***************************************************
+ *  Category: PLUGINS
+ ***************************************************/
+
+// this is the variant of the function above where the plugin arguments are
+// already packed in an array.  Externally, it should be only used in the
+// full-screen editor code, in order to initialize plugins with the same
+// parameters as in the opener window.
+HTMLArea.prototype.registerPlugin2 = function(plugin, args) {
+       if (typeof plugin == "string")
+               plugin = eval(plugin);
+       var obj = new plugin(this, args);
+       if (obj) {
+               var clone = {};
+               var info = plugin._pluginInfo;
+               for (var i in info)
+                       clone[i] = info[i];
+               clone.instance = obj;
+               clone.args = args;
+               this.plugins[plugin._pluginInfo.name] = clone;
+       } else
+               alert("Can't register plugin " + plugin.toString() + ".");
+};
+
+// Create the specified plugin and register it with this HTMLArea
+HTMLArea.prototype.registerPlugin = function() {
+       var plugin = arguments[0];
+       var args = [];
+       for (var i = 1; i < arguments.length; ++i)
+               args.push(arguments[i]);
+       this.registerPlugin2(plugin, args);
+};
+
+// static function that loads the required plugin and lang file, based on the
+// language loaded already for HTMLArea.  You better make sure that the plugin
+// _has_ that language, otherwise shit might happen ;-)
+HTMLArea.loadPlugin = function(pluginName) {
+       var dir = _editor_url + "plugins/" + pluginName;
+       var plugin = pluginName.replace(/([a-z])([A-Z])([a-z])/g,
+                                       function (str, l1, l2, l3) {
+                                               return l1 + "-" + l2.toLowerCase() + l3;
+                                       }).toLowerCase() + ".js";
+       var plugin_file = dir + "/" + plugin;
+       var plugin_lang = dir + "/lang/" + HTMLArea.I18N.lang + ".js";
+       HTMLArea._scripts.push(plugin_file, plugin_lang);
+       document.write("<script type='text/javascript' src='" + plugin_file + "'></script>");
+       document.write("<script type='text/javascript' src='" + plugin_lang + "'></script>");
+};
+
+HTMLArea.loadStyle = function(style, plugin) {
+       var url = _editor_url || '';
+       if (typeof plugin != "undefined") {
+               url += "plugins/" + plugin + "/";
+       }
+       url += style;
+       document.write("<style type='text/css'>@import url(" + url + ");</style>");
+};
+HTMLArea.loadStyle("htmlarea.css");
+
+/***************************************************
+ *  Category: EDITOR UTILITIES
+ ***************************************************/
+
+// The following function is a slight variation of the word cleaner code posted
+// by Weeezl (user @ InteractiveTools forums).
+HTMLArea.prototype._wordClean = function() {
+       var D = this.getInnerHTML();
+       if (D.indexOf('class=Mso') >= 0) {
+
+               // make one line
+               D = D.replace(/\r\n/g, ' ').
+                       replace(/\n/g, ' ').
+                       replace(/\r/g, ' ').
+                       replace(/\&nbsp\;/g,' ');
+
+               // keep tags, strip attributes
+               D = D.replace(/ class=[^\s|>]*/gi,'').
+                       //replace(/<p [^>]*TEXT-ALIGN: justify[^>]*>/gi,'<p align="justify">').
+                       replace(/ style=\"[^>]*\"/gi,'').
+                       replace(/ align=[^\s|>]*/gi,'');
+
+               //clean up tags
+               D = D.replace(/<b [^>]*>/gi,'<b>').
+                       replace(/<i [^>]*>/gi,'<i>').
+                       replace(/<li [^>]*>/gi,'<li>').
+                       replace(/<ul [^>]*>/gi,'<ul>');
+
+               // replace outdated tags
+               D = D.replace(/<b>/gi,'<strong>').
+                       replace(/<\/b>/gi,'</strong>');
+
+               // mozilla doesn't like <em> tags
+               D = D.replace(/<em>/gi,'<i>').
+                       replace(/<\/em>/gi,'</i>');
+
+               // kill unwanted tags
+               D = D.replace(/<\?xml:[^>]*>/g, '').       // Word xml
+                       replace(/<\/?st1:[^>]*>/g,'').     // Word SmartTags
+                       replace(/<\/?[a-z]\:[^>]*>/g,'').  // All other funny Word non-HTML stuff
+                       replace(/<\/?font[^>]*>/gi,'').    // Disable if you want to keep font formatting
+                       replace(/<\/?span[^>]*>/gi,' ').
+                       replace(/<\/?div[^>]*>/gi,' ').
+                       replace(/<\/?pre[^>]*>/gi,' ').
+                       replace(/<\/?h[1-6][^>]*>/gi,' ');
+
+               //remove empty tags
+               //D = D.replace(/<strong><\/strong>/gi,'').
+               //replace(/<i><\/i>/gi,'').
+               //replace(/<P[^>]*><\/P>/gi,'');
+
+               // nuke double tags
+               oldlen = D.length + 1;
+               while(oldlen > D.length) {
+                       oldlen = D.length;
+                       // join us now and free the tags, we'll be free hackers, we'll be free... ;-)
+                       D = D.replace(/<([a-z][a-z]*)> *<\/\1>/gi,' ').
+                               replace(/<([a-z][a-z]*)> *<([a-z][^>]*)> *<\/\1>/gi,'<$2>');
+               }
+               D = D.replace(/<([a-z][a-z]*)><\1>/gi,'<$1>').
+                       replace(/<\/([a-z][a-z]*)><\/\1>/gi,'<\/$1>');
+
+               // nuke double spaces
+               D = D.replace(/  */gi,' ');
+
+               this.setHTML(D);
+               this.updateToolbar();
+       }
+};
+
+HTMLArea.prototype.forceRedraw = function() {
+       this._doc.body.style.visibility = "hidden";
+       this._doc.body.style.visibility = "visible";
+       // this._doc.body.innerHTML = this.getInnerHTML();
+};
+
+// focuses the iframe window.  returns a reference to the editor document.
+HTMLArea.prototype.focusEditor = function() {
+       switch (this._editMode) {
+           case "wysiwyg" : this._iframe.contentWindow.focus(); break;
+           case "textmode": this._textArea.focus(); break;
+           default        : alert("ERROR: mode " + this._editMode + " is not defined");
+       }
+       return this._doc;
+};
+
+// takes a snapshot of the current text (for undo)
+HTMLArea.prototype._undoTakeSnapshot = function() {
+       ++this._undoPos;
+       if (this._undoPos >= this.config.undoSteps) {
+               // remove the first element
+               this._undoQueue.shift();
+               --this._undoPos;
+       }
+       // use the fasted method (getInnerHTML);
+       var take = true;
+       var txt = this.getInnerHTML();
+       if (this._undoPos > 0)
+               take = (this._undoQueue[this._undoPos - 1] != txt);
+       if (take) {
+               this._undoQueue[this._undoPos] = txt;
+       } else {
+               this._undoPos--;
+       }
+};
+
+HTMLArea.prototype.undo = function() {
+       if (this._undoPos > 0) {
+               var txt = this._undoQueue[--this._undoPos];
+               if (txt) this.setHTML(txt);
+               else ++this._undoPos;
+       }
+};
+
+HTMLArea.prototype.redo = function() {
+       if (this._undoPos < this._undoQueue.length - 1) {
+               var txt = this._undoQueue[++this._undoPos];
+               if (txt) this.setHTML(txt);
+               else --this._undoPos;
+       }
+};
+
+// updates enabled/disable/active state of the toolbar elements
+HTMLArea.prototype.updateToolbar = function(noStatus) {
+       var doc = this._doc;
+       var text = (this._editMode == "textmode");
+       var ancestors = null;
+       if (!text) {
+               ancestors = this.getAllAncestors();
+               if (this.config.statusBar && !noStatus) {
+                       this._statusBarTree.innerHTML = HTMLArea.I18N.msg["Path"] + ": "; // clear
+                       for (var i = ancestors.length; --i >= 0;) {
+                               var el = ancestors[i];
+                               if (!el) {
+                                       // hell knows why we get here; this
+                                       // could be a classic example of why
+                                       // it's good to check for conditions
+                                       // that are impossible to happen ;-)
+                                       continue;
+                               }
+                               var a = document.createElement("a");
+                               a.href = "#";
+                               a.el = el;
+                               a.editor = this;
+                               a.onclick = function() {
+                                       this.blur();
+                                       this.editor.selectNodeContents(this.el);
+                                       this.editor.updateToolbar(true);
+                                       return false;
+                               };
+                               a.oncontextmenu = function() {
+                                       // TODO: add context menu here
+                                       this.blur();
+                                       var info = "Inline style:\n\n";
+                                       info += this.el.style.cssText.split(/;\s*/).join(";\n");
+                                       alert(info);
+                                       return false;
+                               };
+                               var txt = el.tagName.toLowerCase();
+                               a.title = el.style.cssText;
+                               if (el.id) {
+                                       txt += "#" + el.id;
+                               }
+                               if (el.className) {
+                                       txt += "." + el.className;
+                               }
+                               a.appendChild(document.createTextNode(txt));
+                               this._statusBarTree.appendChild(a);
+                               if (i != 0) {
+                                       this._statusBarTree.appendChild(document.createTextNode(String.fromCharCode(0xbb)));
+                               }
+                       }
+               }
+       }
+       for (var i in this._toolbarObjects) {
+               var btn = this._toolbarObjects[i];
+               var cmd = i;
+               var inContext = true;
+               if (btn.context && !text) {
+                       inContext = false;
+                       var context = btn.context;
+                       var attrs = [];
+                       if (/(.*)\[(.*?)\]/.test(context)) {
+                               context = RegExp.$1;
+                               attrs = RegExp.$2.split(",");
+                       }
+                       context = context.toLowerCase();
+                       var match = (context == "*");
+                       for (var k in ancestors) {
+                               if (!ancestors[k]) {
+                                       // the impossible really happens.
+                                       continue;
+                               }
+                               if (match || (ancestors[k].tagName.toLowerCase() == context)) {
+                                       inContext = true;
+                                       for (var ka in attrs) {
+                                               if (!eval("ancestors[k]." + attrs[ka])) {
+                                                       inContext = false;
+                                                       break;
+                                               }
+                                       }
+                                       if (inContext) {
+                                               break;
+                                       }
+                               }
+                       }
+               }
+               btn.state("enabled", (!text || btn.text) && inContext);
+               if (typeof cmd == "function") {
+                       continue;
+               }
+               // look-it-up in the custom dropdown boxes
+               var dropdown = this.config.customSelects[cmd];
+               if ((!text || btn.text) && (typeof dropdown != "undefined")) {
+                       dropdown.refresh(this);
+                       continue;
+               }
+               switch (cmd) {
+                   case "fontname":
+                   case "fontsize":
+                   case "formatblock":
+                       if (!text) try {
+                               var value = ("" + doc.queryCommandValue(cmd)).toLowerCase();
+                               if (!value) {
+                                       // FIXME: what do we do here?
+                                       break;
+                               }
+                               // HACK -- retrieve the config option for this
+                               // combo box.  We rely on the fact that the
+                               // variable in config has the same name as
+                               // button name in the toolbar.
+                               var options = this.config[cmd];
+                               var k = 0;
+                               // btn.element.selectedIndex = 0;
+                               for (var j in options) {
+                                       // FIXME: the following line is scary.
+                                       if ((j.toLowerCase() == value) ||
+                                           (options[j].substr(0, value.length).toLowerCase() == value)) {
+                                               btn.element.selectedIndex = k;
+                                               break;
+                                       }
+                                       ++k;
+                               }
+                       } catch(e) {};
+                       break;
+                   case "textindicator":
+                       if (!text) {
+                               try {with (btn.element.style) {
+                                       backgroundColor = HTMLArea._makeColor(
+                                               doc.queryCommandValue(HTMLArea.is_ie ? "backcolor" : "hilitecolor"));
+                                       if (/transparent/i.test(backgroundColor)) {
+                                               // Mozilla
+                                               backgroundColor = HTMLArea._makeColor(doc.queryCommandValue("backcolor"));
+                                       }
+                                       color = HTMLArea._makeColor(doc.queryCommandValue("forecolor"));
+                                       fontFamily = doc.queryCommandValue("fontname");
+                                       fontWeight = doc.queryCommandState("bold") ? "bold" : "normal";
+                                       fontStyle = doc.queryCommandState("italic") ? "italic" : "normal";
+                               }} catch (e) {
+                                       // alert(e + "\n\n" + cmd);
+                               }
+                       }
+                       break;
+                   case "htmlmode": btn.state("active", text); break;
+                   case "lefttoright":
+                   case "righttoleft":
+                       var el = this.getParentElement();
+                       while (el && !HTMLArea.isBlockElement(el))
+                               el = el.parentNode;
+                       if (el)
+                               btn.state("active", (el.style.direction == ((cmd == "righttoleft") ? "rtl" : "ltr")));
+                       break;
+                   default:
+                       try {
+                               btn.state("active", (!text && doc.queryCommandState(cmd)));
+                       } catch (e) {}
+               }
+       }
+       // take undo snapshots
+       if (this._customUndo && !this._timerUndo) {
+               this._undoTakeSnapshot();
+               var editor = this;
+               this._timerUndo = setTimeout(function() {
+                       editor._timerUndo = null;
+               }, this.config.undoTimeout);
+       }
+       // check if any plugins have registered refresh handlers
+       for (var i in this.plugins) {
+               var plugin = this.plugins[i].instance;
+               if (typeof plugin.onUpdateToolbar == "function")
+                       plugin.onUpdateToolbar();
+       }
+};
+
+/** Returns a node after which we can insert other nodes, in the current
+ * selection.  The selection is removed.  It splits a text node, if needed.
+ */
+HTMLArea.prototype.insertNodeAtSelection = function(toBeInserted) {
+       if (!HTMLArea.is_ie) {
+               var sel = this._getSelection();
+               var range = this._createRange(sel);
+               // remove the current selection
+               sel.removeAllRanges();
+               range.deleteContents();
+               var node = range.startContainer;
+               var pos = range.startOffset;
+               switch (node.nodeType) {
+                   case 3: // Node.TEXT_NODE
+                       // we have to split it at the caret position.
+                       if (toBeInserted.nodeType == 3) {
+                               // do optimized insertion
+                               node.insertData(pos, toBeInserted.data);
+                               range = this._createRange();
+                               range.setEnd(node, pos + toBeInserted.length);
+                               range.setStart(node, pos + toBeInserted.length);
+                               sel.addRange(range);
+                       } else {
+                               node = node.splitText(pos);
+                               var selnode = toBeInserted;
+                               if (toBeInserted.nodeType == 11 /* Node.DOCUMENT_FRAGMENT_NODE */) {
+                                       selnode = selnode.firstChild;
+                               }
+                               node.parentNode.insertBefore(toBeInserted, node);
+                               this.selectNodeContents(selnode);
+                               this.updateToolbar();
+                       }
+                       break;
+                   case 1: // Node.ELEMENT_NODE
+                       var selnode = toBeInserted;
+                       if (toBeInserted.nodeType == 11 /* Node.DOCUMENT_FRAGMENT_NODE */) {
+                               selnode = selnode.firstChild;
+                       }
+                       node.insertBefore(toBeInserted, node.childNodes[pos]);
+                       this.selectNodeContents(selnode);
+                       this.updateToolbar();
+                       break;
+               }
+       } else {
+               return null;    // this function not yet used for IE <FIXME>
+       }
+};
+
+// Returns the deepest node that contains both endpoints of the selection.
+HTMLArea.prototype.getParentElement = function() {
+       var sel = this._getSelection();
+       var range = this._createRange(sel);
+       if (HTMLArea.is_ie) {
+               switch (sel.type) {
+                   case "Text":
+                   case "None":
+                       // It seems that even for selection of type "None",
+                       // there _is_ a parent element and it's value is not
+                       // only correct, but very important to us.  MSIE is
+                       // certainly the buggiest browser in the world and I
+                       // wonder, God, how can Earth stand it?
+                       return range.parentElement();
+                   case "Control":
+                       return range.item(0);
+                   default:
+                       return this._doc.body;
+               }
+       } else try {
+               var p = range.commonAncestorContainer;
+               if (!range.collapsed && range.startContainer == range.endContainer &&
+                   range.startOffset - range.endOffset <= 1 && range.startContainer.hasChildNodes())
+                       p = range.startContainer.childNodes[range.startOffset];
+               /*
+               alert(range.startContainer + ":" + range.startOffset + "\n" +
+                     range.endContainer + ":" + range.endOffset);
+               */
+               while (p.nodeType == 3) {
+                       p = p.parentNode;
+               }
+               return p;
+       } catch (e) {
+               return null;
+       }
+};
+
+// Returns an array with all the ancestor nodes of the selection.
+HTMLArea.prototype.getAllAncestors = function() {
+       var p = this.getParentElement();
+       var a = [];
+       while (p && (p.nodeType == 1) && (p.tagName.toLowerCase() != 'body')) {
+               a.push(p);
+               p = p.parentNode;
+       }
+       a.push(this._doc.body);
+       return a;
+};
+
+// Selects the contents inside the given node
+HTMLArea.prototype.selectNodeContents = function(node, pos) {
+       this.focusEditor();
+       this.forceRedraw();
+       var range;
+       var collapsed = (typeof pos != "undefined");
+       if (HTMLArea.is_ie) {
+               range = this._doc.body.createTextRange();
+               range.moveToElementText(node);
+               (collapsed) && range.collapse(pos);
+               range.select();
+       } else {
+               var sel = this._getSelection();
+               range = this._doc.createRange();
+               range.selectNodeContents(node);
+               (collapsed) && range.collapse(pos);
+               sel.removeAllRanges();
+               sel.addRange(range);
+       }
+};
+
+/** Call this function to insert HTML code at the current position.  It deletes
+ * the selection, if any.
+ */
+HTMLArea.prototype.insertHTML = function(html) {
+       var sel = this._getSelection();
+       var range = this._createRange(sel);
+       if (HTMLArea.is_ie) {
+               range.pasteHTML(html);
+       } else {
+               // construct a new document fragment with the given HTML
+               var fragment = this._doc.createDocumentFragment();
+               var div = this._doc.createElement("div");
+               div.innerHTML = html;
+               while (div.firstChild) {
+                       // the following call also removes the node from div
+                       fragment.appendChild(div.firstChild);
+               }
+               // this also removes the selection
+               var node = this.insertNodeAtSelection(fragment);
+       }
+};
+
+/**
+ *  Call this function to surround the existing HTML code in the selection with
+ *  your tags.  FIXME: buggy!  This function will be deprecated "soon".
+ */
+HTMLArea.prototype.surroundHTML = function(startTag, endTag) {
+       var html = this.getSelectedHTML();
+       // the following also deletes the selection
+       this.insertHTML(startTag + html + endTag);
+};
+
+/// Retrieve the selected block
+HTMLArea.prototype.getSelectedHTML = function() {
+       var sel = this._getSelection();
+       var range = this._createRange(sel);
+       var existing = null;
+       if (HTMLArea.is_ie) {
+               existing = range.htmlText;
+       } else {
+               existing = HTMLArea.getHTML(range.cloneContents(), false, this);
+       }
+       return existing;
+};
+
+/// Return true if we have some selection
+HTMLArea.prototype.hasSelectedText = function() {
+       // FIXME: come _on_ mishoo, you can do better than this ;-)
+       return this.getSelectedHTML() != '';
+};
+
+HTMLArea.prototype._createLink = function(link) {
+       var editor = this;
+       var outparam = null;
+       if (typeof link == "undefined") {
+               link = this.getParentElement();
+               if (link && !/^a$/i.test(link.tagName))
+                       link = null;
+       }
+       if (link) outparam = {
+               f_href   : HTMLArea.is_ie ? editor.stripBaseURL(link.href) : link.getAttribute("href"),
+               f_title  : link.title,
+               f_target : link.target
+       };
+       this._popupDialog("link.html", function(param) {
+               if (!param)
+                       return false;
+               var a = link;
+               if (!a) {
+                       editor._doc.execCommand("createlink", false, param.f_href);
+                       a = editor.getParentElement();
+                       var sel = editor._getSelection();
+                       var range = editor._createRange(sel);
+                       if (!HTMLArea.is_ie) {
+                               a = range.startContainer;
+                               if (!/^a$/i.test(a.tagName))
+                                       a = a.nextSibling;
+                       }
+               } else a.href = param.f_href.trim();
+               if (!/^a$/i.test(a.tagName))
+                       return false;
+               a.target = param.f_target.trim();
+               a.title = param.f_title.trim();
+               editor.selectNodeContents(a);
+               editor.updateToolbar();
+       }, outparam);
+};
+
+// Called when the user clicks on "InsertImage" button.  If an image is already
+// there, it will just modify it's properties.
+HTMLArea.prototype._insertImage = function(image) {
+       var editor = this;      // for nested functions
+       var outparam = null;
+       if (typeof image == "undefined") {
+               image = this.getParentElement();
+               if (image && !/^img$/i.test(image.tagName))
+                       image = null;
+       }
+       if (image) outparam = {
+               f_url    : HTMLArea.is_ie ? editor.stripBaseURL(image.src) : image.getAttribute("src"),
+               f_alt    : image.alt,
+               f_border : image.border,
+               f_align  : image.align,
+               f_vert   : image.vspace,
+               f_horiz  : image.hspace
+       };
+       this._popupDialog("insert_image.html", function(param) {
+               if (!param) {   // user must have pressed Cancel
+                       return false;
+               }
+               var img = image;
+               if (!img) {
+                       var sel = editor._getSelection();
+                       var range = editor._createRange(sel);
+                       editor._doc.execCommand("insertimage", false, param.f_url);
+                       if (HTMLArea.is_ie) {
+                               img = range.parentElement();
+                               // wonder if this works...
+                               if (img.tagName.toLowerCase() != "img") {
+                                       img = img.previousSibling;
+                               }
+                       } else {
+                               img = range.startContainer.previousSibling;
+                       }
+               } else {
+                       img.src = param.f_url;
+               }
+               for (field in param) {
+                       var value = param[field];
+                       switch (field) {
+                           case "f_alt"    : img.alt    = value; break;
+                           case "f_border" : img.border = parseInt(value || "0"); break;
+                           case "f_align"  : img.align  = value; break;
+                           case "f_vert"   : img.vspace = parseInt(value || "0"); break;
+                           case "f_horiz"  : img.hspace = parseInt(value || "0"); break;
+                       }
+               }
+       }, outparam);
+};
+
+// Called when the user clicks the Insert Table button
+HTMLArea.prototype._insertTable = function() {
+       var sel = this._getSelection();
+       var range = this._createRange(sel);
+       var editor = this;      // for nested functions
+       this._popupDialog("insert_table.html", function(param) {
+               if (!param) {   // user must have pressed Cancel
+                       return false;
+               }
+               var doc = editor._doc;
+               // create the table element
+               var table = doc.createElement("table");
+               // assign the given arguments
+               for (var field in param) {
+                       var value = param[field];
+                       if (!value) {
+                               continue;
+                       }
+                       switch (field) {
+                           case "f_width"   : table.style.width = value + param["f_unit"]; break;
+                           case "f_align"   : table.align       = value; break;
+                           case "f_border"  : table.border      = parseInt(value); break;
+                           case "f_spacing" : table.cellspacing = parseInt(value); break;
+                           case "f_padding" : table.cellpadding = parseInt(value); break;
+                       }
+               }
+               var tbody = doc.createElement("tbody");
+               table.appendChild(tbody);
+               for (var i = 0; i < param["f_rows"]; ++i) {
+                       var tr = doc.createElement("tr");
+                       tbody.appendChild(tr);
+                       for (var j = 0; j < param["f_cols"]; ++j) {
+                               var td = doc.createElement("td");
+                               tr.appendChild(td);
+                               // Mozilla likes to see something inside the cell.
+                               (HTMLArea.is_gecko) && td.appendChild(doc.createElement("br"));
+                       }
+               }
+               if (HTMLArea.is_ie) {
+                       range.pasteHTML(table.outerHTML);
+               } else {
+                       // insert the table
+                       editor.insertNodeAtSelection(table);
+               }
+               return true;
+       }, null);
+};
+
+/***************************************************
+ *  Category: EVENT HANDLERS
+ ***************************************************/
+
+// el is reference to the SELECT object
+// txt is the name of the select field, as in config.toolbar
+HTMLArea.prototype._comboSelected = function(el, txt) {
+       this.focusEditor();
+       var value = el.options[el.selectedIndex].value;
+       switch (txt) {
+           case "fontname":
+           case "fontsize": this.execCommand(txt, false, value); break;
+           case "formatblock":
+               (HTMLArea.is_ie) && (value = "<" + value + ">");
+               this.execCommand(txt, false, value);
+               break;
+           default:
+               // try to look it up in the registered dropdowns
+               var dropdown = this.config.customSelects[txt];
+               if (typeof dropdown != "undefined") {
+                       dropdown.action(this);
+               } else {
+                       alert("FIXME: combo box " + txt + " not implemented");
+               }
+       }
+};
+
+// the execCommand function (intercepts some commands and replaces them with
+// our own implementation)
+HTMLArea.prototype.execCommand = function(cmdID, UI, param) {
+       var editor = this;      // for nested functions
+       this.focusEditor();
+       cmdID = cmdID.toLowerCase();
+       switch (cmdID) {
+           case "htmlmode" : this.setMode(); break;
+           case "hilitecolor":
+               (HTMLArea.is_ie) && (cmdID = "backcolor");
+           case "forecolor":
+               this._popupDialog("select_color.html", function(color) {
+                       if (color) { // selection not canceled
+                               editor._doc.execCommand(cmdID, false, "#" + color);
+                       }
+               }, HTMLArea._colorToRgb(this._doc.queryCommandValue(cmdID)));
+               break;
+           case "createlink":
+               this._createLink();
+               break;
+           case "popupeditor":
+               // this object will be passed to the newly opened window
+               HTMLArea._object = this;
+               if (HTMLArea.is_ie) {
+                       //if (confirm(HTMLArea.I18N.msg["IE-sucks-full-screen"]))
+                       {
+                               window.open(this.popupURL("fullscreen.html"), "ha_fullscreen",
+                                           "toolbar=no,location=no,directories=no,status=no,menubar=no," +
+                                           "scrollbars=no,resizable=yes,width=640,height=480");
+                       }
+               } else {
+                       window.open(this.popupURL("fullscreen.html"), "ha_fullscreen",
+                                   "toolbar=no,menubar=no,personalbar=no,width=640,height=480," +
+                                   "scrollbars=no,resizable=yes");
+               }
+               break;
+           case "undo":
+           case "redo":
+               if (this._customUndo)
+                       this[cmdID]();
+               else
+                       this._doc.execCommand(cmdID, UI, param);
+               break;
+           case "inserttable": this._insertTable(); break;
+           case "insertimage": this._insertImage(); break;
+           case "about"    : this._popupDialog("about.html", null, this); break;
+           case "showhelp" : window.open(_editor_url + "reference.html", "ha_help"); break;
+
+           case "killword": this._wordClean(); break;
+
+           case "cut":
+           case "copy":
+           case "paste":
+               try {
+                       if (this.config.killWordOnPaste)
+                               this._wordClean();
+                       this._doc.execCommand(cmdID, UI, param);
+               } catch (e) {
+                       if (HTMLArea.is_gecko) {
+                               if (confirm("Unprivileged scripts cannot access Cut/Copy/Paste programatically " +
+                                           "for security reasons.  Click OK to see a technical note at mozilla.org " +
+                                           "which shows you how to allow a script to access the clipboard."))
+                                       window.open("http://mozilla.org/editor/midasdemo/securityprefs.html");
+                       }
+               }
+               break;
+           case "lefttoright":
+           case "righttoleft":
+               var dir = (cmdID == "righttoleft") ? "rtl" : "ltr";
+               var el = this.getParentElement();
+               while (el && !HTMLArea.isBlockElement(el))
+                       el = el.parentNode;
+               if (el) {
+                       if (el.style.direction == dir)
+                               el.style.direction = "";
+                       else
+                               el.style.direction = dir;
+               }
+               break;
+           default: this._doc.execCommand(cmdID, UI, param);
+       }
+       this.updateToolbar();
+       return false;
+};
+
+/** A generic event handler for things that happen in the IFRAME's document.
+ * This function also handles key bindings. */
+HTMLArea.prototype._editorEvent = function(ev) {
+       var editor = this;
+       var keyEvent = (HTMLArea.is_ie && ev.type == "keydown") || (ev.type == "keypress");
+       if (keyEvent) {
+               for (var i in editor.plugins) {
+                       var plugin = editor.plugins[i].instance;
+                       if (typeof plugin.onKeyPress == "function") plugin.onKeyPress(ev);
+               }
+       }
+       if (keyEvent && ev.ctrlKey) {
+               var sel = null;
+               var range = null;
+               var key = String.fromCharCode(HTMLArea.is_ie ? ev.keyCode : ev.charCode).toLowerCase();
+               var cmd = null;
+               var value = null;
+               switch (key) {
+                   case 'a':
+                       if (!HTMLArea.is_ie) {
+                               // KEY select all
+                               sel = this._getSelection();
+                               sel.removeAllRanges();
+                               range = this._createRange();
+                               range.selectNodeContents(this._doc.body);
+                               sel.addRange(range);
+                               HTMLArea._stopEvent(ev);
+                       }
+                       break;
+
+                       // simple key commands follow
+
+                   case 'b': cmd = "bold"; break;
+                   case 'i': cmd = "italic"; break;
+                   case 'u': cmd = "underline"; break;
+                   case 's': cmd = "strikethrough"; break;
+                   case 'l': cmd = "justifyleft"; break;
+                   case 'e': cmd = "justifycenter"; break;
+                   case 'r': cmd = "justifyright"; break;
+                   case 'j': cmd = "justifyfull"; break;
+                   case 'z': cmd = "undo"; break;
+                   case 'y': cmd = "redo"; break;
+                   case 'v': cmd = "paste"; break;
+
+                   case '0': cmd = "killword"; break;
+
+                       // headings
+                   case '1':
+                   case '2':
+                   case '3':
+                   case '4':
+                   case '5':
+                   case '6':
+                       cmd = "formatblock";
+                       value = "h" + key;
+                       if (HTMLArea.is_ie) {
+                               value = "<" + value + ">";
+                       }
+                       break;
+               }
+               if (cmd) {
+                       // execute simple command
+                       this.execCommand(cmd, false, value);
+                       HTMLArea._stopEvent(ev);
+               }
+       }
+       /*
+       else if (keyEvent) {
+               // other keys here
+               switch (ev.keyCode) {
+                   case 13: // KEY enter
+                       // if (HTMLArea.is_ie) {
+                       this.insertHTML("<br />");
+                       HTMLArea._stopEvent(ev);
+                       // }
+                       break;
+               }
+       }
+       */
+       // update the toolbar state after some time
+       if (editor._timerToolbar) {
+               clearTimeout(editor._timerToolbar);
+       }
+       editor._timerToolbar = setTimeout(function() {
+               editor.updateToolbar();
+               editor._timerToolbar = null;
+       }, 50);
+};
+
+// retrieve the HTML
+HTMLArea.prototype.getHTML = function() {
+       switch (this._editMode) {
+           case "wysiwyg"  :
+               if (!this.config.fullPage) {
+                       return HTMLArea.getHTML(this._doc.body, false, this);
+               } else
+                       return this.doctype + "\n" + HTMLArea.getHTML(this._doc.documentElement, true, this);
+           case "textmode" : return this._textArea.value;
+           default         : alert("Mode <" + mode + "> not defined!");
+       }
+       return false;
+};
+
+// retrieve the HTML (fastest version, but uses innerHTML)
+HTMLArea.prototype.getInnerHTML = function() {
+       switch (this._editMode) {
+           case "wysiwyg"  :
+               if (!this.config.fullPage)
+                       return this._doc.body.innerHTML;
+               else
+                       return this.doctype + "\n" + this._doc.documentElement.innerHTML;
+           case "textmode" : return this._textArea.value;
+           default         : alert("Mode <" + mode + "> not defined!");
+       }
+       return false;
+};
+
+// completely change the HTML inside
+HTMLArea.prototype.setHTML = function(html) {
+       switch (this._editMode) {
+           case "wysiwyg"  :
+               if (!this.config.fullPage)
+                       this._doc.body.innerHTML = html;
+               else
+                       // this._doc.documentElement.innerHTML = html;
+                       this._doc.body.innerHTML = html;
+               break;
+           case "textmode" : this._textArea.value = html; break;
+           default         : alert("Mode <" + mode + "> not defined!");
+       }
+       return false;
+};
+
+// sets the given doctype (useful when config.fullPage is true)
+HTMLArea.prototype.setDoctype = function(doctype) {
+       this.doctype = doctype;
+};
+
+/***************************************************
+ *  Category: UTILITY FUNCTIONS
+ ***************************************************/
+
+// browser identification
+
+HTMLArea.agt = navigator.userAgent.toLowerCase();
+HTMLArea.is_ie    = ((HTMLArea.agt.indexOf("msie") != -1) && (HTMLArea.agt.indexOf("opera") == -1));
+HTMLArea.is_opera  = (HTMLArea.agt.indexOf("opera") != -1);
+HTMLArea.is_mac           = (HTMLArea.agt.indexOf("mac") != -1);
+HTMLArea.is_mac_ie = (HTMLArea.is_ie && HTMLArea.is_mac);
+HTMLArea.is_win_ie = (HTMLArea.is_ie && !HTMLArea.is_mac);
+HTMLArea.is_gecko  = (navigator.product == "Gecko");
+
+// variable used to pass the object to the popup editor window.
+HTMLArea._object = null;
+
+// function that returns a clone of the given object
+HTMLArea.cloneObject = function(obj) {
+       var newObj = new Object;
+
+       // check for array objects
+       if (obj.constructor.toString().indexOf("function Array(") == 1) {
+               newObj = obj.constructor();
+       }
+
+       // check for function objects (as usual, IE is fucked up)
+       if (obj.constructor.toString().indexOf("function Function(") == 1) {
+               newObj = obj; // just copy reference to it
+       } else for (var n in obj) {
+               var node = obj[n];
+               if (typeof node == 'object') { newObj[n] = HTMLArea.cloneObject(node); }
+               else                         { newObj[n] = node; }
+       }
+
+       return newObj;
+};
+
+// FIXME!!! this should return false for IE < 5.5
+HTMLArea.checkSupportedBrowser = function() {
+       if (HTMLArea.is_gecko) {
+               if (navigator.productSub < 20021201) {
+                       alert("You need at least Mozilla-1.3 Alpha.\n" +
+                             "Sorry, your Gecko is not supported.");
+                       return false;
+               }
+               if (navigator.productSub < 20030210) {
+                       alert("Mozilla < 1.3 Beta is not supported!\n" +
+                             "I'll try, though, but it might not work.");
+               }
+       }
+       return HTMLArea.is_gecko || HTMLArea.is_ie;
+};
+
+// selection & ranges
+
+// returns the current selection object
+HTMLArea.prototype._getSelection = function() {
+       if (HTMLArea.is_ie) {
+               return this._doc.selection;
+       } else {
+               return this._iframe.contentWindow.getSelection();
+       }
+};
+
+// returns a range for the current selection
+HTMLArea.prototype._createRange = function(sel) {
+       if (HTMLArea.is_ie) {
+               return sel.createRange();
+       } else {
+               this.focusEditor();
+               if (typeof sel != "undefined") {
+                       try {
+                               return sel.getRangeAt(0);
+                       } catch(e) {
+                               return this._doc.createRange();
+                       }
+               } else {
+                       return this._doc.createRange();
+               }
+       }
+};
+
+// event handling
+
+HTMLArea._addEvent = function(el, evname, func) {
+       if (HTMLArea.is_ie) {
+               el.attachEvent("on" + evname, func);
+       } else {
+               el.addEventListener(evname, func, true);
+       }
+};
+
+HTMLArea._addEvents = function(el, evs, func) {
+       for (var i in evs) {
+               HTMLArea._addEvent(el, evs[i], func);
+       }
+};
+
+HTMLArea._removeEvent = function(el, evname, func) {
+       if (HTMLArea.is_ie) {
+               el.detachEvent("on" + evname, func);
+       } else {
+               el.removeEventListener(evname, func, true);
+       }
+};
+
+HTMLArea._removeEvents = function(el, evs, func) {
+       for (var i in evs) {
+               HTMLArea._removeEvent(el, evs[i], func);
+       }
+};
+
+HTMLArea._stopEvent = function(ev) {
+       if (HTMLArea.is_ie) {
+               ev.cancelBubble = true;
+               ev.returnValue = false;
+       } else {
+               ev.preventDefault();
+               ev.stopPropagation();
+       }
+};
+
+HTMLArea._removeClass = function(el, className) {
+       if (!(el && el.className)) {
+               return;
+       }
+       var cls = el.className.split(" ");
+       var ar = new Array();
+       for (var i = cls.length; i > 0;) {
+               if (cls[--i] != className) {
+                       ar[ar.length] = cls[i];
+               }
+       }
+       el.className = ar.join(" ");
+};
+
+HTMLArea._addClass = function(el, className) {
+       // remove the class first, if already there
+       HTMLArea._removeClass(el, className);
+       el.className += " " + className;
+};
+
+HTMLArea._hasClass = function(el, className) {
+       if (!(el && el.className)) {
+               return false;
+       }
+       var cls = el.className.split(" ");
+       for (var i = cls.length; i > 0;) {
+               if (cls[--i] == className) {
+                       return true;
+               }
+       }
+       return false;
+};
+
+HTMLArea.isBlockElement = function(el) {
+       var blockTags = " body form textarea fieldset ul ol dl li div " +
+               "p h1 h2 h3 h4 h5 h6 quote pre table thead " +
+               "tbody tfoot tr td iframe address ";
+       return (blockTags.indexOf(" " + el.tagName.toLowerCase() + " ") != -1);
+};
+
+HTMLArea.needsClosingTag = function(el) {
+       var closingTags = " head script style div span tr td tbody table em strong font a title ";
+       return (closingTags.indexOf(" " + el.tagName.toLowerCase() + " ") != -1);
+};
+
+// performs HTML encoding of some given string
+HTMLArea.htmlEncode = function(str) {
+       // we don't need regexp for that, but.. so be it for now.
+       str = str.replace(/&/ig, "&amp;");
+       str = str.replace(/</ig, "&lt;");
+       str = str.replace(/>/ig, "&gt;");
+       str = str.replace(/\x22/ig, "&quot;");
+       // \x22 means '"' -- we use hex reprezentation so that we don't disturb
+       // JS compressors (well, at least mine fails.. ;)
+       return str;
+};
+
+// Retrieves the HTML code from the given node.         This is a replacement for
+// getting innerHTML, using standard DOM calls.
+HTMLArea.getHTML = function(root, outputRoot, editor) {
+       var html = "";
+       switch (root.nodeType) {
+           case 1: // Node.ELEMENT_NODE
+           case 11: // Node.DOCUMENT_FRAGMENT_NODE
+               var closed;
+               var i;
+               var root_tag = (root.nodeType == 1) ? root.tagName.toLowerCase() : '';
+               if (HTMLArea.is_ie && root_tag == "head") {
+                       if (outputRoot)
+                               html += "<head>";
+                       // lowercasize
+                       var save_multiline = RegExp.multiline;
+                       RegExp.multiline = true;
+                       var txt = root.innerHTML.replace(HTMLArea.RE_tagName, function(str, p1, p2) {
+                               return p1 + p2.toLowerCase();
+                       });
+                       RegExp.multiline = save_multiline;
+                       html += txt;
+                       if (outputRoot)
+                               html += "</head>";
+                       break;
+               } else if (outputRoot) {
+                       closed = (!(root.hasChildNodes() || HTMLArea.needsClosingTag(root)));
+                       html = "<" + root.tagName.toLowerCase();
+                       var attrs = root.attributes;
+                       for (i = 0; i < attrs.length; ++i) {
+                               var a = attrs.item(i);
+                               if (!a.specified) {
+                                       continue;
+                               }
+                               var name = a.nodeName.toLowerCase();
+                               if (/_moz|contenteditable|_msh/.test(name)) {
+                                       // avoid certain attributes
+                                       continue;
+                               }
+                               var value;
+                               if (name != "style") {
+                                       // IE5.5 reports 25 when cellSpacing is
+                                       // 1; other values might be doomed too.
+                                       // For this reason we extract the
+                                       // values directly from the root node.
+                                       // I'm starting to HATE JavaScript
+                                       // development.  Browser differences
+                                       // suck.
+                                       //
+                                       // Using Gecko the values of href and src are converted to absolute links
+                                       // unless we get them using nodeValue()
+                                       if (typeof root[a.nodeName] != "undefined" && name != "href" && name != "src") {
+                                               value = root[a.nodeName];
+                                       } else {
+                                               value = a.nodeValue;
+                                               // IE seems not willing to return the original values - it converts to absolute
+                                               // links using a.nodeValue, a.value, a.stringValue, root.getAttribute("href")
+                                               // So we have to strip the baseurl manually -/
+                                               if (HTMLArea.is_ie && (name == "href" || name == "src")) {
+                                                       value = editor.stripBaseURL(value);
+                                               }
+                                       }
+                               } else { // IE fails to put style in attributes list
+                                       // FIXME: cssText reported by IE is UPPERCASE
+                                       value = root.style.cssText;
+                               }
+                               if (/(_moz|^$)/.test(value)) {
+                                       // Mozilla reports some special tags
+                                       // here; we don't need them.
+                                       continue;
+                               }
+                               html += " " + name + '="' + value + '"';
+                       }
+                       html += closed ? " />" : ">";
+               }
+               for (i = root.firstChild; i; i = i.nextSibling) {
+                       html += HTMLArea.getHTML(i, true, editor);
+               }
+               if (outputRoot && !closed) {
+                       html += "</" + root.tagName.toLowerCase() + ">";
+               }
+               break;
+           case 3: // Node.TEXT_NODE
+               // If a text node is alone in an element and all spaces, replace it with an non breaking one
+               // This partially undoes the damage done by moz, which translates '&nbsp;'s into spaces in the data element
+               if ( !root.previousSibling && !root.nextSibling && root.data.match(/^\s*$/i) ) html = '&nbsp;';
+               else html = HTMLArea.htmlEncode(root.data);
+               break;
+           case 8: // Node.COMMENT_NODE
+               html = "<!--" + root.data + "-->";
+               break;          // skip comments, for now.
+       }
+       return html;
+};
+
+HTMLArea.prototype.stripBaseURL = function(string) {
+       var baseurl = this.config.baseURL;
+
+       // strip to last directory in case baseurl points to a file
+       baseurl = baseurl.replace(/[^\/]+$/, '');
+       var basere = new RegExp(baseurl);
+       string = string.replace(basere, "");
+
+       // strip host-part of URL which is added by MSIE to links relative to server root
+       baseurl = baseurl.replace(/^(https?:\/\/[^\/]+)(.*)$/, '$1');
+       basere = new RegExp(baseurl);
+       return string.replace(basere, "");
+};
+
+String.prototype.trim = function() {
+       a = this.replace(/^\s+/, '');
+       return a.replace(/\s+$/, '');
+};
+
+// creates a rgb-style color from a number
+HTMLArea._makeColor = function(v) {
+       if (typeof v != "number") {
+               // already in rgb (hopefully); IE doesn't get here.
+               return v;
+       }
+       // IE sends number; convert to rgb.
+       var r = v & 0xFF;
+       var g = (v >> 8) & 0xFF;
+       var b = (v >> 16) & 0xFF;
+       return "rgb(" + r + "," + g + "," + b + ")";
+};
+
+// returns hexadecimal color representation from a number or a rgb-style color.
+HTMLArea._colorToRgb = function(v) {
+       if (!v)
+               return '';
+
+       // returns the hex representation of one byte (2 digits)
+       function hex(d) {
+               return (d < 16) ? ("0" + d.toString(16)) : d.toString(16);
+       };
+
+       if (typeof v == "number") {
+               // we're talking to IE here
+               var r = v & 0xFF;
+               var g = (v >> 8) & 0xFF;
+               var b = (v >> 16) & 0xFF;
+               return "#" + hex(r) + hex(g) + hex(b);
+       }
+
+       if (v.substr(0, 3) == "rgb") {
+               // in rgb(...) form -- Mozilla
+               var re = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/;
+               if (v.match(re)) {
+                       var r = parseInt(RegExp.$1);
+                       var g = parseInt(RegExp.$2);
+                       var b = parseInt(RegExp.$3);
+                       return "#" + hex(r) + hex(g) + hex(b);
+               }
+               // doesn't match RE?!  maybe uses percentages or float numbers
+               // -- FIXME: not yet implemented.
+               return null;
+       }
+
+       if (v.substr(0, 1) == "#") {
+               // already hex rgb (hopefully :D )
+               return v;
+       }
+
+       // if everything else fails ;)
+       return null;
+};
+
+// modal dialogs for Mozilla (for IE we're using the showModalDialog() call).
+
+// receives an URL to the popup dialog and a function that receives one value;
+// this function will get called after the dialog is closed, with the return
+// value of the dialog.
+HTMLArea.prototype._popupDialog = function(url, action, init) {
+       Dialog(this.popupURL(url), action, init);
+};
+
+// paths
+
+HTMLArea.prototype.imgURL = function(file, plugin) {
+       if (typeof plugin == "undefined")
+               return _editor_url + file;
+       else
+               return _editor_url + "plugins/" + plugin + "/img/" + file;
+};
+
+HTMLArea.prototype.popupURL = function(file) {
+       var url = "";
+       if (file.match(/^plugin:\/\/(.*?)\/(.*)/)) {
+               var plugin = RegExp.$1;
+               var popup = RegExp.$2;
+               if (!/\.html$/.test(popup))
+                       popup += ".html";
+               url = _editor_url + "plugins/" + plugin + "/popups/" + popup;
+       } else
+               url = _editor_url + this.config.popupURL + file;
+       return url;
+};
+
+/**
+ * FIX: Internet Explorer returns an item having the _name_ equal to the given
+ * id, even if it's not having any id.  This way it can return a different form
+ * field even if it's not a textarea.  This workarounds the problem by
+ * specifically looking to search only elements having a certain tag name.
+ */
+HTMLArea.getElementById = function(tag, id) {
+       var el, i, objs = document.getElementsByTagName(tag);
+       for (i = objs.length; --i >= 0 && (el = objs[i]);)
+               if (el.id == id)
+                       return el;
+       return null;
+};
+
+
+
+// EOF
+// Local variables: //
+// c-basic-offset:8 //
+// indent-tabs-mode:t //
+// End: //
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_about.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_about.gif
new file mode 100644 (file)
index 0000000..f0a338b
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_about.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_align_center.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_align_center.gif
new file mode 100644 (file)
index 0000000..9505db2
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_align_center.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_align_justify.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_align_justify.gif
new file mode 100644 (file)
index 0000000..29cf731
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_align_justify.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_align_left.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_align_left.gif
new file mode 100644 (file)
index 0000000..d0356d4
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_align_left.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_align_right.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_align_right.gif
new file mode 100644 (file)
index 0000000..b9f7a96
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_align_right.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_blank.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_blank.gif
new file mode 100644 (file)
index 0000000..1ea396b
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_blank.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_charmap.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_charmap.gif
new file mode 100644 (file)
index 0000000..9fac54d
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_charmap.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_color_bg.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_color_bg.gif
new file mode 100644 (file)
index 0000000..8b464c9
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_color_bg.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_color_fg.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_color_fg.gif
new file mode 100644 (file)
index 0000000..44af9c4
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_color_fg.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_copy.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_copy.gif
new file mode 100644 (file)
index 0000000..975740a
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_copy.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_custom.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_custom.gif
new file mode 100644 (file)
index 0000000..9529a52
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_custom.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_cut.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_cut.gif
new file mode 100644 (file)
index 0000000..2066038
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_cut.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_delete.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_delete.gif
new file mode 100644 (file)
index 0000000..3c3df5b
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_delete.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_bold.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_bold.gif
new file mode 100644 (file)
index 0000000..c6291f0
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_bold.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_italic.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_italic.gif
new file mode 100644 (file)
index 0000000..7bb67aa
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_italic.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_strike.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_strike.gif
new file mode 100644 (file)
index 0000000..0e00304
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_strike.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_sub.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_sub.gif
new file mode 100644 (file)
index 0000000..effcf57
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_sub.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_sup.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_sup.gif
new file mode 100644 (file)
index 0000000..1b6f401
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_sup.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_underline.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_underline.gif
new file mode 100644 (file)
index 0000000..ef8c19e
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_format_underline.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_help.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_help.gif
new file mode 100644 (file)
index 0000000..06c2256
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_help.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_hr.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_hr.gif
new file mode 100644 (file)
index 0000000..9f6e5e8
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_hr.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_html.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_html.gif
new file mode 100644 (file)
index 0000000..807f084
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_html.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_image.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_image.gif
new file mode 100644 (file)
index 0000000..9d2bff1
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_image.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_indent_less.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_indent_less.gif
new file mode 100644 (file)
index 0000000..f320b3e
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_indent_less.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_indent_more.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_indent_more.gif
new file mode 100644 (file)
index 0000000..a67139d
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_indent_more.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_left_to_right.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_left_to_right.gif
new file mode 100644 (file)
index 0000000..9edfa63
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_left_to_right.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_link.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_link.gif
new file mode 100644 (file)
index 0000000..76e568b
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_link.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_list_bullet.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_list_bullet.gif
new file mode 100644 (file)
index 0000000..caedfd2
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_list_bullet.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_list_num.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_list_num.gif
new file mode 100644 (file)
index 0000000..427839d
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_list_num.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_paste.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_paste.gif
new file mode 100644 (file)
index 0000000..13e2324
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_paste.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_redo.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_redo.gif
new file mode 100644 (file)
index 0000000..2bc002a
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_redo.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_right_to_left.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_right_to_left.gif
new file mode 100644 (file)
index 0000000..231f183
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_right_to_left.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_save.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_save.gif
new file mode 100644 (file)
index 0000000..df3aaab
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_save.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_save.png b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_save.png
new file mode 100644 (file)
index 0000000..a87f92b
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_save.png differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_show_border.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_show_border.gif
new file mode 100644 (file)
index 0000000..9e3fdd2
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_show_border.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_splitcel.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_splitcel.gif
new file mode 100644 (file)
index 0000000..a619d8a
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_splitcel.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_undo.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_undo.gif
new file mode 100644 (file)
index 0000000..f90faad
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/ed_undo.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/fullscreen_maximize.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/fullscreen_maximize.gif
new file mode 100644 (file)
index 0000000..07620bc
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/fullscreen_maximize.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/fullscreen_minimize.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/fullscreen_minimize.gif
new file mode 100644 (file)
index 0000000..09c0383
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/fullscreen_minimize.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/insert_table.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/insert_table.gif
new file mode 100644 (file)
index 0000000..027f7c8
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/insert_table.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/makefile.xml b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/images/makefile.xml
new file mode 100644 (file)
index 0000000..19e075f
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<files>
+  <file name="*.{gif,jpg,jpeg}" />
+</files>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/index.html b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/index.html
new file mode 100644 (file)
index 0000000..88f45ae
--- /dev/null
@@ -0,0 +1,199 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN">
+<html>
+  <head>
+    <title>HTMLArea -- the free, customizable online editor</title>
+
+    <style type="text/css">
+      html, body { font-family: georgia,"times new roman",serif; background-color: #fff; color: #000; }
+      .label { text-align: right; padding-right: 0.3em; }
+      .bline { border-bottom: 1px solid #aaa; }
+    </style>
+  </head>
+
+  <body>
+    <div style="float: right; border: 1px solid #aaa; background-color: #eee; padding: 3px; margin-left: 10px; margin-bottom: 10px;">
+      <table cellspacing="0" cellpadding="0" border="0">
+        <tr>
+          <td class="label">Version:</td><td>3.0</td>
+        </tr>
+        <tr>
+          <td class="label">Release:</td><td>rc1 (<a href="release-notes.html">release notes</a>)</td>
+        </tr>
+        <tr>
+          <td class="label bline">Compiled at:</td><td class="bline">Mar  1, 2004 [19:37] GMT</td>
+        </tr>
+        <tr>
+          <td class="label">SourceForge page:</td><td><a href="http://sf.net/projects/itools-htmlarea/">http://sf.net/projects/itools-htmlarea/</a></td>
+      </table>
+    </div>
+    <h1>HTMLArea -- the free<br/>customizable online editor</h1>
+
+    <p>
+      HTMLArea is a free, customizable online editor.  It works inside your
+      browser.  It uses a non-standard feature implemented in Internet
+      Explorer 5.5 or better for Windows and Mozilla 1.3 or better (any
+      platform), therefore it will only work in one of these browsers.
+    </p>
+
+    <p>
+      HTMLArea is copyright <a
+      href="http://interactivetools.com">InteractiveTools.com</a> and <a
+      href="http://dynarch.com">Dynarch.com</a> and it is
+      released under a BSD-style license.  HTMLArea is created and developed
+      upto version 2.03 by InteractiveTools.com.  Version 3.0 developed by
+      <a href="http://dynarch.com/mishoo/">Mihai Bazon</a> for
+      InteractiveTools.  It contains code sponsored by third-party companies as well.
+      Please see our About Box for details about who sponsored what plugins.
+    </p>
+
+    <h2>Online demos</h2>
+
+    <ul>
+
+      <li><a href="examples/core.html">HTMLArea standard</a> -- contains the core
+        editor.</li>
+
+      <li><a href="examples/table-operations.html">HTMLArea + tables</a> --
+        loads the <tt>TableOperations</tt> plugin which provides some extra
+        editing features for tables.</li>
+
+      <li><a href="examples/spell-checker.html">HTMLArea + spell checher</a>
+        -- loads the <tt>SpellChecker</tt> plugin which provides what its
+        name says: a spell checker.  This one requires additional support on
+        the server-side.</li>
+
+      <li><a href="examples/full-page.html">HTMLArea Full HTML Editor</a> --
+        loads the <tt>FullPage</tt> plugin which allows you to edit a full
+        HTML page, including &lt;title&gt;, &lt;!DOCTYPE...&gt; and some
+        other options.</li>
+
+      <li><a href="examples/context-menu.html">HTMLArea with Context
+          Menu</a> -- this plugin provides a nice and useful context menu.</li>
+
+      <li><a href="examples/fully-loaded.html">HTMLArea fully loaded</a> --
+        all of the above. ;-)</li>
+
+    </ul>
+
+    <h2>Installation</h2>
+
+    <p>
+      Installation is (or should be) easy.  You need to unpack the ZIP file
+      in a directory accessible through your webserver.  Supposing you
+      unpack in your <tt>DocumentRoot</tt> and your <tt>DocumentRoot</tt> is
+      <tt>/var/www/html</tt> as in a standard RedHat installation, you need
+      to acomplish the following steps: (the example is for a Unix-like
+      operating system)
+    </p>
+
+    <pre style="margin-left: 2em"
+>
+cd /var/www/html
+unzip /path/to/archive/HTMLArea-3.0-rc1.zip
+mv HTMLArea-3.0-rc1 htmlarea
+find htmlarea/ -type f -exec chmod 644 {} \;
+find htmlarea/ -type d -exec chmod 755 {} \;
+find htmlarea/ -name "*.cgi" -exec chmod 755 {} \;</pre>
+
+    <p>
+      <strong>Notes.</strong> You may chose to symlink "htmlarea" to "HTMLArea-3.0-rc1", in which case your server needs to be configured to
+      "<tt>FollowSymLinks</tt>".  You need to make sure that *.cgi files are
+      interpreted as CGI scripts.  If you want to use the SpellChecker
+      plugin you need to have a recent version of Perl installed (I
+      recommend 5.8.0) on the server, and the module Text::Aspell, available
+      from CPAN.  More info in "<a
+      href="plugins/SpellChecker/readme-tech.html">plugins/SpellChecker/readme-tech.html</a>".
+    </p>
+
+    <p>About how to setup your pages to use the editor, please read the
+      [outdated yet generally valid] <a
+        href="reference.html">documentation</a>.</p>
+
+    <h2>Status and links</h2>
+
+    <p>HTMLArea has reached version 3.0.  As of this version, it
+      supports:</p>
+
+    <ul>
+
+      <li>Customizable toolbar</li>
+
+      <li>Easy internationalization</li>
+
+      <li>Plugin-based infrastructure</li>
+
+      <li>Delivers W3-compliant HTML (with few exceptions)</li>
+
+      <li>Has a subset of Microsoft Word's keyboard shortcuts</li>
+
+      <li>Full-screen editor</li>
+
+      <li>Advanced table operations (by external plugin
+        "TableOperations")</li>
+
+      <li>Spell checker (by external plugin "SpellChecker")</li>
+
+      <li>probably more... ;-)</li>
+
+    </ul>
+
+    <p>We have a <a
+    href="http://sourceforge.net/projects/itools-htmlarea/">project page</a>
+    at <a href="http://sourceforge.net">SourceForge.net</a>.  There you can
+    also find out <a href="http://sourceforge.net/cvs/?group_id=69750">how
+    to retrieve the code from CVS</a>, or you can <a
+    href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/itools-htmlarea">browse
+    the CVS online</a>.  We also have a <a
+    href="http://sourceforge.net/tracker/?atid=525656&group_id=69750&func=browse">bug
+    system</a>, a <a
+    href="http://sourceforge.net/tracker/?atid=525658&group_id=69750&func=browse">patch
+    tracking system</a> and a <a
+    href="http://sourceforge.net/tracker/?atid=525659&group_id=69750&func=browse">feature
+    request page</a>.</p>
+
+    <p>We invite you to say everything you want about HTMLArea <a
+    href="http://www.interactivetools.com/forum/gforum.cgi?forum=14;">on the
+    forums</a> at InteractiveTools.com.  There you should also find the
+    latest news.</p>
+
+    <p>Sometimes I post news about the latest developments on <a
+    href="http://dynarch.com/mishoo/">my personal homepage</a>.</p>
+
+    <h2>"It doesn't work, what's wrong?"</h2>
+
+    <p>If it doesn't work, you have several options:</p>
+
+    <ul>
+
+      <li>Post a message to the forum.  Describe your problem in as much
+      detail as possible.  Include errors you might find in the JavaScript
+      console (if you are a Mozilla user), or errors displayed by IE (though
+      they're most of the times useless).</li>
+
+      <li>If you're positive that you discovered a bug in HTMLArea then feel
+      free to fill a bug report in our bug system.  If you have the time you
+      should check to see if a similar bug was reported or not; it might be
+      fixed already in the CVS ;-) If you're positive that a similar bug was
+      not yet reported, do fill a bug report and please include as much
+      detail as possible, such as your browser, OS, errors from JavaScript
+      console, etc.</li>
+
+      <li>If you want a new feature to be implemented, post it on the
+      features request and someone will hopefully take care of it.</li>
+
+    </ul>
+
+    <p>You can <a href="mailto:mishoo@infoiasi.ro">contact me directly</a>
+    <em>only</em> if you want to pay me for implementing custom features to
+    HTMLArea.  If you want to sponsor these features (that is, allow them to
+    get back into the public HTMLArea distribution) I'll be cheaper. ;-)</p>
+
+    <hr />
+    <address><a href="http://dynarch.com/mishoo/">Mihai Bazon</a></address>
+<!-- Created: Sun Aug  3 14:11:26 EEST 2003 -->
+<!-- hhmts start --> Last modified: Wed Jan 28 11:54:47 EET 2004 <!-- hhmts end -->
+<!-- doc-lang: English -->
+  </body>
+</html>
+
+
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/b5.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/b5.js
new file mode 100644 (file)
index 0000000..248c40a
--- /dev/null
@@ -0,0 +1,36 @@
+// I18N constants -- Chinese Big-5
+// by Dave Lo -- dlo@interactivetools.com
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "b5",
+
+       tooltips: {
+               bold:           "²ÊÅé",
+               italic:         "±×Åé",
+               underline:      "©³½u",
+               strikethrough:  "§R°£½u",
+               subscript:      "¤U¼Ð",
+               superscript:    "¤W¼Ð",
+               justifyleft:    "¦ì¸m¾a¥ª",
+               justifycenter:  "¦ì¸m©~¤¤",
+               justifyright:   "¦ì¸m¾a¥k",
+               justifyfull:    "¦ì¸m¥ª¥k¥­µ¥",
+               orderedlist:    "¶¶§Ç²M³æ",
+               unorderedlist:  "µL§Ç²M³æ",
+               outdent:        "´î¤p¦æ«eªÅ¥Õ",
+               indent:         "¥[¼e¦æ«eªÅ¥Õ",
+               forecolor:      "¤å¦rÃC¦â",
+               backcolor:      "­I´ºÃC¦â",
+               horizontalrule: "¤ô¥­½u",
+               createlink:     "´¡¤J³sµ²",
+               insertimage:    "´¡¤J¹Ï§Î",
+               inserttable:    "´¡¤Jªí®æ",
+               htmlmode:       "¤Á´«HTML­ì©l½X",
+               popupeditor:    "©ñ¤j",
+               about:          "Ãö©ó HTMLArea",
+               help:           "»¡©ú",
+               textindicator:  "¦rÅé¨Ò¤l"
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/cz.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/cz.js
new file mode 100644 (file)
index 0000000..91f6595
--- /dev/null
@@ -0,0 +1,63 @@
+// I18N constants
+
+// LANG: "cz", ENCODING: UTF-8 | ISO-8859-2
+// Author: Jiri Löw, <jirilow@jirilow.com>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "cz",
+
+       tooltips: {
+               bold:           "Tučně",
+               italic:         "Kurzíva",
+               underline:      "Podtržení",
+               strikethrough:  "Přeškrtnutí",
+               subscript:      "Dolní index",
+               superscript:    "Horní index",
+               justifyleft:    "Zarovnat doleva",
+               justifycenter:  "Na střed",
+               justifyright:   "Zarovnat doprava",
+               justifyfull:    "Zarovnat do stran",
+               orderedlist:    "Seznam",
+               unorderedlist:  "Odrážky",
+               outdent:        "Předsadit",
+               indent:         "Odsadit",
+               forecolor:      "Barva písma",
+               hilitecolor:    "Barva pozadí",
+               horizontalrule: "Vodorovná čára",
+               createlink:     "Vložit odkaz",
+               insertimage:    "Vložit obrázek",
+               inserttable:    "Vložit tabulku",
+               htmlmode:       "Přepnout HTML",
+               popupeditor:    "Nové okno editoru",
+               about:          "O této aplikaci",
+               showhelp:       "Nápověda aplikace",
+               textindicator:  "Zvolený styl",
+               undo:           "Vrátí poslední akci",
+               redo:           "Opakuje poslední akci",
+               cut:            "Vyjmout",
+               copy:           "Kopírovat",
+               paste:          "Vložit"
+       },
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Zrušit"
+       },
+
+       msg: {
+               "Path":         "Cesta",
+               "TEXT_MODE":    "Jste v TEXTOVÉM REŽIMU.  Použijte tlačítko [<>] pro přepnutí do WYSIWIG."
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/da.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/da.js
new file mode 100644 (file)
index 0000000..86dc617
--- /dev/null
@@ -0,0 +1,38 @@
+// danish version for htmlArea v3.0 - Alpha Release
+// - translated by rene<rene@laerke.net>
+// term´s and licenses are equal to htmlarea!
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "da",
+
+       tooltips: {
+               bold:           "Fed",
+               italic:         "Kursiv",
+               underline:      "Understregning",
+               strikethrough:  "Overstregning ",
+               subscript:      "Sænket skrift",
+               superscript:    "Hævet skrift",
+               justifyleft:    "Venstrejuster",
+               justifycenter:  "Centrer",
+               justifyright:   "Højrejuster",
+               justifyfull:    "Lige margener",
+               orderedlist:    "Opstilling med tal",
+               unorderedlist:  "Opstilling med punkttegn",
+               outdent:        "Formindsk indrykning",
+               indent:         "Forøg indrykning",
+               forecolor:      "Skriftfarve",
+               backcolor:      "Baggrundsfarve",
+               horizontalrule: "Horisontal linie",
+               createlink:     "Indsæt hyperlink",
+               insertimage:    "Indsæt billede",
+               inserttable:    "Indsæt tabel",
+               htmlmode:       "HTML visning",
+               popupeditor:    "Vis editor i popup",
+               about:          "Om htmlarea",
+               help:           "Hjælp",
+               textindicator:  "Anvendt stil"
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/de.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/de.js
new file mode 100644 (file)
index 0000000..550b794
--- /dev/null
@@ -0,0 +1,54 @@
+// german version for htmlArea v3.0 - Alpha Release
+// - translated by AtK<atk@chello.at>
+// term´s and licenses are equal to htmlarea!
+// translation improved by broxx<broxx@broxx.com>
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "de",
+
+       tooltips: {
+               bold:           "Fett",
+               italic:         "Kursiv",
+               underline:      "Unterstrichen",
+               strikethrough:  "Durchgestrichen",
+               subscript:      "Hochgestellt",
+               superscript:    "Tiefgestellt",
+               justifyleft:    "Links ausrichten",
+               justifycenter:  "Zentrieren",
+               justifyright:   "Rechts ausrichten",
+               justifyfull:    "Blocksatz",
+               orderedlist:    "Nummerierung",
+               unorderedlist:  "Aufzaehlungszeichen",
+               outdent:        "Einzug verkleinern",
+               indent:         "Einzug vergrössern",
+               forecolor:      "Text Farbe",
+               hilitecolor:    "Hintergrund Farbe",
+               horizontalrule: "Horizontale Linie",
+               createlink:     "Hyperlink einfuegen",
+               insertimage:    "Bild einfuegen",
+               inserttable:    "Tabelle einfuegen",
+               htmlmode:       "HTML Modus",
+               popupeditor:    "Editor im Popup öffnen",
+               about:          "Ueber HtmlArea",
+               showhelp:       "Hilfe",
+               textindicator:  "derzeitiger Stil",
+               undo:           "Rueckgaengig",
+               redo:           "Wiederholen",
+               cut:            "Ausschneiden",
+               copy:           "Kopieren",
+               paste:          "Einfuegen"
+       },
+  
+ buttons: {
+               "ok":           "OK",
+               "cancel":       "Abbrechen"
+       },
+
+       msg: {
+               "Path":         "Pfad",
+               "TEXT_MODE":    "Du befindest dich im HTML Modus.  Benuetze die [<>] Schaltflaeche um in den WYSIWIG-Modus zu wechseln."
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/ee.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/ee.js
new file mode 100644 (file)
index 0000000..3e4f8bb
--- /dev/null
@@ -0,0 +1,63 @@
+// I18N constants
+
+// LANG: "ee", ENCODING: UTF-8 | ISO-8859-1
+// Author: Martin Raie, <albertvill@hot.ee>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "ee",
+
+       tooltips: {
+               bold:           "Paks",
+               italic:         "Kursiiv",
+               underline:      "Allakriipsutatud",
+               strikethrough:  "Läbikriipsutatud",
+               subscript:      "Allindeks",
+               superscript:    "Ülaindeks",
+               justifyleft:    "Joonda vasakule",
+               justifycenter:  "Joonda keskele",
+               justifyright:   "Joonda paremale",
+               justifyfull:    "Rööpjoonda",
+               insertorderedlist:    "Nummerdus",
+               insertunorderedlist:  "Täpploend",
+               outdent:        "Vähenda taanet",
+               indent:         "Suurenda taanet",
+               forecolor:      "Fondi värv",
+               hilitecolor:    "Tausta värv",
+               inserthorizontalrule: "Horisontaaljoon",
+               createlink:     "Lisa viit",
+               insertimage:    "Lisa pilt",
+               inserttable:    "Lisa tabel",
+               htmlmode:       "HTML/tavaline vaade",
+               popupeditor:    "Suurenda toimeti aken",
+               about:          "Teave toimeti kohta",
+               showhelp:       "Spikker",
+               textindicator:  "Kirjastiil",
+               undo:           "Võta tagasi",
+               redo:           "Tee uuesti",
+               cut:            "Lõika",
+               copy:           "Kopeeri",
+               paste:          "Kleebi"
+       },
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Loobu"
+       },
+
+       msg: {
+               "Path":         "Path",
+               "TEXT_MODE":    "Sa oled tekstireziimis.  Kasuta nuppu [<>] lülitamaks tagasi WYSIWIG reziimi."
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/el.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/el.js
new file mode 100644 (file)
index 0000000..b7c5a27
--- /dev/null
@@ -0,0 +1,75 @@
+// I18N constants
+
+// LANG: "el", ENCODING: UTF-8 | ISO-8859-7
+// Author: Dimitris Glezos, dimitris@glezos.com
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "el",
+
+       tooltips: {
+               bold:           "Έντονα",
+               italic:         "Πλάγια",
+               underline:      "Υπογραμμισμένα",
+               strikethrough:  "Διαγραμμένα",
+               subscript:      "Δείκτης",
+               superscript:    "Δείκτης",
+               justifyleft:    "Στοίχιση Αριστερά",
+               justifycenter:  "Στοίχιση Κέντρο",
+               justifyright:   "Στοίχιση Δεξιά",
+               justifyfull:    "Πλήρης Στοίχιση",
+               orderedlist:    "Αρίθμηση",
+               unorderedlist:  "Κουκκίδες",
+               outdent:        "Μείωση Εσοχής",
+               indent:         "Αύξηση Εσοχής",
+               forecolor:      "Χρώμα Γραμματοσειράς",
+               hilitecolor:    "Χρώμα Φόντου",
+               horizontalrule: "Οριζόντια Γραμμή",
+               createlink:     "Εισαγωγή Συνδέσμου",
+               insertimage:    "Εισαγωγή/Τροποποίηση Εικόνας",
+               inserttable:    "Εισαγωγή Πίνακα",
+               htmlmode:       "Εναλλαγή σε/από HTML",
+               popupeditor:    "Μεγένθυνση επεξεργαστή",
+               about:          "Πληροφορίες",
+               showhelp:       "Βοήθεια",
+               textindicator:  "Παρών στυλ",
+               undo:           "Αναίρεση τελευταίας ενέργειας",
+               redo:           "Επαναφορά από αναίρεση",
+               cut:            "Αποκοπή",
+               copy:           "Αντιγραφή",
+               paste:          "Επικόλληση",
+        lefttoright:    "Κατεύθυνση αριστερά προς δεξιά",
+        righttoleft:    "Κατεύθυνση από δεξιά προς τα αριστερά"
+       },
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Ακύρωση"
+       },
+
+       msg: {
+               "Path":         "Διαδρομή",
+               "TEXT_MODE":    "Είστε σε TEXT MODE.  Χρησιμοποιήστε το κουμπί [<>] για να επανέρθετε στο WYSIWIG.",
+
+       "IE-sucks-full-screen": "Η κατάσταση πλήρης οθόνης έχει προβλήματα με τον Internet Explorer, " +
+                                                               "λόγω σφαλμάτων στον ίδιο τον browser.  Αν το σύστημα σας είναι Windows 9x " +
+                                                               "μπορεί και να χρειαστείτε reboot. Αν είστε σίγουροι, πατήστε ΟΚ."
+       },
+
+       dialogs: {
+               "Cancel"                                            : "Ακύρωση",
+               "Insert/Modify Link"                                : "Εισαγωγή/Τροποποίηση σύνδεσμου",
+               "New window (_blank)"                               : "Νέο παράθυρο (_blank)",
+               "None (use implicit)"                               : "Κανένα (χρήση απόλυτου)",
+               "OK"                                                : "Εντάξει",
+               "Other"                                             : "Αλλο",
+               "Same frame (_self)"                                : "Ίδιο frame (_self)",
+               "Target:"                                           : "Target:",
+               "Title (tooltip):"                                  : "Τίτλος (tooltip):",
+               "Top frame (_top)"                                  : "Πάνω frame (_top)",
+               "URL:"                                              : "URL:",
+               "You must enter the URL where this link points to"  : "Πρέπει να εισάγετε το URL που οδηγεί αυτός ο σύνδεσμος"
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/en.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/en.js
new file mode 100644 (file)
index 0000000..361c7ab
--- /dev/null
@@ -0,0 +1,88 @@
+// I18N constants
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "en",
+
+       tooltips: {
+               bold:           "Bold",
+               italic:         "Italic",
+               underline:      "Underline",
+               strikethrough:  "Strikethrough",
+               subscript:      "Subscript",
+               superscript:    "Superscript",
+               justifyleft:    "Justify Left",
+               justifycenter:  "Justify Center",
+               justifyright:   "Justify Right",
+               justifyfull:    "Justify Full",
+               orderedlist:    "Ordered List",
+               unorderedlist:  "Bulleted List",
+               outdent:        "Decrease Indent",
+               indent:         "Increase Indent",
+               forecolor:      "Font Color",
+               hilitecolor:    "Background Color",
+               horizontalrule: "Horizontal Rule",
+               createlink:     "Insert Web Link",
+               insertimage:    "Insert/Modify Image",
+               inserttable:    "Insert Table",
+               htmlmode:       "Toggle HTML Source",
+               popupeditor:    "Enlarge Editor",
+               about:          "About this editor",
+               showhelp:       "Help using editor",
+               textindicator:  "Current style",
+               undo:           "Undoes your last action",
+               redo:           "Redoes your last action",
+               cut:            "Cut selection",
+               copy:           "Copy selection",
+               paste:          "Paste from clipboard",
+               lefttoright:    "Direction left to right",
+               righttoleft:    "Direction right to left"
+       },
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Cancel"
+       },
+
+       msg: {
+               "Path":         "Path",
+               "TEXT_MODE":    "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.",
+
+               "IE-sucks-full-screen" :
+               // translate here
+               "The full screen mode is known to cause problems with Internet Explorer, " +
+               "due to browser bugs that we weren't able to workaround.  You might experience garbage " +
+               "display, lack of editor functions and/or random browser crashes.  If your system is Windows 9x " +
+               "it's very likely that you'll get a 'General Protection Fault' and need to reboot.\n\n" +
+               "You have been warned.  Please press OK if you still want to try the full screen editor."
+       },
+
+       dialogs: {
+               "Cancel"                                            : "Cancel",
+               "Insert/Modify Link"                                : "Insert/Modify Link",
+               "New window (_blank)"                               : "New window (_blank)",
+               "None (use implicit)"                               : "None (use implicit)",
+               "OK"                                                : "OK",
+               "Other"                                             : "Other",
+               "Same frame (_self)"                                : "Same frame (_self)",
+               "Target:"                                           : "Target:",
+               "Title (tooltip):"                                  : "Title (tooltip):",
+               "Top frame (_top)"                                  : "Top frame (_top)",
+               "URL:"                                              : "URL:",
+               "You must enter the URL where this link points to"  : "You must enter the URL where this link points to"
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/es.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/es.js
new file mode 100644 (file)
index 0000000..766ec66
--- /dev/null
@@ -0,0 +1,51 @@
+// I18N constants
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "es",
+
+       tooltips: {
+               bold:           "Negrita",
+               italic:         "Cursiva",
+               underline:      "Subrayado",
+               strikethrough:  "Tachado",
+               subscript:      "Subíndice",
+               superscript:    "Superíndice",
+               justifyleft:    "Alinear a la Izquierda",
+               justifycenter:  "Centrar",
+               justifyright:   "Alinear a la Derecha",
+               justifyfull:    "Justificar",
+               insertorderedlist:    "Lista Ordenada",
+               insertunorderedlist:  "Lista No Ordenada",
+               outdent:        "Aumentar Sangría",
+               indent:         "Disminuir Sangría",
+               forecolor:      "Color del Texto",
+               hilitecolor:    "Color del Fondo",
+               inserthorizontalrule: "Línea Horizontal",
+               createlink:     "Insertar Enlace",
+               insertimage:    "Insertar Imagen",
+               inserttable:    "Insertar Tabla",
+               htmlmode:       "Ver Documento en HTML",
+               popupeditor:    "Ampliar Editor",
+               about:          "Acerca del Editor",
+               showhelp:       "Ayuda",
+               textindicator:  "Estilo Actual",
+               undo:           "Deshacer",
+               redo:           "Rehacer",
+               cut:            "Cortar selección",
+               copy:           "Copiar selección",
+               paste:          "Pegar desde el portapapeles"
+       },
+
+       buttons: {
+               "ok":           "Aceptar",
+               "cancel":       "Cancelar"
+       },
+
+       msg: {
+               "Path":         "Ruta",
+               "TEXT_MODE":    "Esta en modo TEXTO. Use el boton [<>] para cambiar a WYSIWIG",
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/fi.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/fi.js
new file mode 100644 (file)
index 0000000..e0576cc
--- /dev/null
@@ -0,0 +1,46 @@
+// I18N constants
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "en",
+
+       tooltips: {
+               bold:                   "Lihavoitu",
+               italic:                 "Kursivoitu",
+               underline:              "Alleviivattu",
+               strikethrough:          "Yliviivattu",
+               subscript:              "Alaindeksi",
+               superscript:            "Yläindeksi",
+               justifyleft:            "Tasaa vasemmat reunat",
+               justifycenter:          "Keskitä",
+               justifyright:           "Tasaa oikeat reunat",
+               justifyfull:            "Tasaa molemmat reunat",
+               insertorderedlist:      "Numerointi",
+               insertunorderedlist:    "Luettelomerkit",
+               outdent:                "Lisää sisennystä",
+               indent:                 "Pienennä sisennystä",
+               forecolor:              "Fontin väri",
+               hilitecolor:            "Taustaväri",
+               inserthorizontalrule:   "Vaakaviiva",
+               createlink:             "Lisää Linkki",
+               insertimage:            "Lisää Kuva",
+               inserttable:            "Lisää Taulu",
+               htmlmode:               "HTML Lähdekoodi vs WYSIWYG",
+               popupeditor:            "Suurenna Editori",
+               about:                  "Tietoja Editorista",
+               showhelp:               "Näytä Ohje",
+               textindicator:          "Nykyinen tyyli",
+               undo:                   "Peruuta viimeinen toiminto",
+               redo:                   "Palauta viimeinen toiminto",
+               cut:                    "Leikkaa maalattu",
+               copy:                   "Kopioi maalattu",
+               paste:                  "Liitä leikepyödältä"
+       },
+
+       buttons: {
+               "ok":                   "Hyväksy",
+               "cancel":               "Peruuta"
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/fr.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/fr.js
new file mode 100644 (file)
index 0000000..d4cd6ac
--- /dev/null
@@ -0,0 +1,61 @@
+// I18N constants
+// Author: Jonathan Ernst, <Jonathan.Ernst@NetOxygen.ch>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "fr",
+
+       tooltips: {
+               bold:           "Gras",
+               italic:         "Italique",
+               underline:      "Souligné",
+               strikethrough:  "Barré",
+               subscript:      "Subscript",
+               superscript:    "Superscript",
+               justifyleft:    "Aligné à gauche",
+               justifycenter:  "Centré",
+               justifyright:   "Aligné à droite",
+               justifyfull:    "Justifié",
+               orderedlist:    "Numérotation",
+               unorderedlist:  "Puces",
+               outdent:        "Augmenter le retrait",
+               indent:         "Diminuer le retrait",
+               forecolor:      "Couleur du texte",
+               hilitecolor:    "Couleur du fond",
+               horizontalrule: "Ligne horizontale",
+               createlink:     "Insérer un lien",
+               insertimage:    "Insérer une image",
+               inserttable:    "Insérer un tableau",
+               htmlmode:       "Passer au code source HTML",
+               popupeditor:    "Agrandir l'éditeur",
+               about:          "A propos de cet éditeur",
+               showhelp:       "Aide sur l'éditeur",
+               textindicator:  "Style courant",
+               undo:           "Annule la dernière action",
+               redo:           "Refait la dernière action",
+               cut:            "Coupe la sélection",
+               copy:           "Copie la sélection",
+               paste:          "Colle depuis le presse papiers"
+       },
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Annuler"
+       },
+
+       msg: {
+               "Path":         "Chemin",
+               "TEXT_MODE":    "Vous êtes en mode texte.  Utilisez le bouton [<>] pour revenir au mode WYSIWIG."
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/gb.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/gb.js
new file mode 100644 (file)
index 0000000..049087f
--- /dev/null
@@ -0,0 +1,36 @@
+// I18N constants -- Chinese GB
+// by Dave Lo -- dlo@interactivetools.com
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "gb",
+
+       tooltips: {
+               bold:           "´ÖÌå",
+               italic:         "бÌå",
+               underline:      "µ×Ïß",
+               strikethrough:  "ɾ³ýÏß",
+               subscript:      "ϱê",
+               superscript:    "Éϱê",
+               justifyleft:    "λÖÿ¿×ó",
+               justifycenter:  "λÖþÓÖÐ",
+               justifyright:   "λÖÿ¿ÓÒ",
+               justifyfull:    "λÖÃ×óÓÒÆ½µÈ",
+               orderedlist:    "˳ÐòÇåµ¥",
+               unorderedlist:  "ÎÞÐòÇåµ¥",
+               outdent:        "¼õСÐÐǰ¿Õ°×",
+               indent:         "¼Ó¿íÐÐǰ¿Õ°×",
+               forecolor:      "ÎÄ×ÖÑÕÉ«",
+               backcolor:      "±³¾°ÑÕÉ«",
+               horizontalrule: "ˮƽÏß",
+               createlink:     "²åÈëÁ¬½á",
+               insertimage:    "²åÈëͼÐÎ",
+               inserttable:    "²åÈë±í¸ñ",
+               htmlmode:       "Çл»HTMLԭʼÂë",
+               popupeditor:    "·Å´ó",
+               about:          "¹Øì¶ HTMLArea",
+               help:           "˵Ã÷",
+               textindicator:  "×ÖÌåÀý×Ó"
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/he.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/he.js
new file mode 100644 (file)
index 0000000..1843632
--- /dev/null
@@ -0,0 +1,63 @@
+// I18N constants
+
+// LANG: "he", ENCODING: UTF-8
+// Author: Liron Newman, <plastish@ultinet.org>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "he",
+
+       tooltips: {
+               bold:           "מודגש",
+               italic:         "נטוי",
+               underline:      "קו תחתי",
+               strikethrough:  "קו אמצע",
+               subscript:      "כתב עילי",
+               superscript:    "כתב תחתי",
+               justifyleft:    " ישור לשמאל",
+               justifycenter:  "ישור למרכז",
+               justifyright:   "ישור לימין",
+               justifyfull:    "יישור לשורה מלאה",
+               orderedlist:    "רשימה ממוספרת",
+               unorderedlist:  "רשימה לא ממוספרת",
+               outdent:        "הקטן כניסה",
+               indent:         "הגדל כניסה",
+               forecolor:      "צבע גופן",
+               hilitecolor:    "צבע רקע",
+               horizontalrule: "קו אנכי",
+               createlink:     "הכנס היפר-קישור",
+               insertimage:    "הכנס תמונה",
+               inserttable:    "הכנס טבלה",
+               htmlmode:       "שנה מצב קוד HTML",
+               popupeditor:    "הגדל את העורך",
+               about:          "אודות עורך זה",
+               showhelp:       "עזרה לשימוש בעורך",
+               textindicator:  "סגנון נוכחי",
+               undo:           "מבטל את פעולתך האחרונה",
+               redo:           "מבצע מחדש את הפעולה האחרונה שביטלת",
+               cut:            "גזור בחירה",
+               copy:           "העתק בחירה",
+               paste:          "הדבק מהלוח"
+       },
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "ביטול"
+       },
+
+       msg: {
+               "Path":         "נתיב עיצוב",
+               "TEXT_MODE":    "אתה במצב טקסט נקי (קוד). השתמש בכפתור [<>] כדי לחזור למצב WYSIWYG (תצוגת עיצוב)."
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/hu.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/hu.js
new file mode 100644 (file)
index 0000000..828aec1
--- /dev/null
@@ -0,0 +1,63 @@
+// I18N constants
+
+// LANG: "hu", ENCODING: UTF-8
+// Author: Miklós Somogyi, <somogyine@vnet.hu>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "hu",
+
+       tooltips: {
+               bold:           "Félkövér",
+               italic:         "Dőlt",
+               underline:      "Aláhúzott",
+               strikethrough:  "Áthúzott",
+               subscript:      "Alsó index",
+               superscript:    "Felső index",
+               justifyleft:    "Balra zárt",
+               justifycenter:  "Középre zárt",
+               justifyright:   "Jobbra zárt",
+               justifyfull:    "Sorkizárt",
+               orderedlist:    "Számozott lista",
+               unorderedlist:  "Számozatlan lista",
+               outdent:        "Behúzás csökkentése",
+               indent:         "Behúzás növelése",
+               forecolor:      "Karakterszín",
+               hilitecolor:    "Háttérszín",
+               horizontalrule: "Elválasztó vonal",
+               createlink:     "Hiperhivatkozás beszúrása",
+               insertimage:    "Kép beszúrása",
+               inserttable:    "Táblázat beszúrása",
+               htmlmode:       "HTML forrás be/ki",
+               popupeditor:    "Szerkesztő külön ablakban",
+               about:          "Névjegy",
+               showhelp:       "Súgó",
+               textindicator:  "Aktuális stílus",
+               undo:           "Visszavonás",
+               redo:           "Újra végrehajtás",
+               cut:            "Kivágás",
+               copy:           "Másolás",
+               paste:          "Beillesztés"
+       },
+
+       buttons: {
+               "ok":           "Rendben",
+               "cancel":       "Mégsem"
+       },
+
+       msg: {
+               "Path":         "Hierarchia",
+               "TEXT_MODE":    "Forrás mód. Visszaváltás [<>] gomb"
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/it.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/it.js
new file mode 100644 (file)
index 0000000..be06e99
--- /dev/null
@@ -0,0 +1,54 @@
+// I18N constants
+
+// LANG: "it", ENCODING: UTF-8 | ISO-8859-1
+// Author: Fabio Rotondo <fabio@rotondo.it>
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "it",
+
+       tooltips: {
+               bold:           "Grassetto",
+               italic:         "Italico",
+               underline:      "Sottolineato",
+               strikethrough:  "Barrato",
+               subscript:      "Pedice",
+               superscript:    "Apice",
+               justifyleft:    "Giustifica a Sinistra",
+               justifycenter:  "Giustifica in Centro",
+               justifyright:   "Giustifica a Destra",
+               justifyfull:    "Giustifica Completamente",
+               orderedlist:    "Lista Ordinata",
+               unorderedlist:  "Lista Puntata",
+               outdent:        "Decrementa Indentazione",
+               indent:         "Incrementa Indentazione",
+               forecolor:      "Colore del Carattere",
+               hilitecolor:    "Colore di Sfondo",
+               horizontalrule: "Linea Orizzontale",
+               createlink:     "Inserisci un Link",
+               insertimage:    "Inserisci un'Immagine",
+               inserttable:    "Inserisci una Tabella",
+               htmlmode:       "Attiva il codice HTML",
+               popupeditor:    "Allarga l'editor",
+               about:          "Info sull'editor",
+               showhelp:       "Aiuto sull'editor",
+               textindicator:  "Stile Attuale",
+               undo:           "Elimina l'ultima modifica",
+               redo:           "Ripristina l'ultima modifica",
+               cut:            "Taglia l'area selezionata",
+               copy:           "Copia l'area selezionata",
+               paste:          "Incolla dalla memoria"
+       },
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Annulla"
+       },
+
+       msg: {
+               "Path":         "Percorso",
+               "TEXT_MODE":    "Sei in MODALITA' TESTO. Usa il bottone [<>] per tornare alla modalità WYSIWYG."
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/ja-euc.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/ja-euc.js
new file mode 100644 (file)
index 0000000..87574e8
--- /dev/null
@@ -0,0 +1,37 @@
+// I18N constants -- Japanese EUC
+// by Manabu Onoue -- tmocsys@tmocsys.com
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "ja-euc",
+
+       tooltips: {
+               bold:           "ÂÀ»ú",
+               italic:         "¼ÐÂÎ",
+               underline:      "²¼Àþ",
+               strikethrough:  "ÂǤÁ¾Ã¤·Àþ",
+               subscript:      "²¼ÉÕ¤­Åº¤¨»ú",
+               superscript:    "¾åÉÕ¤­Åº¤¨»ú",
+               justifyleft:    "º¸´ó¤»",
+               justifycenter:  "Ãæ±û´ó¤»",
+               justifyright:   "±¦´ó¤»",
+               justifyfull:    "¶ÑÅù³äÉÕ",
+               orderedlist:    "ÈÖ¹æÉÕ¤­²Õ¾ò½ñ¤­",
+               unorderedlist:  "µ­¹æÉÕ¤­²Õ¾ò½ñ¤­",
+               outdent:        "¥¤¥ó¥Ç¥ó¥È²ò½ü",
+               indent:         "¥¤¥ó¥Ç¥ó¥ÈÀßÄê",
+               forecolor:      "ʸ»ú¿§",
+               backcolor:      "ÇØ·Ê¿§",
+               horizontalrule: "¿åÊ¿Àþ",
+               createlink:     "¥ê¥ó¥¯ºîÀ®",
+               insertimage:    "²èÁüÁÞÆþ",
+               inserttable:    "¥Æ¡¼¥Ö¥ëÁÞÆþ",
+               htmlmode:       "HTMLɽ¼¨ÀÚÂØ",
+               popupeditor:    "¥¨¥Ç¥£¥¿³ÈÂç",
+               about:          "¥Ð¡¼¥¸¥ç¥ó¾ðÊó",
+               help:           "¥Ø¥ë¥×",
+               textindicator:  "¸½ºß¤Î¥¹¥¿¥¤¥ë"
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/ja-jis.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/ja-jis.js
new file mode 100644 (file)
index 0000000..49e5a3b
--- /dev/null
@@ -0,0 +1,37 @@
+// I18N constants -- Japanese JIS
+// by Manabu Onoue -- tmocsys@tmocsys.com
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "ja-jis",
+
+       tooltips: {
+               bold:           "\e$BB@;z\e(B",
+               italic:         "\e$B<PBN\e(B",
+               underline:      "\e$B2<@~\e(B",
+               strikethrough:  "\e$BBG$A>C$7@~\e(B",
+               subscript:      "\e$B2<IU$-E:$(;z\e(B",
+               superscript:    "\e$B>eIU$-E:$(;z\e(B",
+               justifyleft:    "\e$B:84s$;\e(B",
+               justifycenter:  "\e$BCf1{4s$;\e(B",
+               justifyright:   "\e$B1&4s$;\e(B",
+               justifyfull:    "\e$B6QEy3dIU\e(B",
+               orderedlist:    "\e$BHV9fIU$-2U>r=q$-\e(B",
+               unorderedlist:  "\e$B5-9fIU$-2U>r=q$-\e(B",
+               outdent:        "\e$B%$%s%G%s%H2r=|\e(B",
+               indent:         "\e$B%$%s%G%s%H@_Dj\e(B",
+               forecolor:      "\e$BJ8;z?'\e(B",
+               backcolor:      "\e$BGX7J?'\e(B",
+               horizontalrule: "\e$B?eJ?@~\e(B",
+               createlink:     "\e$B%j%s%/:n@.\e(B",
+               insertimage:    "\e$B2hA|A^F~\e(B",
+               inserttable:    "\e$B%F!<%V%kA^F~\e(B",
+               htmlmode:       "HTML\e$BI=<(@ZBX\e(B",
+               popupeditor:    "\e$B%(%G%#%?3HBg\e(B",
+               about:          "\e$B%P!<%8%g%s>pJs\e(B",
+               help:           "\e$B%X%k%W\e(B",
+               textindicator:  "\e$B8=:_$N%9%?%$%k\e(B"
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/ja-sjis.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/ja-sjis.js
new file mode 100644 (file)
index 0000000..9124529
--- /dev/null
@@ -0,0 +1,37 @@
+// I18N constants -- Japanese Shift-JIS
+// by Manabu Onoue -- tmocsys@tmocsys.com
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "ja-sjis",
+
+       tooltips: {
+               bold:           "\91¾\8e\9a",
+               italic:         "\8eÎ\91Ì",
+               underline:      "\89º\90ü",
+               strikethrough:  "\91Å\82¿\8fÁ\82µ\90ü",
+               subscript:      "\89º\95t\82«\93Y\82¦\8e\9a",
+               superscript:    "\8fã\95t\82«\93Y\82¦\8e\9a",
+               justifyleft:    "\8d\8añ\82¹",
+               justifycenter:  "\92\86\89\9b\8añ\82¹",
+               justifyright:   "\89E\8añ\82¹",
+               justifyfull:    "\8bÏ\93\99\8a\84\95t",
+               orderedlist:    "\94Ô\8d\86\95t\82«\89Ó\8fð\8f\91\82«",
+               unorderedlist:  "\8bL\8d\86\95t\82«\89Ó\8fð\8f\91\82«",
+               outdent:        "\83C\83\93\83f\83\93\83g\89ð\8f\9c",
+               indent:         "\83C\83\93\83f\83\93\83g\90Ý\92è",
+               forecolor:      "\95\8e\9a\90F",
+               backcolor:      "\94w\8ci\90F",
+               horizontalrule: "\90\85\95½\90ü",
+               createlink:     "\83\8a\83\93\83N\8dì\90¬",
+               insertimage:    "\89æ\91\9c\91}\93ü",
+               inserttable:    "\83e\81[\83u\83\8b\91}\93ü",
+               htmlmode:       "HTML\95\\8e¦\90Ø\91Ö",
+               popupeditor:    "\83G\83f\83B\83^\8ag\91å",
+               about:          "\83o\81[\83W\83\87\83\93\8fî\95ñ",
+               help:           "\83w\83\8b\83v",
+               textindicator:  "\8c»\8dÝ\82Ì\83X\83^\83C\83\8b"
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/ja-utf8.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/ja-utf8.js
new file mode 100644 (file)
index 0000000..f351fac
--- /dev/null
@@ -0,0 +1,37 @@
+// I18N constants -- Japanese UTF-8
+// by Manabu Onoue -- tmocsys@tmocsys.com
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "ja-utf8",
+
+       tooltips: {
+               bold:           "太字",
+               italic:         "斜体",
+               underline:      "下線",
+               strikethrough:  "打ち消し線",
+               subscript:      "下付き添え字",
+               superscript:    "上付き添え字",
+               justifyleft:    "左寄せ",
+               justifycenter:  "中央寄せ",
+               justifyright:   "右寄せ",
+               justifyfull:    "均等割付",
+               orderedlist:    "番号付き箇条書き",
+               unorderedlist:  "記号付き箇条書き",
+               outdent:        "インデント解除",
+               indent:         "インデント設定",
+               forecolor:      "文字色",
+               backcolor:      "背景色",
+               horizontalrule: "水平線",
+               createlink:     "リンク作成",
+               insertimage:    "画像挿入",
+               inserttable:    "テーブル挿入",
+               htmlmode:       "HTML表示切替",
+               popupeditor:    "エディタ拡大",
+               about:          "バージョン情報",
+               help:           "ヘルプ",
+               textindicator:  "現在のスタイル"
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/lt.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/lt.js
new file mode 100644 (file)
index 0000000..bf1efc5
--- /dev/null
@@ -0,0 +1,55 @@
+// I18N constants
+
+// LANG: "lt", ENCODING: UTF-8
+// Author: Jaroslav Šatkevič, <jaro@akl.lt>
+
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "lt",
+
+       tooltips: {
+               bold:           "Paryškinti",
+               italic:         "Kursyvas",
+               underline:      "Pabraukti",
+               strikethrough:  "Perbraukti",
+               subscript:      "Apatinis indeksas",
+               superscript:    "Viršutinis indeksas",
+               justifyleft:    "Lygiavimas pagal kairę",
+               justifycenter:  "Lygiavimas pagal centrą",
+               justifyright:   "Lygiavimas pagal dešinę",
+               justifyfull:    "Lygiuoti pastraipą",
+               orderedlist:    "Numeruotas sąrašas",
+               unorderedlist:  "Suženklintas sąrašas",
+               outdent:        "Sumažinti paraštę",
+               indent:         "Padidinti paraštę",
+               forecolor:      "Šrifto spalva",
+               hilitecolor:    "Fono spalva",
+               horizontalrule: "Horizontali linija",
+               createlink:     "Įterpti nuorodą",
+               insertimage:    "Įterpti paveiksliuką",
+               inserttable:    "Įterpti lentelę",
+               htmlmode:       "Perjungti į HTML/WYSIWYG",
+               popupeditor:    "Išplėstas redagavimo ekranas/Enlarge Editor",
+               about:          "Apie redaktorių",
+               showhelp:       "Pagalba naudojant redaktorių",
+               textindicator:  "Dabartinis stilius",
+               undo:           "Atšaukia paskutini jūsų veiksmą",
+               redo:           "Pakartoja paskutinį atšauktą jūsų veiksmą",
+               cut:            "Iškirpti",
+               copy:           "Kopijuoti",
+               paste:          "Įterpti"
+       },
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Atšaukti"
+       },
+
+       msg: {
+               "Path":         "Kelias",
+               "TEXT_MODE":    "Jūs esete teksto režime.  Naudokite [<>] mygtuką grįžimui į WYSIWYG."
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/lv.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/lv.js
new file mode 100644 (file)
index 0000000..8cdfb5d
--- /dev/null
@@ -0,0 +1,55 @@
+// I18N constants
+
+// LANG: "lv", ENCODING: UTF-8 | ISO-8859-1
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+// Translated by: Janis Klavins, <janis.klavins@devia.lv>
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "lv",
+
+       tooltips: {
+               bold:           "Trekniem burtiem",
+               italic:         "Kursîvâ",
+               underline:      "Pasvîtrots",
+               strikethrough:  "Pârsvîtrots",
+               subscript:      "Novietot zem rindas",
+               superscript:    "Novietot virs rindas",
+               justifyleft:    "Izlîdzinât pa kreisi",
+               justifycenter:  "Izlîdzinât centrâ",
+               justifyright:   "Izlîdzinât pa labi",
+               justifyfull:    "Izlîdzinât pa visu lapu",
+               orderedlist:    "Numurçts saraksts",
+               unorderedlist:  "Saraksts",
+               outdent:        "Samazinât atkâpi",
+               indent:         "Palielinât atkâpi",
+               forecolor:      "Burtu krâsa",
+               hilitecolor:    "Fona krâsa",
+               horizontalrule: "Horizontâla atdalîtâjsvîtra",
+               createlink:     "Ievietot hipersaiti",
+               insertimage:    "Ievietot attçlu",
+               inserttable:    "Ievietot tabulu",
+               htmlmode:       "Skatît HTML kodu",
+               popupeditor:    "Palielinât Rediìçtâju",
+               about:          "Par ðo rediìçtâju",
+               showhelp:       "Rediìçtâja palîgs",
+               textindicator:  "Patreizçjais stils",
+               undo:           "Atcelt pçdçjo darbîbu",
+               redo:           "Atkârtot pçdçjo darbîbu",
+               cut:            "Izgriezt iezîmçto",
+               copy:           "Kopçt iezîmçto",
+               paste:          "Ievietot iezîmçto"
+       },
+
+       buttons: {
+               "ok":           "Labi",
+               "cancel":       "Atcelt"
+       },
+
+       msg: {
+               "Path":         "Ceïð",
+               "TEXT_MODE":    "Jûs patlaban darbojaties TEKSTA REÞÎMÂ. Lai pârietu atpakaï uz GRAFISKO REÞÎMU (WYSIWIG), lietojiet [<>] pogu."
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/makefile.xml b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/makefile.xml
new file mode 100644 (file)
index 0000000..0d645c9
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<files>
+  <file name="*.js" />
+</files>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/nb.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/nb.js
new file mode 100644 (file)
index 0000000..4b95b8c
--- /dev/null
@@ -0,0 +1,36 @@
+// I18N constants
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "nb",
+
+       tooltips: {
+               bold:           "Fet",
+               italic:         "Kursiv",
+               underline:      "Understreket",
+               strikethrough:  "Gjennomstreket",
+               subscript:      "Senket",
+               superscript:    "Hevet",
+               justifyleft:    "Venstrejuster",
+               justifycenter:  "Midtjuster",
+               justifyright:   "Høyrejuster",
+               justifyfull:    "Blokkjuster",
+               orderedlist:    "Nummerert liste",
+               unorderedlist:  "Punktmerket liste",
+               outdent:        "Øke innrykk",
+               indent:         "Reduser innrykk",
+               forecolor:      "Skriftfarge",
+               backcolor:      "Bakgrunnsfarge",
+               horizontalrule: "Horisontal linje",
+               createlink:     "Sett inn lenke",
+               insertimage:    "Sett inn bilde",
+               inserttable:    "Sett inn tabell",
+               htmlmode:       "Vis HTML kode",
+               popupeditor:    "Forstørr redigeringsvindu",
+               about:          "Om..",
+               help:           "Hjelp",
+               textindicator:  "Gjeldende stil"
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/nl.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/nl.js
new file mode 100644 (file)
index 0000000..59bfe18
--- /dev/null
@@ -0,0 +1,90 @@
+// I18N constants
+
+// LANG: "nl", ENCODING: UTF-8 | ISO-8859-1
+// Author: Michel Weegeerink (info@mmc-shop.nl), http://mmc-shop.nl
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "nl",
+
+       tooltips: {
+               bold:                                   "Vet",
+               italic:                                 "Cursief",
+               underline:                              "Onderstrepen",
+               strikethrough:                  "Doorhalen",
+               subscript:                              "Subscript",
+               superscript:                    "Superscript",
+               justifyleft:                    "Links uitlijnen",
+               justifycenter:                  "Centreren",
+               justifyright:                   "Rechts uitlijnen",
+               justifyfull:                    "Uitvullen",
+               insertorderedlist:              "Nummering",
+               insertunorderedlist:    "Opsommingstekens",
+               outdent:                                "Inspringing verkleinen",
+               indent:                                 "Inspringing vergroten",
+               forecolor:                              "Tekstkleur",
+               hilitecolor:                    "Achtergrondkleur",
+               inserthorizontalrule:   "Horizontale lijn",
+               createlink:                             "Hyperlink invoegen/aanpassen",
+               insertimage:                    "Afbeelding invoegen/aanpassen",
+               inserttable:                    "Tabel invoegen",
+               htmlmode:                               "HTML broncode",
+               popupeditor:                    "Vergroot Editor",
+               about:                                  "Over deze editor",
+               showhelp:                               "HTMLArea help",
+               textindicator:                  "Huidige stijl",
+               undo:                                   "Ongedaan maken",
+               redo:                                   "Herhalen",
+               cut:                                    "Knippen",
+               copy:                                   "Kopiëren",
+               paste:                                  "Plakken",
+               lefttoright:                    "Tekstrichting links naar rechts",
+               righttoleft:                    "Tekstrichting rechts naar links"
+       },
+
+       buttons: {
+               "ok":                                   "OK",
+               "cancel":                               "Annuleren"
+       },
+
+       msg: {
+               "Path":                                 "Pad",
+               "TEXT_MODE":                    "Je bent in TEKST-mode. Gebruik de [<>] knop om terug te keren naar WYSIWYG-mode.",
+      
+               "IE-sucks-full-screen" :
+               // translate here
+               "Fullscreen-mode veroorzaakt problemen met Internet Explorer door bugs in de webbrowser " +
+               "die we niet kunnen omzeilen. Hierdoor kunnen de volgende effecten optreden: verknoeide teksten, " +
+               "een verlies aan editor-functionaliteit en/of willekeurig vastlopen van de webbrowser. " +
+               "Als u Windows 95 of 98 gebruikt, is het zeer waarschijnlijk dat u een algemene beschermingsfout " +
+               "('General Protection Fault') krijgt en de computer opnieuw zal moeten opstarten.\n\n" +
+               "U bent gewaarschuwd. Druk OK als u toch nog de Fullscreen-editor wil gebruiken."
+       },
+
+       dialogs: {
+               "Cancel"                                            : "Annuleren",
+               "Insert/Modify Link"                                : "Hyperlink invoegen/aanpassen",
+               "New window (_blank)"                               : "Nieuw venster (_blank)",
+               "None (use implicit)"                               : "Geen",
+               "OK"                                                : "OK",
+               "Other"                                             : "Ander",
+               "Same frame (_self)"                                : "Zelfde frame (_self)",
+               "Target:"                                           : "Doel:",
+               "Title (tooltip):"                                  : "Titel (tooltip):",
+               "Top frame (_top)"                                  : "Bovenste frame (_top)",
+               "URL:"                                              : "URL:",
+               "You must enter the URL where this link points to"  : "Geef de URL in waar de link naar verwijst"
+       }
+};
+
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/no.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/no.js
new file mode 100644 (file)
index 0000000..c1fd3a1
--- /dev/null
@@ -0,0 +1,79 @@
+// Norwegian version for htmlArea v3.0 - pre1
+// - translated by ses<ses@online.no>
+// Additional translations by Håvard Wigtil <havardw@extend.no>
+// term´s and licenses are equal to htmlarea!
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "no",
+
+       tooltips: {
+               bold:                 "Fet",
+               italic:               "Kursiv",
+               underline:            "Understreket",
+               strikethrough:        "Gjennomstreket",
+               subscript:            "Nedsenket",
+               superscript:          "Opphøyet",
+               justifyleft:          "Venstrejuster",
+               justifycenter:        "Midtjuster",
+               justifyright:         "Høyrejuster",
+               justifyfull:          "Blokkjuster",
+               insertorderedlist:    "Nummerert liste",
+               insertunorderedlist:  "Punktliste",
+               outdent:              "Reduser innrykk",
+               indent:               "Øke innrykk",
+               forecolor:            "Tekstfarge",
+               hilitecolor:          "Bakgrundsfarge",
+               inserthorizontalrule: "Vannrett linje",
+               createlink:           "Lag lenke",
+               insertimage:          "Sett inn bilde",
+               inserttable:          "Sett inn tabell",
+               htmlmode:             "Vis kildekode",
+               popupeditor:          "Vis i eget vindu",
+               about:                "Om denne editor",
+               showhelp:             "Hjelp",
+               textindicator:        "Nåværende stil",
+                undo:                 "Angrer siste redigering",
+               redo:                 "Gjør om siste angring",
+               cut:                  "Klipp ut område",
+               copy:                 "Kopier område",
+               paste:                "Lim inn",
+               lefttoright:          "Fra venstre mot høyre",
+               righttoleft:          "Fra høyre mot venstre"
+       },
+    
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Avbryt"
+       },
+
+       msg: {
+               "Path":         "Tekstvelger",
+               "TEXT_MODE":    "Du er i tekstmodus  Klikk på [<>] for å gå tilbake til WYSIWIG.",
+                "IE-sucks-full-screen" :
+               // translate here
+                "Visning i eget vindu har kjente problemer med Internet Explorer, " + 
+                "på grunn av problemer med denne nettleseren. Mulige problemer er et uryddig " + 
+                "skjermbilde, manglende editorfunksjoner og/eller at nettleseren crasher. Hvis du bruker Windows 95 eller Windows 98 " +
+                "er det også muligheter for at Windows will crashe.\n\n" +
+                "Trykk 'OK' hvis du vil bruke visning i eget vindu på tross av denne advarselen."
+       },
+
+       dialogs: {
+               "Cancel"                                            : "Avbryt",
+               "Insert/Modify Link"                                : "Rediger lenke",
+               "New window (_blank)"                               : "Eget vindu (_blank)",
+               "None (use implicit)"                               : "Ingen (bruk standardinnstilling)",
+               "OK"                                                : "OK",
+               "Other"                                             : "Annen",
+               "Same frame (_self)"                                : "Samme ramme (_self)",
+               "Target:"                                           : "Mål:",
+               "Title (tooltip):"                                  : "Tittel (tooltip):",
+               "Top frame (_top)"                                  : "Toppramme (_top)",
+               "URL:"                                              : "Adresse:",
+               "You must enter the URL where this link points to"  : "Du må skrive inn en adresse som denne lenken skal peke til"
+       }
+};
+
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/pl.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/pl.js
new file mode 100644 (file)
index 0000000..4907a26
--- /dev/null
@@ -0,0 +1,36 @@
+// I18N constants
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "pl",
+
+       tooltips: {
+               bold:           "Pogrubienie",
+               italic:         "Pochylenie",
+               underline:      "Podkre\9clenie",
+               strikethrough:  "Przekre\9clenie",
+               subscript:      "Indeks dolny",
+               superscript:    "Indeks górny",
+               justifyleft:    "Wyrównaj do lewej",
+               justifycenter:  "Wy\9crodkuj",
+               justifyright:   "Wyrównaj do prawej",
+               justifyfull:    "Wyjustuj",
+               orderedlist:    "Numerowanie",
+               unorderedlist:  "Wypunktowanie",
+               outdent:        "Zmniejsz wciêcie",
+               indent:         "Zwiêksz wciêcie",
+               forecolor:      "Kolor czcionki",
+               backcolor:      "Kolor t³a",
+               horizontalrule: "Linia pozioma",
+               createlink:     "Wstaw adres sieci Web",
+               insertimage:    "Wstaw obraz",
+               inserttable:    "Wstaw tabelê",
+               htmlmode:       "Edycja WYSIWYG/w \9fródle strony",
+               popupeditor:    "Pe³ny ekran",
+               about:          "Informacje o tym edytorze",
+               help:           "Pomoc",
+               textindicator:  "Obecny styl"
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/pt_br.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/pt_br.js
new file mode 100644 (file)
index 0000000..ac8b951
--- /dev/null
@@ -0,0 +1,37 @@
+// I18N constants
+// Brazilian Portuguese Translation by Alex Piaz <webmaster@globalmap.com>
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "pt_br",
+
+       tooltips: {
+               bold:           "Negrito",
+               italic:         "Itálico",
+               underline:      "Sublinhado",
+               strikethrough:  "Tachado",
+               subscript:      "Subescrito",
+               superscript:    "Sobrescrito",
+               justifyleft:    "Alinhar à Esquerda",
+               justifycenter:  "Centralizar",
+               justifyright:   "Alinhar à Direita",
+               justifyfull:    "Justificar",
+               orderedlist:    "Lista Numerada",
+               unorderedlist:  "Lista Marcadores",
+               outdent:        "Diminuir Indentação",
+               indent:         "Aumentar Indentação",
+               forecolor:      "Cor da Fonte",
+               backcolor:      "Cor do Fundo",
+               horizontalrule: "Linha Horizontal",
+               createlink:     "Inserir Link",
+               insertimage:    "Inserir Imagem",
+               inserttable:    "Inserir Tabela",
+               htmlmode:       "Ver Código-Fonte",
+               popupeditor:    "Expandir Editor",
+               about:          "Sobre",
+               help:           "Ajuda",
+               textindicator:  "Estilo Atual"
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/ro.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/ro.js
new file mode 100644 (file)
index 0000000..9e33775
--- /dev/null
@@ -0,0 +1,80 @@
+// I18N constants
+
+// LANG: "ro", ENCODING: UTF-8
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "ro",
+
+       tooltips: {
+               bold:           "Îngroşat",
+               italic:         "Italic",
+               underline:      "Subliniat",
+               strikethrough:  "Tăiat",
+               subscript:      "Indice jos",
+               superscript:    "Indice sus",
+               justifyleft:    "Aliniere la stânga",
+               justifycenter:  "Aliniere pe centru",
+               justifyright:   "Aliniere la dreapta",
+               justifyfull:    "Aliniere în ambele părţi",
+               orderedlist:    "Listă ordonată",
+               unorderedlist:  "Listă marcată",
+               outdent:        "Micşorează alineatul",
+               indent:         "Măreşte alineatul",
+               forecolor:      "Culoarea textului",
+               hilitecolor:    "Culoare de fundal",
+               horizontalrule: "Linie orizontală",
+               createlink:     "Inserează/modifică link",
+               insertimage:    "Inserează/modifică imagine",
+               inserttable:    "Inserează un tabel",
+               htmlmode:       "Sursa HTML / WYSIWYG",
+               popupeditor:    "Maximizează editorul",
+               about:          "Despre editor",
+               showhelp:       "Documentaţie (devel)",
+               textindicator:  "Stilul curent",
+               undo:           "Anulează ultima acţiune",
+               redo:           "Reface ultima acţiune anulată",
+               cut:            "Taie în clipboard",
+               copy:           "Copie în clipboard",
+               paste:          "Aduce din clipboard",
+               lefttoright:    "Direcţia de scriere: stânga - dreapta",
+               righttoleft:    "Direcţia de scriere: dreapta - stânga"
+       },
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Anulează"
+       },
+
+       msg: {
+               "Path":         "Calea",
+               "TEXT_MODE":    "Eşti în modul TEXT.  Apasă butonul [<>] pentru a te întoarce în modul WYSIWYG."
+       },
+
+       dialogs: {
+               "Cancel"                                            : "Renunţă",
+               "Insert/Modify Link"                                : "Inserează/modifcă link",
+               "New window (_blank)"                               : "Fereastră nouă (_blank)",
+               "None (use implicit)"                               : "Nimic (foloseşte ce-i implicit)",
+               "OK"                                                : "Acceptă",
+               "Other"                                             : "Alt target",
+               "Same frame (_self)"                                : "Aceeaşi fereastră (_self)",
+               "Target:"                                           : "Ţinta:",
+               "Title (tooltip):"                                  : "Titlul (tooltip):",
+               "Top frame (_top)"                                  : "Fereastra principală (_top)",
+               "URL:"                                              : "URL:",
+               "You must enter the URL where this link points to"  : "Trebuie să introduceţi un URL"
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/ru.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/ru.js
new file mode 100644 (file)
index 0000000..e8e1a32
--- /dev/null
@@ -0,0 +1,63 @@
+// I18N constants
+
+// LANG: "ru", ENCODING: UTF-8 | ISO-8859-1
+// Author: Yulya Shtyryakova, <yulya@vdcom.ru>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "ru",
+
+       tooltips: {
+               bold:           "Полужирный",
+               italic:         "Наклонный",
+               underline:      "Подчеркнутый",
+               strikethrough:  "Перечеркнутый",
+               subscript:      "Нижний индекс",
+               superscript:    "Верхний индекс",
+               justifyleft:    "По левому краю",
+               justifycenter:  "По центру",
+               justifyright:   "По правому краю",
+               justifyfull:    "По ширине",
+               insertorderedlist:    "Нумерованный лист",
+               insertunorderedlist:  "Маркированный лист",
+               outdent:        "Уменьшить отступ",
+               indent:         "Увеличить отступ",
+               forecolor:      "Цвет шрифта",
+               hilitecolor:    "Цвет фона",
+               horizontalrule: "Горизонтальный разделитель",
+               createlink:     "Вставить гиперссылку",
+               insertimage:    "Вставить изображение",
+               inserttable:    "Вставить таблицу",
+               htmlmode:       "Показать Html-код",
+               popupeditor:    "Увеличить редактор",
+               about:          "О редакторе",
+               showhelp:       "Помощь",
+               textindicator:  "Текущий стиль",
+               undo:           "Отменить",
+               redo:           "Повторить",
+               cut:            "Вырезать",
+               copy:           "Копировать",
+               paste:          "Вставить"
+       },
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Отмена"
+       },
+
+       msg: {
+               "Path":         "Путь",
+               "TEXT_MODE":    "Вы в режиме отображения Html-кода. нажмите кнопку [<>], чтобы переключиться в визуальный режим."
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/se.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/se.js
new file mode 100644 (file)
index 0000000..8b1a78f
--- /dev/null
@@ -0,0 +1,38 @@
+// Swedish version for htmlArea v3.0 - Alpha Release
+// - translated by pat<pat@engvall.nu>
+// term´s and licenses are equal to htmlarea!
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "se",
+
+       tooltips: {
+               bold:           "Fet",
+               italic:         "Kursiv",
+               underline:      "Understruken",
+               strikethrough:  "Genomstruken",
+               subscript:      "Nedsänkt",
+               superscript:    "Upphöjd",
+               justifyleft:    "Vänsterjustera",
+               justifycenter:  "Centrera",
+               justifyright:   "Högerjustera",
+               justifyfull:    "Marginaljustera",
+               orderedlist:    "Numrerad lista",
+               unorderedlist:  "Punktlista",
+               outdent:        "Minska indrag",
+               indent:         "Öka indrag",
+               forecolor:      "Textfärg",
+               backcolor:      "Bakgrundsfärg",
+               horizontalrule: "Vågrät linje",
+               createlink:     "Infoga länk",
+               insertimage:    "Infoga bild",
+               inserttable:    "Infoga tabell",
+               htmlmode:       "Visa källkod",
+               popupeditor:    "Visa i eget fönster",
+               about:          "Om denna editor",
+               help:           "Hjälp",
+               textindicator:  "Nuvarande stil"
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/si.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/si.js
new file mode 100644 (file)
index 0000000..7cfb496
--- /dev/null
@@ -0,0 +1,63 @@
+// I18N constants
+
+// LANG: "si", ENCODING: ISO-8859-2
+// Author: Tomaz Kregar, x_tomo_x@email.si
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "si",
+
+       tooltips: {
+               bold:           "Krepko",
+               italic:         "Le¾eèe",
+               underline:      "Podèrtano",
+               strikethrough:  "Preèrtano",
+               subscript:      "Podpisano",
+               superscript:    "Nadpisano",
+               justifyleft:    "Poravnaj levo",
+               justifycenter:  "Na sredino",
+               justifyright:   "Poravnaj desno",
+               justifyfull:    "Porazdeli vsebino",
+               orderedlist:    "O¹tevilèevanje",
+               unorderedlist:  "Oznaèevanje",
+               outdent:        "Zmanj¹aj zamik",
+               indent:         "Poveèaj zamik",
+               forecolor:      "Barva pisave",
+               hilitecolor:    "Barva ozadja",
+               horizontalrule: "Vodoravna èrta",
+               createlink:     "Vstavi hiperpovezavo",
+               insertimage:    "Vstavi sliko",
+               inserttable:    "Vstavi tabelo",
+               htmlmode:       "Preklopi na HTML kodo",
+               popupeditor:    "Poveèaj urejevalnik",
+               about:          "Vizitka za urejevalnik",
+               showhelp:       "Pomoè za urejevalnik",
+               textindicator:  "Trenutni slog",
+               undo:           "Razveljavi zadnjo akcijo",
+               redo:           "Uveljavi zadnjo akcijo",
+               cut:            "Izre¾i",
+               copy:           "Kopiraj",
+               paste:          "Prilepi"
+       },
+
+       buttons: {
+               "ok":           "V redu",
+               "cancel":       "Preklièi"
+       },
+
+       msg: {
+               "Path":         "Pot",
+               "TEXT_MODE":    "Si v tekstovnem naèinu.  Uporabi [<>] gumb za prklop nazaj na WYSIWYG."
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/vn.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/lang/vn.js
new file mode 100644 (file)
index 0000000..7742496
--- /dev/null
@@ -0,0 +1,51 @@
+// I18N constants : Vietnamese
+// LANG: "en", ENCODING: UTF-8
+// Author: Nguyễn Đình Nam, <hncryptologist@yahoo.com>
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "vn",
+
+       tooltips: {
+               bold:           "Đậm",
+               italic:         "Nghiêng",
+               underline:      "Gạch Chân",
+               strikethrough:  "Gạch Xóa",
+               subscript:      "Viết Xuống Dưới",
+               superscript:    "Viết Lên Trên",
+               justifyleft:    "Căn Trái",
+               justifycenter:  "Căn Giữa",
+               justifyright:   "Căn Phải",
+               justifyfull:    "Căn Đều",
+               orderedlist:    "Danh Sách Có Thứ Tự",
+               unorderedlist:  "Danh Sách Phi Thứ Tự",
+               outdent:        "Lùi Ra Ngoài",
+               indent:         "Thụt Vào Trong",
+               forecolor:      "Màu Chữ",
+               backcolor:      "Màu Nền",
+               horizontalrule: "Dòng Kẻ Ngang",
+               createlink:     "Tạo Liên Kết",
+               insertimage:    "Chèn Ảnh",
+               inserttable:    "Chèn Bảng",
+               htmlmode:       "Chế Độ Mã HTML",
+               popupeditor:    "Phóng To Ô Soạn Thảo",
+               about:          "Tự Giới Thiệu",
+               showhelp:       "Giúp Đỡ",
+               textindicator:  "Định Dạng Hiện Thời",
+               undo:           "Undo",
+               redo:           "Redo",
+               cut:            "Cắt",
+               copy:           "Copy",
+               paste:          "Dán"
+       },
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Hủy"
+       },
+       msg: {
+               "Path":         "Đường Dẫn",
+               "TEXT_MODE":    "Bạn đang ở chế độ text.  Sử dụng nút [<>] để chuyển lại chế độ WYSIWIG."
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/license.txt b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/license.txt
new file mode 100644 (file)
index 0000000..32ac404
--- /dev/null
@@ -0,0 +1,30 @@
+htmlArea License (based on BSD license)
+Copyright (c) 2002-2004, interactivetools.com, inc.
+Copyright (c) 2003-2004 dynarch.com
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1) Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+2) Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3) Neither the name of interactivetools.com, inc. nor the names of its
+   contributors may be used to endorse or promote products derived from this
+   software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/make-release.pl b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/make-release.pl
new file mode 100644 (file)
index 0000000..01168c0
--- /dev/null
@@ -0,0 +1,263 @@
+#! /usr/bin/perl -w
+# $Id: make-release.pl,v 1.1 2004/02/06 10:10:07 ugo Exp $
+
+# Script for creating a distribution archive.  Based on make-release.pl from
+# jscalendar.
+
+# Author: Mihai Bazon, http://dynarch.com/mishoo
+# NO WARRANTIES WHATSOEVER.  READ GNU LGPL.
+
+# This file requires HTML::Mason; this module is used for automatic
+# substitution of the version/release number as well as for selection of the
+# changelog (at least in the file release-notes.html).  It might not work
+# without HTML::Mason.
+
+use strict;
+# use diagnostics;
+use HTML::Mason;
+use File::Find;
+use XML::Parser;
+use Data::Dumper;
+
+my $verbosity = 1;
+
+my $tmpdir = '/tmp';
+
+my $config = parseXML("project-config.xml");
+speak(3, Data::Dumper::Dumper($config));
+
+my ($project, $version, $release, $basename);
+
+$project = $config->{project}{ATTR}{title};
+$version = $config->{project}{version}{DATA};
+$release = $config->{project}{release}{DATA};
+$basename = "$project-$version";
+$basename .= "-$release" if ($release);
+
+speak(1, "Project: $basename");
+
+## create directory tree
+my ($basedir);
+{
+    # base directory
+    $basedir = "$tmpdir/$basename";
+    if (-d $basedir) {
+        speak(-1, "$basedir already exists, removing... >:-]\n");
+        system "rm -rf $basedir";
+    }
+}
+
+process_directory();
+
+## make the ZIP file
+chdir "$basedir/..";
+speak(1, "Making ZIP file /tmp/$basename.zip");
+system ("zip -r $basename.zip $basename > /dev/null");
+system ("ls -la /tmp/$basename.zip");
+
+## remove the basedir
+system("rm -rf $basedir");
+
+## back
+#chdir $cwd;
+
+
+
+### SUBROUTINES
+
+# handle _one_ file
+sub process_one_file {
+    my ($attr, $target) = @_;
+
+    $target =~ s/\/$//;
+    $target .= '/';
+    my $destination = $target.$attr->{REALNAME};
+
+    # copy file first
+    speak(1, "   copying $attr->{REALNAME}");
+    system "cp $attr->{REALNAME} $destination";
+
+    my $masonize = $attr->{masonize} || '';
+    if ($masonize =~ /yes|on|1/i) {
+        speak(1, "   > masonizing to $destination...");
+        my $args = $attr->{args} || '';
+        my @vars = split(/\s*,\s*/, $args);
+        my %args = ();
+        foreach my $i (@vars) {
+            $args{$i} = eval '$'.$i;
+            speak(1, "      > argument: $i => $args{$i}");
+        }
+        my $outbuf;
+        my $interp = HTML::Mason::Interp->new ( comp_root    => $target,
+                                                out_method   => \$outbuf );
+        $interp->exec("/$attr->{REALNAME}", %args);
+        open (FILE, "> $destination");
+        print FILE $outbuf;
+        close (FILE);
+    }
+}
+
+# handle some files
+sub process_files {
+    my ($files, $target) = @_;
+
+    # proceed with the explicitely required files first
+    my %options = ();
+    foreach my $i (@{$files}) {
+        $options{$i->{ATTR}{name}} = $i->{ATTR};
+    }
+
+    foreach my $i (@{$files}) {
+        my @expanded = glob "$i->{ATTR}{name}";
+        foreach my $file (@expanded) {
+            $i->{ATTR}{REALNAME} = $file;
+            if (defined $options{$file}) {
+                unless (defined $options{$file}->{PROCESSED}) {
+                    speak(1, "EXPLICIT FILE: $file");
+                    $options{$file}->{REALNAME} = $file;
+                    process_one_file($options{$file}, $target);
+                    $options{$file}->{PROCESSED} = 1;
+                }
+            } else {
+                speak(2, "GLOB: $file");
+                process_one_file($i->{ATTR}, $target);
+                $options{$file} = 2;
+            }
+        }
+    }
+}
+
+# handle _one_ directory
+sub process_directory {
+    my ($dir, $path) = @_;
+    my $cwd = '..';             # ;-)
+
+    (defined $dir) || ($dir = '.');
+    (defined $path) || ($path = '');
+    speak(2, "DIR: $path$dir");
+    $dir =~ s/\/$//;
+    $dir .= '/';
+
+    unless (-d $dir) {
+        speak(-1, "DIRECTORY '$dir' NOT FOUND, SKIPPING");
+        return 0;
+    }
+
+    # go where we have stuff to do
+    chdir $dir;
+
+    my $target = $basedir;
+    ($path =~ /\S/) && ($target .= "/$path");
+    ($dir ne './') && ($target .= $dir);
+
+    speak(1, "*** Creating directory: $target");
+    mkdir $target;
+
+    unless (-f 'makefile.xml') {
+        speak(-1, "No makefile.xml in this directory");
+        chdir $cwd;
+        return 0;
+    }
+    my $config = parseXML("makefile.xml");
+    speak(3, Data::Dumper::Dumper($config));
+
+    my $tmp = $config->{files}{file};
+    if (defined $tmp) {
+        my $files;
+        if (ref($tmp) eq 'ARRAY') {
+            $files = $tmp;
+        } else {
+            $files = [ $tmp ];
+        }
+        process_files($files, $target);
+    }
+
+    $tmp = $config->{files}{dir};
+    if (defined $tmp) {
+        my $subdirs;
+        if (ref($tmp) eq 'ARRAY') {
+            $subdirs = $tmp;
+        } else {
+            $subdirs = [ $tmp ];
+        }
+        foreach my $i (@{$subdirs}) {
+            process_directory($i->{ATTR}{name}, $path.$dir);
+        }
+    }
+
+    # get back to our previous location
+    chdir $cwd;
+}
+
+# this does all the XML parsing shit we'll need for our little task
+sub parseXML {
+    my ($filename) = @_;
+    my $rethash = {};
+
+    my @tagstack;
+
+    my $handler_start = sub {
+        my ($parser, $tag, @attrs) = @_;
+        my $current_tag = {};
+        $current_tag->{NAME} = $tag;
+        $current_tag->{DATA} = '';
+        push @tagstack, $current_tag;
+        if (scalar @attrs) {
+            my $attrs = {};
+            $current_tag->{ATTR} = $attrs;
+            while (scalar @attrs) {
+                my $name = shift @attrs;
+                my $value = shift @attrs;
+                $attrs->{$name} = $value;
+            }
+        }
+    };
+
+    my $handler_char = sub {
+        my ($parser, $data) = @_;
+        if ($data =~ /\S/) {
+            $tagstack[$#tagstack]->{DATA} .= $data;
+        }
+    };
+
+    my $handler_end = sub {
+        my $current_tag = pop @tagstack;
+        if (scalar @tagstack) {
+            my $tmp = $tagstack[$#tagstack]->{$current_tag->{NAME}};
+            if (defined $tmp) {
+                ## better build an array, there are more elements with this tagname
+                if (ref($tmp) eq 'ARRAY') {
+                    ## oops, the ARRAY is already there, just add the new element
+                    push @{$tmp}, $current_tag;
+                } else {
+                    ## create the array "in-place"
+                    $tagstack[$#tagstack]->{$current_tag->{NAME}} = [ $tmp, $current_tag ];
+                }
+            } else {
+                $tagstack[$#tagstack]->{$current_tag->{NAME}} = $current_tag;
+            }
+        } else {
+            $rethash->{$current_tag->{NAME}} = $current_tag;
+        }
+    };
+
+    my $parser = new XML::Parser
+      ( Handlers => { Start => $handler_start,
+                      Char  => $handler_char,
+                      End   => $handler_end } );
+    $parser->parsefile($filename);
+
+    return $rethash;
+}
+
+# print somethign according to the level of verbosity
+# receives: verbosity_level and message
+# prints message if verbosity_level >= $verbosity (global)
+sub speak {
+    my ($v, $t) = @_;
+    if ($v < 0) {
+        print STDERR "\033[1;31m!! $t\033[0m\n";
+    } elsif ($verbosity >= $v) {
+        print $t, "\n";
+    }
+}
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/makefile.xml b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/makefile.xml
new file mode 100644 (file)
index 0000000..59cd114
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<files>
+  <file name="*.{js,html,css,cgi}" />
+  <file name="license.txt" />
+  <file name="release-notes.html" masonize="yes" />
+  <file name="index.html" masonize="yes" />
+  <file name="ChangeLog" />
+
+  <dir name="lang" />
+  <dir name="plugins" />
+  <dir name="popups" />
+  <dir name="images" />
+  <dir name="examples" />
+
+  <shell dir="dest"><![CDATA[
+    find . -type d               -exec chmod 755 {} \; ;
+    find . -type f               -exec chmod 644 {} \; ;
+    find . -type f -name "*.cgi" -exec chmod 755 {} \; ;
+  ]]></shell>
+</files>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/CSS/css.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/CSS/css.js
new file mode 100644 (file)
index 0000000..422d97f
--- /dev/null
@@ -0,0 +1,116 @@
+// Simple CSS (className) plugin for the editor
+// Sponsored by http://www.miro.com.au
+// Implementation by Mihai Bazon, http://dynarch.com/mishoo.
+//
+// (c) dynarch.com 2003
+// Distributed under the same terms as HTMLArea itself.
+// This notice MUST stay intact for use (see license.txt).
+//
+// $Id: css.js 30938 2004-07-29 19:08:16Z vgritsenko $
+
+function CSS(editor, params) {
+       this.editor = editor;
+       var cfg = editor.config;
+       var toolbar = cfg.toolbar;
+       var self = this;
+       var i18n = CSS.I18N;
+       var plugin_config = params[0];
+       var combos = plugin_config.combos;
+
+       var first = true;
+       for (var i = combos.length; --i >= 0;) {
+               var combo = combos[i];
+               var id = "CSS-class" + i;
+               var css_class = {
+                       id         : id,
+                       options    : combo.options,
+                       action     : function(editor) { self.onSelect(editor, this, combo.context, combo.updatecontextclass); },
+                       refresh    : function(editor) { self.updateValue(editor, this); },
+                       context    : combo.context
+               };
+               cfg.registerDropdown(css_class);
+
+               // prepend to the toolbar
+               toolbar[1].splice(0, 0, first ? "separator" : "space");
+               toolbar[1].splice(0, 0, id);
+               if (combo.label)
+                       toolbar[1].splice(0, 0, "T[" + combo.label + "]");
+               first = false;
+       }
+};
+
+CSS._pluginInfo = {
+       name          : "CSS",
+       version       : "1.0",
+       developer     : "Mihai Bazon",
+       developer_url : "http://dynarch.com/mishoo/",
+       c_owner       : "Mihai Bazon",
+       sponsor       : "Miro International",
+       sponsor_url   : "http://www.miro.com.au",
+       license       : "htmlArea"
+};
+
+CSS.prototype.onSelect = function(editor, obj, context, updatecontextclass) {
+       var tbobj = editor._toolbarObjects[obj.id];
+       var index = tbobj.element.selectedIndex;
+       var className = tbobj.element.value;
+
+       // retrieve parent element of the selection
+       var parent = editor.getParentElement();
+       var surround = true;
+
+       var is_span = (parent && parent.tagName.toLowerCase() == "span");
+       var update_parent = (context && updatecontextclass && parent && parent.tagName.toLowerCase() == context);
+
+       if (update_parent) {
+               parent.className = className;
+               editor.updateToolbar();
+               return;
+       }
+
+       if (is_span && index == 0 && !/\S/.test(parent.style.cssText)) {
+               while (parent.firstChild) {
+                       parent.parentNode.insertBefore(parent.firstChild, parent);
+               }
+               parent.parentNode.removeChild(parent);
+               editor.updateToolbar();
+               return;
+       }
+
+       if (is_span) {
+               // maybe we could simply change the class of the parent node?
+               if (parent.childNodes.length == 1) {
+                       parent.className = className;
+                       surround = false;
+                       // in this case we should handle the toolbar updation
+                       // ourselves.
+                       editor.updateToolbar();
+               }
+       }
+
+       // Other possibilities could be checked but require a lot of code.  We
+       // can't afford to do that now.
+       if (surround) {
+               // shit happens ;-) most of the time.  this method works, but
+               // it's dangerous when selection spans multiple block-level
+               // elements.
+               editor.surroundHTML("<span class='" + className + "'>", "</span>");
+       }
+};
+
+CSS.prototype.updateValue = function(editor, obj) {
+       var select = editor._toolbarObjects[obj.id].element;
+       var parent = editor.getParentElement();
+       if (typeof parent.className != "undefined" && /\S/.test(parent.className)) {
+               var options = select.options;
+               var value = parent.className;
+               for (var i = options.length; --i >= 0;) {
+                       var option = options[i];
+                       if (value == option.value) {
+                               select.selectedIndex = i;
+                               return;
+                       }
+               }
+       }
+       select.selectedIndex = 0;
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/CSS/lang/en.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/CSS/lang/en.js
new file mode 100644 (file)
index 0000000..7ffba00
--- /dev/null
@@ -0,0 +1,2 @@
+// none yet; this file is a stub.
+CSS.I18N = {};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/CSS/lang/makefile.xml b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/CSS/lang/makefile.xml
new file mode 100644 (file)
index 0000000..a44c5d7
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<files>
+  <file name="*.js" />
+</files>
+
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/CSS/makefile.xml b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/CSS/makefile.xml
new file mode 100644 (file)
index 0000000..60ca757
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<files>
+  <file name="*.{js,html,cgi,css}" />
+
+  <dir name="lang" />
+</files>
+
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/1.pl b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/1.pl
new file mode 100644 (file)
index 0000000..fdf6679
--- /dev/null
@@ -0,0 +1,38 @@
+#! /usr/bin/perl -w
+
+use strict;
+
+my $file = 'context-menu.js';
+my $outfile = $file.'-i18n';
+my $langfile = 'en.js';
+
+open FILE, "<$file";
+#open OUTFILE, ">$outfile";
+#open LANGFILE, ">$langfile";
+my %texts = ();
+while (<FILE>) {
+    if (/"(.*?)"/) {
+        my $inline = $_;
+        chomp $inline;
+        my $key = $1;
+        my $val = $1;
+        print "Key: [$key]: ";
+        my $line = <STDIN>;
+        if (defined $line) {
+            chomp $line;
+            if ($line =~ /(\S+)/) {
+                $key = $1;
+                print "-- using $key\n";
+            }
+            $texts{$val} = $key;
+        } else {
+            print " -- skipped...\n";
+        }
+    }
+}
+#close LANGFILE;
+#close OUTFILE;
+close FILE;
+
+print "\n\n\n";
+print '"', join("\"\n\"", sort keys %texts), '"', "\n";
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/context-menu.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/context-menu.js
new file mode 100644 (file)
index 0000000..ee44312
--- /dev/null
@@ -0,0 +1,416 @@
+// Context Menu Plugin for HTMLArea-3.0
+// Sponsored by www.americanbible.org
+// Implementation by Mihai Bazon, http://dynarch.com/mishoo/
+//
+// (c) dynarch.com 2003.
+// Distributed under the same terms as HTMLArea itself.
+// This notice MUST stay intact for use (see license.txt).
+//
+// $Id: context-menu.js 30938 2004-07-29 19:08:16Z vgritsenko $
+
+HTMLArea.loadStyle("menu.css", "ContextMenu");
+
+function ContextMenu(editor) {
+       this.editor = editor;
+};
+
+ContextMenu._pluginInfo = {
+       name          : "ContextMenu",
+       version       : "1.0",
+       developer     : "Mihai Bazon",
+       developer_url : "http://dynarch.com/mishoo/",
+       c_owner       : "dynarch.com",
+       sponsor       : "American Bible Society",
+       sponsor_url   : "http://www.americanbible.org",
+       license       : "htmlArea"
+};
+
+ContextMenu.prototype.onGenerate = function() {
+       var self = this;
+       var doc = this.editordoc = this.editor._iframe.contentWindow.document;
+       HTMLArea._addEvents(doc, ["contextmenu"],
+                           function (event) {
+                                   return self.popupMenu(HTMLArea.is_ie ? self.editor._iframe.contentWindow.event : event);
+                           });
+       this.currentMenu = null;
+};
+
+ContextMenu.prototype.getContextMenu = function(target) {
+       var self = this;
+       var editor = this.editor;
+       var config = editor.config;
+       var menu = [];
+       var tbo = this.editor.plugins.TableOperations;
+       if (tbo) tbo = tbo.instance;
+       var i18n = ContextMenu.I18N;
+
+       var selection = editor.hasSelectedText();
+       if (selection)
+               menu.push([ i18n["Cut"], function() { editor.execCommand("cut"); }, null, config.btnList["cut"][1] ],
+                         [ i18n["Copy"], function() { editor.execCommand("copy"); }, null, config.btnList["copy"][1] ]);
+       menu.push([ i18n["Paste"], function() { editor.execCommand("paste"); }, null, config.btnList["paste"][1] ]);
+
+       var currentTarget = target;
+       var elmenus = [];
+
+       var link = null;
+       var table = null;
+       var tr = null;
+       var td = null;
+       var img = null;
+
+       function tableOperation(opcode) {
+               tbo.buttonPress(editor, opcode);
+       };
+
+       for (; target; target = target.parentNode) {
+               var tag = target.tagName;
+               if (!tag)
+                       continue;
+               tag = tag.toLowerCase();
+               switch (tag) {
+                   case "img":
+                       img = target;
+                       elmenus.push(null,
+                                    [ i18n["Image Properties"],
+                                      function() {
+                                              editor._insertImage(img);
+                                      },
+                                      i18n["Show the image properties dialog"],
+                                      config.btnList["insertimage"][1] ]
+                               );
+                       break;
+                   case "a":
+                       link = target;
+                       elmenus.push(null,
+                                    [ i18n["Modify Link"],
+                                      function() { editor.execCommand("createlink", true); },
+                                      i18n["Current URL is"] + ': ' + link.href,
+                                      config.btnList["createlink"][1] ],
+
+                                    [ i18n["Check Link"],
+                                      function() { window.open(link.href); },
+                                      i18n["Opens this link in a new window"] ],
+
+                                    [ i18n["Remove Link"],
+                                      function() {
+                                              if (confirm(i18n["Please confirm that you want to unlink this element."] + "\n" +
+                                                          i18n["Link points to:"] + " " + link.href)) {
+                                                      while (link.firstChild)
+                                                              link.parentNode.insertBefore(link.firstChild, link);
+                                                      link.parentNode.removeChild(link);
+                                              }
+                                      },
+                                      i18n["Unlink the current element"] ]
+                               );
+                       break;
+                   case "td":
+                       td = target;
+                       if (!tbo) break;
+                       elmenus.push(null,
+                                    [ i18n["Cell Properties"],
+                                      function() { tableOperation("TO-cell-prop"); },
+                                      i18n["Show the Table Cell Properties dialog"],
+                                      config.btnList["TO-cell-prop"][1] ]
+                               );
+                       break;
+                   case "tr":
+                       tr = target;
+                       if (!tbo) break;
+                       elmenus.push(null,
+                                    [ i18n["Row Properties"],
+                                      function() { tableOperation("TO-row-prop"); },
+                                      i18n["Show the Table Row Properties dialog"],
+                                      config.btnList["TO-row-prop"][1] ],
+
+                                    [ i18n["Insert Row Before"],
+                                      function() { tableOperation("TO-row-insert-above"); },
+                                      i18n["Insert a new row before the current one"],
+                                      config.btnList["TO-row-insert-above"][1] ],
+
+                                    [ i18n["Insert Row After"],
+                                      function() { tableOperation("TO-row-insert-under"); },
+                                      i18n["Insert a new row after the current one"],
+                                      config.btnList["TO-row-insert-under"][1] ],
+
+                                    [ i18n["Delete Row"],
+                                      function() { tableOperation("TO-row-delete"); },
+                                      i18n["Delete the current row"],
+                                      config.btnList["TO-row-delete"][1] ]
+                               );
+                       break;
+                   case "table":
+                       table = target;
+                       if (!tbo) break;
+                       elmenus.push(null,
+                                    [ i18n["Table Properties"],
+                                      function() { tableOperation("TO-table-prop"); },
+                                      i18n["Show the Table Properties dialog"],
+                                      config.btnList["TO-table-prop"][1] ],
+
+                                    [ i18n["Insert Column Before"],
+                                      function() { tableOperation("TO-col-insert-before"); },
+                                      i18n["Insert a new column before the current one"],
+                                      config.btnList["TO-col-insert-before"][1] ],
+
+                                    [ i18n["Insert Column After"],
+                                      function() { tableOperation("TO-col-insert-after"); },
+                                      i18n["Insert a new column after the current one"],
+                                      config.btnList["TO-col-insert-after"][1] ],
+
+                                    [ i18n["Delete Column"],
+                                      function() { tableOperation("TO-col-delete"); },
+                                      i18n["Delete the current column"],
+                                      config.btnList["TO-col-delete"][1] ]
+                               );
+                       break;
+                   case "body":
+                       elmenus.push(null,
+                                    [ i18n["Justify Left"],
+                                      function() { editor.execCommand("justifyleft"); }, null,
+                                      config.btnList["justifyleft"][1] ],
+                                    [ i18n["Justify Center"],
+                                      function() { editor.execCommand("justifycenter"); }, null,
+                                      config.btnList["justifycenter"][1] ],
+                                    [ i18n["Justify Right"],
+                                      function() { editor.execCommand("justifyright"); }, null,
+                                      config.btnList["justifyright"][1] ],
+                                    [ i18n["Justify Full"],
+                                      function() { editor.execCommand("justifyfull"); }, null,
+                                      config.btnList["justifyfull"][1] ]
+                               );
+                       break;
+               }
+       }
+
+       if (selection && !link)
+               menu.push(null, [ i18n["Make link"],
+                                 function() { editor.execCommand("createlink", true); },
+                                 i18n["Create a link"],
+                                 config.btnList["createlink"][1] ]);
+
+       for (var i in elmenus)
+               menu.push(elmenus[i]);
+
+       menu.push(null,
+                 [ i18n["Remove the"] + " &lt;" + currentTarget.tagName + "&gt; " + i18n["Element"],
+                   function() {
+                           if (confirm(i18n["Please confirm that you want to remove this element:"] + " " + currentTarget.tagName)) {
+                                   var el = currentTarget;
+                                   var p = el.parentNode;
+                                   p.removeChild(el);
+                                   if (HTMLArea.is_gecko) {
+                                           if (p.tagName.toLowerCase() == "td" && !p.hasChildNodes())
+                                                   p.appendChild(editor._doc.createElement("br"));
+                                           editor.forceRedraw();
+                                           editor.focusEditor();
+                                           editor.updateToolbar();
+                                           if (table) {
+                                                   var save_collapse = table.style.borderCollapse;
+                                                   table.style.borderCollapse = "collapse";
+                                                   table.style.borderCollapse = "separate";
+                                                   table.style.borderCollapse = save_collapse;
+                                           }
+                                   }
+                           }
+                   },
+                   i18n["Remove this node from the document"] ]);
+       return menu;
+};
+
+ContextMenu.prototype.popupMenu = function(ev) {
+       var self = this;
+       var i18n = ContextMenu.I18N;
+       if (this.currentMenu)
+               this.currentMenu.parentNode.removeChild(this.currentMenu);
+       function getPos(el) {
+               var r = { x: el.offsetLeft, y: el.offsetTop };
+               if (el.offsetParent) {
+                       var tmp = getPos(el.offsetParent);
+                       r.x += tmp.x;
+                       r.y += tmp.y;
+               }
+               return r;
+       };
+       function documentClick(ev) {
+               ev || (ev = window.event);
+               if (!self.currentMenu) {
+                       alert(i18n["How did you get here? (Please report!)"]);
+                       return false;
+               }
+               var el = HTMLArea.is_ie ? ev.srcElement : ev.target;
+               for (; el != null && el != self.currentMenu; el = el.parentNode);
+               if (el == null)
+                       self.closeMenu();
+               //HTMLArea._stopEvent(ev);
+               //return false;
+       };
+       var keys = [];
+       function keyPress(ev) {
+               ev || (ev = window.event);
+               HTMLArea._stopEvent(ev);
+               if (ev.keyCode == 27) {
+                       self.closeMenu();
+                       return false;
+               }
+               var key = String.fromCharCode(HTMLArea.is_ie ? ev.keyCode : ev.charCode).toLowerCase();
+               for (var i = keys.length; --i >= 0;) {
+                       var k = keys[i];
+                       if (k[0].toLowerCase() == key)
+                               k[1].__msh.activate();
+               }
+       };
+       self.closeMenu = function() {
+               self.currentMenu.parentNode.removeChild(self.currentMenu);
+               self.currentMenu = null;
+               HTMLArea._removeEvent(document, "mousedown", documentClick);
+               HTMLArea._removeEvent(self.editordoc, "mousedown", documentClick);
+               if (keys.length > 0)
+                       HTMLArea._removeEvent(self.editordoc, "keypress", keyPress);
+               if (HTMLArea.is_ie)
+                       self.iePopup.hide();
+       };
+       var target = HTMLArea.is_ie ? ev.srcElement : ev.target;
+       var ifpos = getPos(self.editor._iframe);
+       var x = ev.clientX + ifpos.x;
+       var y = ev.clientY + ifpos.y;
+
+       var div;
+       var doc;
+       if (!HTMLArea.is_ie) {
+               doc = document;
+       } else {
+               // IE stinks
+               var popup = this.iePopup = window.createPopup();
+               doc = popup.document;
+               doc.open();
+               doc.write("<html><head><style type='text/css'>@import url(" + _editor_url + "plugins/ContextMenu/menu.css); html, body { padding: 0px; margin: 0px; overflow: hidden; border: 0px; }</style></head><body unselectable='yes'></body></html>");
+               doc.close();
+       }
+       div = doc.createElement("div");
+       if (HTMLArea.is_ie)
+               div.unselectable = "on";
+       div.oncontextmenu = function() { return false; };
+       div.className = "htmlarea-context-menu";
+       if (!HTMLArea.is_ie)
+               div.style.left = div.style.top = "0px";
+       doc.body.appendChild(div);
+
+       var table = doc.createElement("table");
+       div.appendChild(table);
+       table.cellSpacing = 0;
+       table.cellPadding = 0;
+       var parent = doc.createElement("tbody");
+       table.appendChild(parent);
+
+       var options = this.getContextMenu(target);
+       for (var i = 0; i < options.length; ++i) {
+               var option = options[i];
+               var item = doc.createElement("tr");
+               parent.appendChild(item);
+               if (HTMLArea.is_ie)
+                       item.unselectable = "on";
+               else item.onmousedown = function(ev) {
+                       HTMLArea._stopEvent(ev);
+                       return false;
+               };
+               if (!option) {
+                       item.className = "separator";
+                       var td = doc.createElement("td");
+                       td.className = "icon";
+                       var IE_IS_A_FUCKING_SHIT = '>';
+                       if (HTMLArea.is_ie) {
+                               td.unselectable = "on";
+                               IE_IS_A_FUCKING_SHIT = " unselectable='on' style='height=1px'>&nbsp;";
+                       }
+                       td.innerHTML = "<div" + IE_IS_A_FUCKING_SHIT + "</div>";
+                       var td1 = td.cloneNode(true);
+                       td1.className = "label";
+                       item.appendChild(td);
+                       item.appendChild(td1);
+               } else {
+                       var label = option[0];
+                       item.className = "item";
+                       item.__msh = {
+                               item: item,
+                               label: label,
+                               action: option[1],
+                               tooltip: option[2] || null,
+                               icon: option[3] || null,
+                               activate: function() {
+                                       self.closeMenu();
+                                       self.editor.focusEditor();
+                                       this.action();
+                               }
+                       };
+                       label = label.replace(/_([a-zA-Z0-9])/, "<u>$1</u>");
+                       if (label != option[0])
+                               keys.push([ RegExp.$1, item ]);
+                       label = label.replace(/__/, "_");
+                       var td1 = doc.createElement("td");
+                       if (HTMLArea.is_ie)
+                               td1.unselectable = "on";
+                       item.appendChild(td1);
+                       td1.className = "icon";
+                       if (item.__msh.icon)
+                               td1.innerHTML = "<img align='middle' src='" + item.__msh.icon + "' />";
+                       var td2 = doc.createElement("td");
+                       if (HTMLArea.is_ie)
+                               td2.unselectable = "on";
+                       item.appendChild(td2);
+                       td2.className = "label";
+                       td2.innerHTML = label;
+                       item.onmouseover = function() {
+                               this.className += " hover";
+                               self.editor._statusBarTree.innerHTML = this.__msh.tooltip || '&nbsp;';
+                       };
+                       item.onmouseout = function() { this.className = "item"; };
+                       item.oncontextmenu = function(ev) {
+                               this.__msh.activate();
+                               if (!HTMLArea.is_ie)
+                                       HTMLArea._stopEvent(ev);
+                               return false;
+                       };
+                       item.onmouseup = function(ev) {
+                               var timeStamp = (new Date()).getTime();
+                               if (timeStamp - self.timeStamp > 500)
+                                       this.__msh.activate();
+                               if (!HTMLArea.is_ie)
+                                       HTMLArea._stopEvent(ev);
+                               return false;
+                       };
+                       //if (typeof option[2] == "string")
+                       //item.title = option[2];
+               }
+       }
+
+       if (!HTMLArea.is_ie) {
+               var dx = x + div.offsetWidth - window.innerWidth + 4;
+               var dy = y + div.offsetHeight - window.innerHeight + 4;
+               if (dx > 0) x -= dx;
+               if (dy > 0) y -= dy;
+               div.style.left = x + "px";
+               div.style.top = y + "px";
+       } else {
+               // determine the size (did I mention that IE stinks?)
+               var foobar = document.createElement("div");
+               foobar.className = "htmlarea-context-menu";
+               foobar.innerHTML = div.innerHTML;
+               document.body.appendChild(foobar);
+               var w = foobar.offsetWidth;
+               var h = foobar.offsetHeight;
+               document.body.removeChild(foobar);
+               this.iePopup.show(ev.screenX, ev.screenY, w, h);
+       }
+
+       this.currentMenu = div;
+       this.timeStamp = (new Date()).getTime();
+
+       HTMLArea._addEvent(document, "mousedown", documentClick);
+       HTMLArea._addEvent(this.editordoc, "mousedown", documentClick);
+       if (keys.length > 0)
+               HTMLArea._addEvent(this.editordoc, "keypress", keyPress);
+
+       HTMLArea._stopEvent(ev);
+       return false;
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/lang/de.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/lang/de.js
new file mode 100644 (file)
index 0000000..e9f1fed
--- /dev/null
@@ -0,0 +1,59 @@
+// I18N constants
+
+// LANG: "de", ENCODING: UTF-8 | ISO-8859-1
+
+// translated: <]{MJ}[>  i@student.ethz.ch
+
+
+ContextMenu.I18N = {
+       // Items that appear in menu.  Please note that an underscore (_)
+       // character in the translation (right column) will cause the following
+       // letter to become underlined and be shortcut for that menu option.
+
+       "Cut"                                                   : "Ausschneiden",
+       "Copy"                                                  : "Kopieren",
+       "Paste"                                                 : "Einfügen",
+       "Image Properties"                                      : "_Bild Einstellungen...",
+       "Modify Link"                                           : "_Link ändern...",
+       "Check Link"                                            : "Link testen...",
+       "Remove Link"                                           : "Link entfernen...",
+       "Cell Properties"                                       : "Z_ellen Einstellungen...",
+       "Row Properties"                                        : "Ze_ilen Einstellungen...",
+       "Insert Row Before"                                     : "Zeile einfügen v_or Position",
+       "Insert Row After"                                      : "Zeile einfügen n_ach Position",
+       "Delete Row"                                            : "Zeile löschen",
+       "Table Properties"                                      : "_Tabellen Einstellungen...",
+       "Insert Column Before"                                  : "Spalte einfügen vo_r Position",
+       "Insert Column After"                                   : "Spalte einfügen na_ch Position",
+       "Delete Column"                                         : "Spalte löschen",
+       "Justify Left"                                          : "Links ausrichten",
+       "Justify Center"                                        : "Zentriert",
+       "Justify Right"                                         : "Rechts ausrichten",
+       "Justify Full"                                          : "Blocksatz",
+       "Make link"                                             : "Lin_k erstellen...",
+       "Remove the"                                            : "",
+       "Element"                                               : "Element entfernen...",
+
+       // Other labels (tooltips and alert/confirm box messages)
+
+       "Please confirm that you want to remove this element:"  : "Wollen sie dieses Element wirklich entfernen ?",
+       "Remove this node from the document"                    : "Dieses Element aus dem Dokument entfernen",
+       "How did you get here? (Please report!)"                : "How did you get here? (Please report!)",
+       "Show the image properties dialog"                      : "Fenster für die Bild-Einstellungen anzeigen",
+       "Modify URL"                                            : "URL ändern",
+       "Current URL is"                                        : "Aktuelle URL ist",
+       "Opens this link in a new window"                       : "Diesen Link in neuem Fenster öffnen",
+       "Please confirm that you want to unlink this element."  : "Wollen sie diesen Link wirklich entfernen ?",
+       "Link points to:"                                       : "Link zeigt auf:",
+       "Unlink the current element"                            : "Link auf Element entfernen",
+       "Show the Table Cell Properties dialog"                 : "Zellen-Einstellungen anzeigen",
+       "Show the Table Row Properties dialog"                  : "Zeilen-Einstellungen anzeigen",
+       "Insert a new row before the current one"               : "Zeile einfügen vor der aktuellen Position",
+       "Insert a new row after the current one"                : "Zeile einfügen nach der aktuellen Position",
+       "Delete the current row"                                : "Zeile löschen",
+       "Show the Table Properties dialog"                      : "Show the Table Properties dialog",
+       "Insert a new column before the current one"            : "Spalte einfügen vor der aktuellen Position",
+       "Insert a new column after the current one"             : "Spalte einfügen nach der aktuellen Position",
+       "Delete the current column"                             : "Spalte löschen",
+       "Create a link"                                         : "Link erstellen"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/lang/el.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/lang/el.js
new file mode 100644 (file)
index 0000000..68bbaf2
--- /dev/null
@@ -0,0 +1,57 @@
+// I18N constants
+
+// LANG: "el", ENCODING: UTF-8 | ISO-8859-7
+// Author: Dimitris Glezos, dimitris@glezos.com
+
+ContextMenu.I18N = {
+       // Items that appear in menu.  Please note that an underscore (_)
+       // character in the translation (right column) will cause the following
+       // letter to become underlined and be shortcut for that menu option.
+
+       "Cut"                                                   : "Αποκοπή",
+       "Copy"                                                  : "Αντιγραφή",
+       "Paste"                                                 : "Επικόλληση",
+       "Image Properties"                                      : "Ιδιότητες Εικόνας...",
+       "Modify Link"                                           : "Τροποποίηση συνδέσμου...",
+       "Check Link"                                            : "Έλεγχος συνδέσμων...",
+       "Remove Link"                                           : "Διαγραφή συνδέσμου...",
+       "Cell Properties"                                       : "Ιδιότητες κελιού...",
+       "Row Properties"                                        : "Ιδιότητες γραμμής...",
+       "Insert Row Before"                                     : "Εισαγωγή γραμμής πριν",
+       "Insert Row After"                                      : "Εισαγωγή γραμμής μετά",
+       "Delete Row"                                            : "Διαγραφή γραμμής",
+       "Table Properties"                                      : "Ιδιότητες πίνακα...",
+       "Insert Column Before"                                  : "Εισαγωγή στήλης πριν",
+       "Insert Column After"                                   : "Εισαγωγή στήλης μετά",
+       "Delete Column"                                         : "Διαγραφή στήλης",
+       "Justify Left"                                          : "Στοίχηση Αριστερά",
+       "Justify Center"                                        : "Στοίχηση Κέντρο",
+       "Justify Right"                                         : "Στοίχηση Δεξιά",
+       "Justify Full"                                          : "Πλήρης Στοίχηση",
+       "Make link"                                             : "Δημιουργία συνδέσμου...",
+       "Remove the"                                            : "Αφαίρεση",
+       "Element"                                               : "στοιχείου...",
+
+       // Other labels (tooltips and alert/confirm box messages)
+
+       "Please confirm that you want to remove this element:"  : "Είστε βέβαιος πως θέλετε να αφαιρέσετε το στοιχείο ",
+       "Remove this node from the document"                    : "Αφαίρεση αυτού του κόμβου από το έγγραφο",
+       "How did you get here? (Please report!)"                : "Πώς ήρθατε μέχρι εδώ; (Παρακαλούμε αναφέρετε το!)",
+       "Show the image properties dialog"                      : "Εμφάνιση διαλόγου με τις Ιδιότητες εικόνας",
+       "Modify URL"                                            : "Τροποποίηση URL",
+       "Current URL is"                                        : "Το τρέχων URL είναι",
+       "Opens this link in a new window"                       : "Ανοίγει αυτό τον σύνδεσμο σε ένα νέο παράθυρο",
+       "Please confirm that you want to unlink this element."  : "Είστε βέβαιος πως θέλετε να αφαιρέσετε τον σύνδεσμο από αυτό το στοιχείο:",
+       "Link points to:"                                       : "Ο σύνδεμος οδηγεί εδώ:",
+       "Unlink the current element"                            : "Αφαίρεση συνδέσμου από το παρών στοιχείο",
+       "Show the Table Cell Properties dialog"                 : "Εμφάνιση διαλόγου με τις Ιδιότητες κελιού Πίνακα",
+       "Show the Table Row Properties dialog"                  : "Εμφάνιση διαλόγου με τις Ιδιότητες γραμμής Πίνακα",
+       "Insert a new row before the current one"               : "Εισαγωγή μιας νέας γραμμής πριν την επιλεγμένη",
+       "Insert a new row after the current one"                : "Εισαγωγή μιας νέας γραμμής μετά την επιλεγμένη",
+       "Delete the current row"                                : "Διαγραφή επιλεγμένης γραμμής",
+       "Show the Table Properties dialog"                      : "Εμφάνιση διαλόγου με τις Ιδιότητες Πίνακα",
+       "Insert a new column before the current one"            : "Εισαγωγή νέας στήλης πριν την επιλεγμένη",
+       "Insert a new column after the current one"             : "Εισαγωγή νέας στήλης μετά την επιλεγμένη",
+       "Delete the current column"                             : "Διαγραφή επιλεγμένης στήλης",
+       "Create a link"                                         : "Δημιουργία συνδέσμου"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/lang/en.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/lang/en.js
new file mode 100644 (file)
index 0000000..8d15914
--- /dev/null
@@ -0,0 +1,66 @@
+// I18N constants
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+ContextMenu.I18N = {
+       // Items that appear in menu.  Please note that an underscore (_)
+       // character in the translation (right column) will cause the following
+       // letter to become underlined and be shortcut for that menu option.
+
+       "Cut"                                                   : "Cut",
+       "Copy"                                                  : "Copy",
+       "Paste"                                                 : "Paste",
+       "Image Properties"                                      : "_Image Properties...",
+       "Modify Link"                                           : "_Modify Link...",
+       "Check Link"                                            : "Chec_k Link...",
+       "Remove Link"                                           : "_Remove Link...",
+       "Cell Properties"                                       : "C_ell Properties...",
+       "Row Properties"                                        : "Ro_w Properties...",
+       "Insert Row Before"                                     : "I_nsert Row Before",
+       "Insert Row After"                                      : "In_sert Row After",
+       "Delete Row"                                            : "_Delete Row",
+       "Table Properties"                                      : "_Table Properties...",
+       "Insert Column Before"                                  : "Insert _Column Before",
+       "Insert Column After"                                   : "Insert C_olumn After",
+       "Delete Column"                                         : "De_lete Column",
+       "Justify Left"                                          : "Justify Left",
+       "Justify Center"                                        : "Justify Center",
+       "Justify Right"                                         : "Justify Right",
+       "Justify Full"                                          : "Justify Full",
+       "Make link"                                             : "Make lin_k...",
+       "Remove the"                                            : "Remove the",
+       "Element"                                               : "Element...",
+
+       // Other labels (tooltips and alert/confirm box messages)
+
+       "Please confirm that you want to remove this element:"  : "Please confirm that you want to remove this element:",
+       "Remove this node from the document"                    : "Remove this node from the document",
+       "How did you get here? (Please report!)"                : "How did you get here? (Please report!)",
+       "Show the image properties dialog"                      : "Show the image properties dialog",
+       "Modify URL"                                            : "Modify URL",
+       "Current URL is"                                        : "Current URL is",
+       "Opens this link in a new window"                       : "Opens this link in a new window",
+       "Please confirm that you want to unlink this element."  : "Please confirm that you want to unlink this element.",
+       "Link points to:"                                       : "Link points to:",
+       "Unlink the current element"                            : "Unlink the current element",
+       "Show the Table Cell Properties dialog"                 : "Show the Table Cell Properties dialog",
+       "Show the Table Row Properties dialog"                  : "Show the Table Row Properties dialog",
+       "Insert a new row before the current one"               : "Insert a new row before the current one",
+       "Insert a new row after the current one"                : "Insert a new row after the current one",
+       "Delete the current row"                                : "Delete the current row",
+       "Show the Table Properties dialog"                      : "Show the Table Properties dialog",
+       "Insert a new column before the current one"            : "Insert a new column before the current one",
+       "Insert a new column after the current one"             : "Insert a new column after the current one",
+       "Delete the current column"                             : "Delete the current column",
+       "Create a link"                                         : "Create a link"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/lang/makefile.xml b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/lang/makefile.xml
new file mode 100644 (file)
index 0000000..0d645c9
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<files>
+  <file name="*.js" />
+</files>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/lang/nl.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/lang/nl.js
new file mode 100644 (file)
index 0000000..a91e1f5
--- /dev/null
@@ -0,0 +1,66 @@
+// I18N constants
+
+// LANG: "nl", ENCODING: UTF-8 | ISO-8859-1
+// Author: Michel Weegeerink (info@mmc-shop.nl), http://mmc-shop.nl
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+ContextMenu.I18N = {
+       // Items that appear in menu.  Please note that an underscore (_)
+       // character in the translation (right column) will cause the following
+       // letter to become underlined and be shortcut for that menu option.
+
+       "Cut"                                                   : "Knippen",
+       "Copy"                                                  : "Kopiëren",
+       "Paste"                                                 : "Plakken",
+       "Image Properties"                                      : "Eigenschappen afbeelding...",
+       "Modify Link"                                           : "Hyperlin_k aanpassen...",
+       "Check Link"                                            : "Controleer hyperlin_k...",
+       "Remove Link"                                           : "Ve_rwijder hyperlink...",
+       "Cell Properties"                                       : "C_eleigenschappen...",
+       "Row Properties"                                        : "Rijeigenscha_ppen...",
+       "Insert Row Before"                                     : "Rij invoegen boven",
+       "Insert Row After"                                      : "Rij invoegen onder",
+       "Delete Row"                                            : "Rij _verwijderen",
+       "Table Properties"                                      : "_Tabeleigenschappen...",
+       "Insert Column Before"                                  : "Kolom invoegen voor",
+       "Insert Column After"                                   : "Kolom invoegen na",
+       "Delete Column"                                         : "Kolom verwijderen",
+       "Justify Left"                                          : "Links uitlijnen",
+       "Justify Center"                                        : "Centreren",
+       "Justify Right"                                         : "Rechts uitlijnen",
+       "Justify Full"                                          : "Uitvullen",
+       "Make link"                                             : "Maak hyperlin_k...",
+       "Remove the"                                            : "Verwijder het",
+       "Element"                                               : "element...",
+
+       // Other labels (tooltips and alert/confirm box messages)
+
+       "Please confirm that you want to remove this element:"  : "Is het werkelijk de bedoeling dit element te verwijderen:",
+       "Remove this node from the document"                    : "Verwijder dit punt van het document",
+       "How did you get here? (Please report!)"                : "Hoe kwam je hier? (A.U.B. doorgeven!)",
+       "Show the image properties dialog"                      : "Laat het afbeeldingseigenschappen dialog zien",
+       "Modify URL"                                            : "Aanpassen URL",
+       "Current URL is"                                        : "Huidig URL is",
+       "Opens this link in a new window"                       : "Opend deze hyperlink in een nieuw venster",
+       "Please confirm that you want to unlink this element."  : "Is het werkelijk de bedoeling dit element te unlinken.",
+       "Link points to:"                                       : "Hyperlink verwijst naar:",
+       "Unlink the current element"                            : "Unlink het huidige element",
+       "Show the Table Cell Properties dialog"                 : "Laat de tabel celeigenschappen dialog zien",
+       "Show the Table Row Properties dialog"                  : "Laat de tabel rijeigenschappen dialog zien",
+       "Insert a new row before the current one"               : "Voeg een nieuwe rij in boven de huidige",
+       "Insert a new row after the current one"                : "Voeg een nieuwe rij in onder de huidige",
+       "Delete the current row"                                : "Verwijder de huidige rij",
+       "Show the Table Properties dialog"                      : "Laat de tabel eigenschappen dialog zien",
+       "Insert a new column before the current one"            : "Voeg een nieuwe kolom in voor de huidige",
+       "Insert a new column after the current one"             : "Voeg een nieuwe kolom in na de huidige",
+       "Delete the current column"                             : "Verwijder de huidige kolom",
+       "Create a link"                                         : "Maak een hyperlink"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/makefile.xml b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/makefile.xml
new file mode 100644 (file)
index 0000000..60ca757
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<files>
+  <file name="*.{js,html,cgi,css}" />
+
+  <dir name="lang" />
+</files>
+
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/menu.css b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/ContextMenu/menu.css
new file mode 100644 (file)
index 0000000..70626b5
--- /dev/null
@@ -0,0 +1,64 @@
+/* styles for the ContextMenu /HTMLArea */
+/* The ContextMenu plugin is (c) dynarch.com 2003. */
+/* Distributed under the same terms as HTMLArea itself */
+
+div.htmlarea-context-menu {
+  position: absolute;
+  border: 1px solid #aca899;
+  padding: 2px;
+  background-color: #fff;
+  cursor: default;
+  z-index: 1000;
+}
+
+div.htmlarea-context-menu table {
+  font: 11px tahoma,verdana,sans-serif;
+  border-collapse: collapse;
+}
+
+div.htmlarea-context-menu tr.item td.icon img {
+  width: 18px;
+  height: 18px;
+}
+
+div.htmlarea-context-menu tr.item td.icon {
+  padding: 0px 3px;
+  height: 18px;
+  background-color: #cdf;
+}
+
+div.htmlarea-context-menu tr.item td.label {
+  padding: 1px 10px 1px 3px;
+}
+
+div.htmlarea-context-menu tr.separator td {
+  padding: 2px 0px;
+}
+
+div.htmlarea-context-menu tr.separator td div {
+  border-top: 1px solid #aca899;
+  overflow: hidden;
+  position: relative;
+}
+
+div.htmlarea-context-menu tr.separator td.icon {
+  background-color: #cdf;
+}
+
+div.htmlarea-context-menu tr.separator td.icon div {
+/*  margin-left: 3px; */
+  border-color: #fff;
+}
+
+div.htmlarea-context-menu tr.separator td.label div {
+  margin-right: 3px;
+}
+
+div.htmlarea-context-menu tr.item.hover {
+  background-color: #316ac5;
+  color: #fff;
+}
+
+div.htmlarea-context-menu tr.item.hover td.icon {
+  background-color: #619af5;
+}
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/full-page.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/full-page.js
new file mode 100644 (file)
index 0000000..aee1f61
--- /dev/null
@@ -0,0 +1,143 @@
+// FullPage Plugin for HTMLArea-3.0
+// Implementation by Mihai Bazon.  Sponsored by http://thycotic.com
+//
+// htmlArea v3.0 - Copyright (c) 2002 interactivetools.com, inc.
+// This notice MUST stay intact for use (see license.txt).
+//
+// A free WYSIWYG editor replacement for <textarea> fields.
+// For full source code and docs, visit http://www.interactivetools.com/
+//
+// Version 3.0 developed by Mihai Bazon for InteractiveTools.
+//   http://dynarch.com/mishoo
+//
+// $Id: full-page.js 30938 2004-07-29 19:08:16Z vgritsenko $
+
+function FullPage(editor) {
+       this.editor = editor;
+
+       var cfg = editor.config;
+       cfg.fullPage = true;
+       var tt = FullPage.I18N;
+       var self = this;
+
+       cfg.registerButton("FP-docprop", tt["Document properties"], editor.imgURL("docprop.gif", "FullPage"), false,
+                          function(editor, id) {
+                                  self.buttonPress(editor, id);
+                          });
+
+       // add a new line in the toolbar
+       cfg.toolbar[0].splice(0, 0, "separator");
+       cfg.toolbar[0].splice(0, 0, "FP-docprop");
+};
+
+FullPage._pluginInfo = {
+       name          : "FullPage",
+       version       : "1.0",
+       developer     : "Mihai Bazon",
+       developer_url : "http://dynarch.com/mishoo/",
+       c_owner       : "Mihai Bazon",
+       sponsor       : "Thycotic Software Ltd.",
+       sponsor_url   : "http://thycotic.com",
+       license       : "htmlArea"
+};
+
+FullPage.prototype.buttonPress = function(editor, id) {
+       var self = this;
+       switch (id) {
+           case "FP-docprop":
+               var doc = editor._doc;
+               var links = doc.getElementsByTagName("link");
+               var style1 = '';
+               var style2 = '';
+               for (var i = links.length; --i >= 0;) {
+                       var link = links[i];
+                       if (/stylesheet/i.test(link.rel)) {
+                               if (/alternate/i.test(link.rel))
+                                       style2 = link.href;
+                               else
+                                       style1 = link.href;
+                       }
+               }
+               var title = doc.getElementsByTagName("title")[0];
+               title = title ? title.innerHTML : '';
+               var init = {
+                       f_doctype      : editor.doctype,
+                       f_title        : title,
+                       f_body_bgcolor : HTMLArea._colorToRgb(doc.body.style.backgroundColor),
+                       f_body_fgcolor : HTMLArea._colorToRgb(doc.body.style.color),
+                       f_base_style   : style1,
+                       f_alt_style    : style2,
+
+                       editor         : editor
+               };
+               editor._popupDialog("plugin://FullPage/docprop", function(params) {
+                       self.setDocProp(params);
+               }, init);
+               break;
+       }
+};
+
+FullPage.prototype.setDocProp = function(params) {
+       var txt = "";
+       var doc = this.editor._doc;
+       var head = doc.getElementsByTagName("head")[0];
+       var links = doc.getElementsByTagName("link");
+       var style1 = null;
+       var style2 = null;
+       for (var i = links.length; --i >= 0;) {
+               var link = links[i];
+               if (/stylesheet/i.test(link.rel)) {
+                       if (/alternate/i.test(link.rel))
+                               style2 = link;
+                       else
+                               style1 = link;
+               }
+       }
+       function createLink(alt) {
+               var link = doc.createElement("link");
+               link.rel = alt ? "alternate stylesheet" : "stylesheet";
+               head.appendChild(link);
+               return link;
+       };
+
+       if (!style1 && params.f_base_style)
+               style1 = createLink(false);
+       if (params.f_base_style)
+               style1.href = params.f_base_style;
+       else if (style1)
+               head.removeChild(style1);
+
+       if (!style2 && params.f_alt_style)
+               style2 = createLink(true);
+       if (params.f_alt_style)
+               style2.href = params.f_alt_style;
+       else if (style2)
+               head.removeChild(style2);
+
+       for (var i in params) {
+               var val = params[i];
+               switch (i) {
+                   case "f_title":
+                       var title = doc.getElementsByTagName("title")[0];
+                       if (!title) {
+                               title = doc.createElement("title");
+                               head.appendChild(title);
+                       } else while (node = title.lastChild)
+                               title.removeChild(node);
+                       if (!HTMLArea.is_ie)
+                               title.appendChild(doc.createTextNode(val));
+                       else
+                               doc.title = val;
+                       break;
+                   case "f_doctype":
+                       this.editor.setDoctype(val);
+                       break;
+                   case "f_body_bgcolor":
+                       doc.body.style.backgroundColor = val;
+                       break;
+                   case "f_body_fgcolor":
+                       doc.body.style.color = val;
+                       break;
+               }
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/img/docprop.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/img/docprop.gif
new file mode 100644 (file)
index 0000000..2ceb082
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/img/docprop.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/img/makefile.xml b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/img/makefile.xml
new file mode 100644 (file)
index 0000000..19e075f
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<files>
+  <file name="*.{gif,jpg,jpeg}" />
+</files>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/lang/en.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/lang/en.js
new file mode 100644 (file)
index 0000000..50b6823
--- /dev/null
@@ -0,0 +1,25 @@
+// I18N for the FullPage plugin
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+FullPage.I18N = {
+       "Alternate style-sheet:":               "Alternate style-sheet:",
+       "Background color:":                    "Background color:",
+       "Cancel":                               "Cancel",
+       "DOCTYPE:":                             "DOCTYPE:",
+       "Document properties":                  "Document properties",
+       "Document title:":                      "Document title:",
+       "OK":                                   "OK",
+       "Primary style-sheet:":                 "Primary style-sheet:",
+       "Text color:":                          "Text color:"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/lang/makefile.xml b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/lang/makefile.xml
new file mode 100644 (file)
index 0000000..0d645c9
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<files>
+  <file name="*.js" />
+</files>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/lang/ro.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/lang/ro.js
new file mode 100644 (file)
index 0000000..f43c8e1
--- /dev/null
@@ -0,0 +1,25 @@
+// I18N for the FullPage plugin
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+FullPage.I18N = {
+       "Alternate style-sheet:":               "Template CSS alternativ:",
+       "Background color:":                    "Culoare de fundal:",
+       "Cancel":                               "Renunţă",
+       "DOCTYPE:":                             "DOCTYPE:",
+       "Document properties":                  "Proprietăţile documentului",
+       "Document title:":                      "Titlul documentului:",
+       "OK":                                   "Acceptă",
+       "Primary style-sheet:":                 "Template CSS principal:",
+       "Text color:":                          "Culoare text:"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/makefile.xml b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/makefile.xml
new file mode 100644 (file)
index 0000000..aa06dc6
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<files>
+  <file name="*.{js,html,cgi,css}" />
+
+  <dir name="lang" />
+  <dir name="img" />
+  <dir name="popups" />
+</files>
+
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/popups/docprop.html b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/popups/docprop.html
new file mode 100644 (file)
index 0000000..ee00e2d
--- /dev/null
@@ -0,0 +1,131 @@
+<html>
+
+<head>
+  <title>Document properties</title>
+
+<script type="text/javascript" src="../../../popups/popup.js"></script>
+
+<script type="text/javascript">
+
+FullPage = window.opener.FullPage; // load the FullPage plugin and lang file ;-)
+window.resizeTo(400, 100);
+
+  var accepted = {
+      f_doctype       : true,
+      f_title         : true,
+      f_body_bgcolor  : true,
+      f_body_fgcolor  : true,
+      f_base_style    : true,
+      f_alt_style     : true
+  };
+
+var editor = null;
+function Init() {
+  __dlg_translate(FullPage.I18N);
+  __dlg_init();
+  var params = window.dialogArguments;
+  for (var i in params) {
+      if (i in accepted) {
+        var el = document.getElementById(i);
+        el.value = params[i];
+      }
+  }
+  editor = params.editor;
+  document.getElementById("f_title").focus();
+  document.getElementById("f_title").select();
+};
+
+function onOK() {
+  var required = {
+  };
+  for (var i in required) {
+    var el = document.getElementById(i);
+    if (!el.value) {
+      alert(required[i]);
+      el.focus();
+      return false;
+    }
+  }
+
+  var param = {};
+  for (var i in accepted) {
+    var el = document.getElementById(i);
+    param[i] = el.value;
+  }
+  __dlg_close(param);
+  return false;
+};
+
+function onCancel() {
+  __dlg_close(null);
+  return false;
+};
+
+</script>
+
+<style type="text/css">
+html, body {
+  background: ButtonFace;
+  color: ButtonText;
+  font: 11px Tahoma,Verdana,sans-serif;
+  margin: 0px;
+  padding: 0px;
+}
+body { padding: 5px; }
+table {
+  font: 11px Tahoma,Verdana,sans-serif;
+}
+select, input, button { font: 11px Tahoma,Verdana,sans-serif; }
+button { width: 70px; }
+table .label { text-align: right; width: 12em; }
+
+.title { background: #ddf; color: #000; font-weight: bold; font-size: 120%; padding: 3px 10px; margin-bottom: 10px;
+border-bottom: 1px solid black; letter-spacing: 2px;
+}
+
+#buttons {
+      margin-top: 1em; border-top: 1px solid #999;
+      padding: 2px; text-align: right;
+}
+</style>
+
+  </head>
+
+  <body onload="Init()">
+
+    <div class="title"><span>Document properties</span></div>
+
+    <table style="width: 100%">
+      <tr>
+        <td class="label"><span>Document title:</span></td>
+        <td><input type="text" id="f_title" style="width: 100%" /></td>
+      </tr>
+      <tr>
+        <td class="label"><span>DOCTYPE:</span></td>
+        <td><input type="text" id="f_doctype" style="width: 100%" /></td>
+      </tr>
+      <tr>
+        <td class="label"><span>Primary style-sheet:</span></td>
+        <td><input type="text" id="f_base_style" style="width: 100%" /></td>
+      </tr>
+      <tr>
+        <td class="label"><span>Alternate style-sheet:</span></td>
+        <td><input type="text" id="f_alt_style" style="width: 100%" /></td>
+      </tr>
+      <tr>
+        <td class="label"><span>Background color:</span></td>
+        <td><input type="text" id="f_body_bgcolor" size="7" /></td>
+      </tr>
+      <tr>
+        <td class="label"><span>Text color:</span></td>
+        <td><input type="text" id="f_body_fgcolor" size="7" /></td>
+      </tr>
+    </table>
+
+    <div id="buttons">
+      <button type="button" name="ok" onclick="return onOK();"><span>OK</span></button>
+      <button type="button" name="cancel" onclick="return onCancel();"><span>Cancel</span></button>
+    </div>
+
+  </body>
+</html>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/popups/makefile.xml b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/popups/makefile.xml
new file mode 100644 (file)
index 0000000..37da667
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<files>
+  <file name="*.{js,html,cgi,css}" />
+</files>
+
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/test.html b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/FullPage/test.html
new file mode 100644 (file)
index 0000000..ad4be93
--- /dev/null
@@ -0,0 +1,89 @@
+<html>
+  <head>
+    <title>Test of FullPage plugin</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <script type="text/javascript">
+      _editor_url = "../../";
+    </script>
+
+    <!-- load the main HTMLArea files -->
+    <script type="text/javascript" src="../../htmlarea.js"></script>
+    <script type="text/javascript" src="../../lang/en.js"></script>
+    <script type="text/javascript" src="../../dialog.js"></script>
+
+    <!-- <script type="text/javascript" src="popupdiv.js"></script> -->
+    <script type="text/javascript" src="../../popupwin.js"></script>
+
+    <script type="text/javascript">
+      HTMLArea.loadPlugin("TableOperations");
+      HTMLArea.loadPlugin("SpellChecker");
+      HTMLArea.loadPlugin("FullPage");
+
+      function initDocument() {
+        var editor = new HTMLArea("editor");
+        editor.registerPlugin(TableOperations);
+        editor.registerPlugin(SpellChecker);
+        editor.registerPlugin(FullPage);
+        editor.generate();
+      }
+    </script>
+
+    <style type="text/css">
+      @import url(../../htmlarea.css);
+    </style>
+
+  </head>
+
+  <body onload="initDocument()">
+    <h1>Test of FullPage plugin</h1>
+
+    <textarea id="editor" style="height: 30em; width: 100%;">
+      &lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"&gt;
+      &lt;html&gt;
+        &lt;head&gt;
+          &lt;title&gt;FullPage plugin for HTMLArea&lt;/title&gt;
+          &lt;link rel="alternate stylesheet" href="http://dynarch.com/mishoo/css/dark.css" /&gt;
+          &lt;link rel="stylesheet" href="http://dynarch.com/mishoo/css/cool-light.css" /&gt;
+        &lt;/head&gt;
+        &lt;body style="background-color: #ddddee; color: #000077;"&gt;
+          &lt;table style="width:60%; height: 90%; margin: 2% auto 1% auto;" align="center" border="0" cellpadding="0" cellspacing="0"&gt;
+            &lt;tr&gt;
+              &lt;td style="background-color: #ddeedd; border: 2px solid #002; height: 1.5em; padding: 2px; font: bold 24px Verdana;"&gt;
+                FullPage plugin
+              &lt;/td&gt;
+            &lt;/tr&gt;
+            &lt;tr&gt;
+              &lt;td style="background-color: #fff; border: 1px solid #aab; padding: 1em 3em; font: 12px Verdana;"&gt;
+                &lt;p&gt;
+                  This plugin enables one to edit a full HTML file in &lt;a
+                    href="http://dynarch.com/htmlarea/"&gt;HTMLArea&lt;/a&gt;.  This is not
+                  normally possible with just the core editor since it only
+                  retrieves the HTML inside the &lt;code&gt;body&lt;/code&gt; tag.
+                &lt;/p&gt;
+                &lt;p&gt;
+                  It provides the ability to change the &lt;code&gt;DOCTYPE&lt;/code&gt; of
+                  the document, &lt;code&gt;body&lt;/code&gt; &lt;code&gt;bgcolor&lt;/code&gt; and
+                  &lt;code&gt;fgcolor&lt;/code&gt; attributes as well as to add additional
+                  &lt;code&gt;link&lt;/code&gt;-ed stylesheets.  Cool, eh?
+                &lt;/p&gt;
+                &lt;p&gt;
+                  The development of this plugin was initiated and sponsored by
+                  &lt;a href="http://thycotic.com"&gt;Thycotic Software Ltd.&lt;/a&gt;.
+                  That's also cool, isn't it? ;-)
+                &lt;/p&gt;
+              &lt;/td&gt;
+            &lt;/tr&gt;
+          &lt;/table&gt;
+        &lt;/body&gt;
+      &lt;/html&gt;
+    </textarea>
+
+    <hr />
+    <address><a href="http://dynarch.com/mishoo/">Mihai Bazon</a></address>
+<!-- Created: Wed Oct  1 19:55:37 EEST 2003 -->
+<!-- hhmts start -->
+Last modified on Sat Oct 25 01:06:59 2003
+<!-- hhmts end -->
+<!-- doc-lang: English -->
+  </body>
+</html>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/img/makefile.xml b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/img/makefile.xml
new file mode 100644 (file)
index 0000000..19e075f
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<files>
+  <file name="*.{gif,jpg,jpeg}" />
+</files>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/img/spell-check.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/img/spell-check.gif
new file mode 100644 (file)
index 0000000..29bd11a
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/img/spell-check.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/cz.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/cz.js
new file mode 100644 (file)
index 0000000..108c037
--- /dev/null
@@ -0,0 +1,37 @@
+// I18N constants
+
+// LANG: "cz", ENCODING: UTF-8 | ISO-8859-2
+// Author: Jiri Löw, <jirilow@jirilow.com>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+SpellChecker.I18N = {
+       "CONFIRM_LINK_CLICK"                    : "Prosím potvrďte otevření tohoto odkazu",
+       "Cancel"                                : "Zrušit",
+       "Dictionary"                            : "Slovník",
+       "Finished list of mispelled words"      : "Dokončen seznam chybných slov",
+       "I will open it in a new page."         : "Bude otevřen jej v nové stránce.",
+       "Ignore all"                            : "Ignorovat vše",
+       "Ignore"                                : "Ignorovat",
+       "NO_ERRORS"                             : "Podle zvoleného slovníku nebyla nalezena žádná chybná slova.",
+       "NO_ERRORS_CLOSING"                     : "Kontrola správnosti slov dokončena, nebyla nalezena žádná chybná slova. Ukončování ...",
+       "OK"                                    : "OK",
+       "Original word"                         : "Původní slovo",
+       "Please wait.  Calling spell checker."  : "Prosím čekejte. Komunikuace s kontrolou správnosti slov.",
+       "Please wait: changing dictionary to"   : "Prosím čekejte: změna adresáře na",
+       "QUIT_CONFIRMATION"                     : "Změny budou zrušeny a kontrola správnosti slov ukončena. Prosím potvrďte.",
+       "Re-check"                              : "Překontrolovat",
+       "Replace all"                           : "Zaměnit všechno",
+       "Replace with"                          : "Zaměnit za",
+       "Replace"                               : "Zaměnit",
+       "SC-spell-check"                        : "Kontrola správnosti slov",
+       "Suggestions"                           : "Doporučení",
+       "pliz weit ;-)"                         : "strpení prosím ;-)"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/da.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/da.js
new file mode 100644 (file)
index 0000000..690293e
--- /dev/null
@@ -0,0 +1,37 @@
+// I18N constants
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Steen Sønderup, <steen@soenderup.com>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+SpellChecker.I18N = {
+       "CONFIRM_LINK_CLICK"                    : "Vil du følge dette link?",
+       "Cancel"                                : "Anuler",
+       "Dictionary"                            : "Ordbog",
+       "Finished list of mispelled words"      : "Listen med stavefejl er gennemgået",
+       "I will open it in a new page."         : "Jeg vil åbne det i en ny side.",
+       "Ignore all"                            : "Ignorer alle",
+       "Ignore"                                : "Ignorer",
+       "NO_ERRORS"                             : "Der blev ikke fundet nogle stavefejl med den valgte ordbog.",
+       "NO_ERRORS_CLOSING"                     : "Stavekontrollen er gennemført, der blev ikke fundet nogle stavefejl.  Lukker...",
+       "OK"                                    : "OK",
+       "Original word"                         : "Oprindeligt ord",
+       "Please wait.  Calling spell checker."  : "Vent venligst.  Henter stavekontrol.",
+       "Please wait: changing dictionary to"   : "Vent venligst: skifter ordbog til",
+       "QUIT_CONFIRMATION"                     : "Alle dine ændringer vil gå tabt, vil du fortsætte?",
+       "Re-check"                              : "Tjek igen",
+       "Replace all"                           : "Erstat alle",
+       "Replace with"                          : "Erstat med",
+       "Replace"                               : "Erstat",
+       "SC-spell-check"                        : "Stavekontrol",
+       "Suggestions"                           : "Forslag",
+       "pliz weit ;-)"                         : "Vent venligst"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/de.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/de.js
new file mode 100644 (file)
index 0000000..1a8f4b5
--- /dev/null
@@ -0,0 +1,28 @@
+// I18N constants
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Broxx, <broxx@broxx.com>
+
+SpellChecker.I18N = {
+       "CONFIRM_LINK_CLICK"                    : "Wollen Sie diesen Link oeffnen",
+       "Cancel"                                : "Abbrechen",
+       "Dictionary"                            : "Woerterbuch",
+       "Finished list of mispelled words"      : "Liste der nicht bekannten Woerter",
+       "I will open it in a new page."         : "Wird auf neuer Seite geoeffnet",
+       "Ignore all"                            : "Alle ignorieren",
+       "Ignore"                                : "Ignorieren",
+       "NO_ERRORS"                             : "Keine falschen Woerter mit gewaehlten Woerterbuch gefunden",
+       "NO_ERRORS_CLOSING"                     : "Rechtsschreibpruefung wurde ohne Fehler fertiggestellt.  Wird nun geschlossen...",
+       "OK"                                    : "OK",
+       "Original word"                         : "Original Wort",
+       "Please wait.  Calling spell checker."  : "Bitte warten.  Woerterbuch wird durchsucht.",
+       "Please wait: changing dictionary to"   : "Bitte warten: Woerterbuch wechseln zu",
+       "QUIT_CONFIRMATION"                     : "Aenderungen werden nicht uebernommen.  Bitte bestaettigen.",
+       "Re-check"                              : "Neuueberpruefung",
+       "Replace all"                           : "Alle ersetzen",
+       "Replace with"                          : "Ersetzen mit",
+       "Replace"                               : "Ersetzen",
+       "SC-spell-check"                        : "Ueberpruefung",
+       "Suggestions"                           : "Vorschlag",
+       "pliz weit ;-)"                         : "bittsche wartn ;-)"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/en.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/en.js
new file mode 100644 (file)
index 0000000..529cc6c
--- /dev/null
@@ -0,0 +1,38 @@
+// I18N constants
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+SpellChecker.I18N = {
+       "CONFIRM_LINK_CLICK"                    : "Please confirm that you want to open this link",
+       "Cancel"                                : "Cancel",
+       "Dictionary"                            : "Dictionary",
+       "Finished list of mispelled words"      : "Finished list of mispelled words",
+       "I will open it in a new page."         : "I will open it in a new page.",
+       "Ignore all"                            : "Ignore all",
+       "Ignore"                                : "Ignore",
+       "NO_ERRORS"                             : "No mispelled words found with the selected dictionary.",
+       "NO_ERRORS_CLOSING"                     : "Spell check complete, didn't find any mispelled words.  Closing now...",
+       "OK"                                    : "OK",
+       "Original word"                         : "Original word",
+       "Please wait.  Calling spell checker."  : "Please wait.  Calling spell checker.",
+       "Please wait: changing dictionary to"   : "Please wait: changing dictionary to",
+       "QUIT_CONFIRMATION"                     : "This will drop changes and quit spell checker.  Please confirm.",
+       "Re-check"                              : "Re-check",
+       "Replace all"                           : "Replace all",
+       "Replace with"                          : "Replace with",
+       "Replace"                               : "Replace",
+       "Revert"                                : "Revert",
+       "SC-spell-check"                        : "Spell-check",
+       "Suggestions"                           : "Suggestions",
+       "pliz weit ;-)"                         : "pliz weit ;-)"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/hu.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/hu.js
new file mode 100644 (file)
index 0000000..64102c5
--- /dev/null
@@ -0,0 +1,37 @@
+// I18N constants
+
+// LANG: "hu", ENCODING: UTF-8
+// Author: Miklós Somogyi, <somogyine@vnet.hu>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+SpellChecker.I18N = {
+       "CONFIRM_LINK_CLICK"                    : "Megerősítés",
+       "Cancel"                                : "Mégsem",
+       "Dictionary"                            : "Szótár",
+       "Finished list of mispelled words"      : "A tévesztett szavak listájának vége",
+       "I will open it in a new page."         : "Megnyitás új lapon",
+       "Ignore all"                            : "Minden elvetése",
+       "Ignore"                                : "Elvetés",
+       "NO_ERRORS"                             : "A választott szótár szerint nincs tévesztett szó.",
+       "NO_ERRORS_CLOSING"                     : "A helyesírásellenőrzés kész, tévesztett szó nem fordult elő. Bezárás...",
+       "OK"                                    : "Rendben",
+       "Original word"                         : "Eredeti szó",
+       "Please wait.  Calling spell checker."  : "Kis türelmet, a helyesírásellenőrző hívása folyamatban.",
+       "Please wait: changing dictionary to"   : "Kis türelmet, szótár cseréje",
+       "QUIT_CONFIRMATION"                     : "Kilépés a változások eldobásával. Jóváhagyja?",
+       "Re-check"                              : "Újraellenőrzés",
+       "Replace all"                           : "Mind cseréje",
+       "Replace with"                          : "Csere a következőre:",
+       "Replace"                               : "Csere",
+       "SC-spell-check"                        : "Helyesírásellenőrzés",
+       "Suggestions"                           : "Tippek",
+       "pliz weit ;-)"                         : "Kis türelmet ;-)"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/it.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/it.js
new file mode 100644 (file)
index 0000000..0af5f77
--- /dev/null
@@ -0,0 +1,28 @@
+// I18N constants
+
+// LANG: "it", ENCODING: UTF-8 | ISO-8859-1
+// Author: Fabio Rotondo, <fabio@rotondo.it>
+
+SpellChecker.I18N = {
+       "CONFIRM_LINK_CLICK"                    : "Devi confermare l'apertura di questo link",
+       "Cancel"                                : "Annulla",
+       "Dictionary"                            : "Dizionario",
+       "Finished list of mispelled words"      : "La lista delle parole scritte male è terminata",
+       "I will open it in a new page."         : "Lo aprirò in una nuova pagina.",
+       "Ignore all"                            : "Ignora sempre",
+       "Ignore"                                : "Ignora",
+       "NO_ERRORS"                             : "Non sono state trovate parole scritte male con il dizionario selezionato.",
+       "NO_ERRORS_CLOSING"                     : "Controllo completato, non sono state trovate parole scritte male. Sto chiudendo...",
+       "OK"                                    : "OK",
+       "Original word"                         : "Parola originale",
+       "Please wait.  Calling spell checker."  : "Attendere.  Sto invocando lo Spell Checker.",
+       "Please wait: changing dictionary to"   : "Attendere. Cambio il dizionario in",
+       "QUIT_CONFIRMATION"                     : "Questo annullerà le modifiche e chiuderà lo Spell Checker. Conferma.",
+       "Re-check"                              : "Ricontrolla",
+       "Replace all"                           : "Sostituisci sempre",
+       "Replace with"                          : "Stostituisci con",
+       "Replace"                               : "Sostituisci",
+       "SC-spell-check"                        : "Spell-check",
+       "Suggestions"                           : "Suggerimenti",
+       "pliz weit ;-)"                         : "Attendere Prego ;-)"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/makefile.xml b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/makefile.xml
new file mode 100644 (file)
index 0000000..0d645c9
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<files>
+  <file name="*.js" />
+</files>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/ro.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/lang/ro.js
new file mode 100644 (file)
index 0000000..d8e96b9
--- /dev/null
@@ -0,0 +1,37 @@
+// I18N constants
+
+// LANG: "ro", ENCODING: UTF-8
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+SpellChecker.I18N = {
+       "CONFIRM_LINK_CLICK"                    : "Vă rog confirmaţi că vreţi să deschideţi acest link",
+       "Cancel"                                : "Anulează",
+       "Dictionary"                            : "Dicţionar",
+       "Finished list of mispelled words"      : "Am terminat lista de cuvinte greşite",
+       "I will open it in a new page."         : "O voi deschide într-o altă fereastră.",
+       "Ignore all"                            : "Ignoră toate",
+       "Ignore"                                : "Ignoră",
+       "NO_ERRORS"                             : "Nu am găsit nici un cuvânt greşit cu acest dicţionar.",
+       "NO_ERRORS_CLOSING"                     : "Am terminat, nu am detectat nici o greşeală.  Acum închid fereastra...",
+       "OK"                                    : "OK",
+       "Original word"                         : "Cuvântul original",
+       "Please wait.  Calling spell checker."  : "Vă rog aşteptaţi.  Apelez spell-checker-ul.",
+       "Please wait: changing dictionary to"   : "Vă rog aşteptaţi.  Schimb dicţionarul cu",
+       "QUIT_CONFIRMATION"                     : "Doriţi să renunţaţi la modificări şi să închid spell-checker-ul?",
+       "Re-check"                              : "Scanează",
+       "Replace all"                           : "Înlocuieşte toate",
+       "Replace with"                          : "Înlocuieşte cu",
+       "Replace"                               : "Înlocuieşte",
+       "SC-spell-check"                        : "Detectează greşeli",
+       "Suggestions"                           : "Sugestii",
+       "pliz weit ;-)"                         : "va rog ashteptatzi ;-)"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/makefile.xml b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/makefile.xml
new file mode 100644 (file)
index 0000000..cf040f5
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<files>
+  <file name="*.{js,html,cgi,css}" />
+
+  <dir name="lang" />
+  <dir name="img" />
+</files>
+
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/readme-tech.html b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/readme-tech.html
new file mode 100644 (file)
index 0000000..1afdf6d
--- /dev/null
@@ -0,0 +1,114 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN">
+<html>
+  <head>
+    <title>HTMLArea Spell Checker</title>
+  </head>
+
+  <body>
+    <h1>HTMLArea Spell Checker</h1>
+
+    <p>The HTMLArea Spell Checker subsystem consists of the following
+      files:</p>
+
+    <ul>
+
+      <li>spell-checker.js &mdash; the spell checker plugin interface for
+        HTMLArea</li>
+
+      <li>spell-checker-ui.html &mdash; the HTML code for the user
+        interface</li>
+
+      <li>spell-checker-ui.js &mdash; functionality of the user
+        interface</li>
+
+      <li>spell-checker-logic.cgi &mdash; Perl CGI script that checks a text
+        given through POST for spelling errors</li>
+
+      <li>spell-checker-style.css &mdash; style for mispelled words</li>
+
+      <li>lang/en.js &mdash; main language file (English).</li>
+
+    </ul>
+
+    <h2>Process overview</h2>
+
+    <p>
+      When an end-user clicks the "spell-check" button in the HTMLArea
+      editor, a new window is opened with the URL of "spell-check-ui.html".
+      This window initializes itself with the text found in the editor (uses
+      <tt>window.opener.SpellChecker.editor</tt> global variable) and it
+      submits the text to the server-side script "spell-check-logic.cgi".
+      The target of the FORM is an inline frame which is used both to
+      display the text and correcting.
+    </p>
+
+    <p>
+      Further, spell-check-logic.cgi calls Aspell for each portion of plain
+      text found in the given HTML.  It rebuilds an HTML file that contains
+      clear marks of which words are incorrect, along with suggestions for
+      each of them.  This file is then loaded in the inline frame.  Upon
+      loading, a JavaScript function from "spell-check-ui.js" is called.
+      This function will retrieve all mispelled words from the HTML of the
+      iframe and will setup the user interface so that it allows correction.
+    </p>
+
+    <h2>The server-side script (spell-check-logic.cgi)</h2>
+
+    <p>
+      <strong>Unicode safety</strong> &mdash; the program <em>is</em>
+      Unicode safe.  HTML entities are expanded into their corresponding
+      Unicode characters.  These characters will be matched as part of the
+      word passed to Aspell.  All texts passed to Aspell are in Unicode
+      (when appropriate).  <strike>However, Aspell seems to not support Unicode
+      yet (<a
+        href="http://mail.gnu.org/archive/html/aspell-user/2000-11/msg00007.html">thread concerning Aspell and Unicode</a>).
+      This mean that words containing Unicode
+      characters that are not in 0..255 are likely to be reported as "mispelled" by Aspell.</strike>
+    </p>
+
+    <p>
+      <strong style="font-variant: small-caps; color:
+      red;">Update:</strong> though I've never seen it mentioned
+      anywhere, it looks that Aspell <em>does</em>, in fact, speak
+      Unicode.  Or else, maybe <code>Text::Aspell</code> does
+      transparent conversion; anyway, this new version of our
+      SpellChecker plugin is, as tests show so far, fully
+      Unicode-safe... well, probably the <em>only</em> freeware
+      Web-based spell-checker which happens to have Unicode support.
+    </p>
+
+    <p>
+      The Perl Unicode manual (man perluniintro) states:
+    </p>
+
+    <blockquote>
+      <em>
+        Starting from Perl 5.6.0, Perl has had the capacity to handle Unicode
+        natively.  Perl 5.8.0, however, is the first recommended release for
+        serious Unicode work.  The maintenance release 5.6.1 fixed many of the
+        problems of the initial Unicode implementation, but for example regular
+        expressions still do not work with Unicode in 5.6.1.
+      </em>
+    </blockquote>
+
+    <p>In other words, do <em>not</em> assume that this script is
+      Unicode-safe on Perl interpreters older than 5.8.0.</p>
+
+    <p>The following Perl modules are required:</p>
+
+    <ul>
+      <li><a href="http://search.cpan.org/search?query=Text%3A%3AAspell&mode=all" target="_blank">Text::Aspell</a></li>
+      <li><a href="http://search.cpan.org/search?query=XML%3A%3ADOM&mode=all" target="_blank">XML::DOM</a></li>
+      <li><a href="http://search.cpan.org/search?query=CGI&mode=all" target="_blank">CGI</a></li>
+    </ul>
+
+    <p>Of these, only Text::Aspell might need to be installed manually.  The
+      others are likely to be available by default in most Perl distributions.</p>
+
+    <hr />
+    <address><a href="http://dynarch.com/mishoo/">Mihai Bazon</a></address>
+<!-- Created: Thu Jul 17 13:22:27 EEST 2003 -->
+<!-- hhmts start --> Last modified: Fri Jan 30 19:14:11 EET 2004 <!-- hhmts end -->
+<!-- doc-lang: English -->
+  </body>
+</html>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/spell-check-logic.cgi b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/spell-check-logic.cgi
new file mode 100644 (file)
index 0000000..4a1256b
--- /dev/null
@@ -0,0 +1,210 @@
+#! /usr/bin/perl -w
+
+# Spell Checker Plugin for HTMLArea-3.0
+# Sponsored by www.americanbible.org
+# Implementation by Mihai Bazon, http://dynarch.com/mishoo/
+#
+# (c) dynarch.com 2003.
+# Distributed under the same terms as HTMLArea itself.
+# This notice MUST stay intact for use (see license.txt).
+#
+# $Id: spell-check-logic.cgi,v 1.10 2004/01/31 13:47:05 mishoo Exp $
+
+use strict;
+use utf8;
+use Encode;
+use Text::Aspell;
+use XML::DOM;
+use CGI;
+
+my $TIMER_start = undef;
+eval {
+    use Time::HiRes qw( gettimeofday tv_interval );
+    $TIMER_start = [gettimeofday()];
+};
+# use POSIX qw( locale_h );
+
+binmode STDIN, ':utf8';
+binmode STDOUT, ':utf8';
+
+my $debug = 0;
+
+my $speller = new Text::Aspell;
+my $cgi = new CGI;
+
+my $total_words = 0;
+my $total_mispelled = 0;
+my $total_suggestions = 0;
+my $total_words_suggested = 0;
+
+# FIXME: report a nice error...
+die "Can't create speller!" unless $speller;
+
+my $dict = $cgi->param('dictionary') || $cgi->cookie('dictionary') || 'en';
+
+# add configurable option for this
+$speller->set_option('lang', $dict);
+$speller->set_option('encoding', 'UTF-8');
+#setlocale(LC_CTYPE, $dict);
+
+# ultra, fast, normal, bad-spellers
+# bad-spellers seems to cause segmentation fault
+$speller->set_option('sug-mode', 'normal');
+
+my %suggested_words = ();
+keys %suggested_words = 128;
+
+my $file_content = decode('UTF-8', $cgi->param('content'));
+$file_content = parse_with_dom($file_content);
+
+my $ck_dictionary = $cgi->cookie(-name     => 'dictionary',
+                                 -value    => $dict,
+                                 -expires  => '+30d');
+
+print $cgi->header(-type    => 'text/html; charset: utf-8',
+                   -cookie  => $ck_dictionary);
+
+my $js_suggested_words = make_js_hash(\%suggested_words);
+my $js_spellcheck_info = make_js_hash_from_array
+  ([
+    [ 'Total words'           , $total_words ],
+    [ 'Mispelled words'       , $total_mispelled . ' in dictionary \"'.$dict.'\"' ],
+    [ 'Total suggestions'     , $total_suggestions ],
+    [ 'Total words suggested' , $total_words_suggested ],
+    [ 'Spell-checked in'      , defined $TIMER_start ? (tv_interval($TIMER_start) . ' seconds') : 'n/a' ]
+   ]);
+
+print qq^<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<link rel="stylesheet" type="text/css" media="all" href="spell-check-style.css" />
+<script type="text/javascript">
+  var suggested_words = { $js_suggested_words };
+  var spellcheck_info = { $js_spellcheck_info }; </script>
+</head>
+<body onload="window.parent.finishedSpellChecking();">^;
+
+print $file_content;
+if ($cgi->param('init') eq '1') {
+    my @dicts = $speller->dictionary_info();
+    my $dictionaries = '';
+    foreach my $i (@dicts) {
+        next if $i->{jargon};
+        my $name = $i->{name};
+        if ($name eq $dict) {
+            $name = '@'.$name;
+        }
+        $dictionaries .= ',' . $name;
+    }
+    $dictionaries =~ s/^,//;
+    print qq^<div id="HA-spellcheck-dictionaries">$dictionaries</div>^;
+}
+
+print '</body></html>';
+
+# Perl is beautiful.
+sub spellcheck {
+    my $node = shift;
+    my $doc = $node->getOwnerDocument;
+    my $check = sub {                 # called for each word in the text
+        # input is in UTF-8
+        my $word = shift;
+        my $already_suggested = defined $suggested_words{$word};
+        ++$total_words;
+        if (!$already_suggested && $speller->check($word)) {
+            return undef;
+        } else {
+            # we should have suggestions; give them back to browser in UTF-8
+            ++$total_mispelled;
+            if (!$already_suggested) {
+                # compute suggestions for this word
+                my @suggestions = $speller->suggest($word);
+                my $suggestions = decode($speller->get_option('encoding'), join(',', @suggestions));
+                $suggested_words{$word} = $suggestions;
+                ++$total_suggestions;
+                $total_words_suggested += scalar @suggestions;
+            }
+            # HA-spellcheck-error
+            my $err = $doc->createElement('span');
+            $err->setAttribute('class', 'HA-spellcheck-error');
+            my $tmp = $doc->createTextNode;
+            $tmp->setNodeValue($word);
+            $err->appendChild($tmp);
+            return $err;
+        }
+    };
+    while ($node->getNodeValue =~ /([\p{IsWord}']+)/) {
+        my $word = $1;
+        my $before = $`;
+        my $after = $';
+        my $df = &$check($word);
+        if (!$df) {
+            $before .= $word;
+        }
+        {
+            my $parent = $node->getParentNode;
+            my $n1 = $doc->createTextNode;
+            $n1->setNodeValue($before);
+            $parent->insertBefore($n1, $node);
+            $parent->insertBefore($df, $node) if $df;
+            $node->setNodeValue($after);
+        }
+    }
+};
+
+sub check_inner_text {
+    my $node = shift;
+    my $text = '';
+    for (my $i = $node->getFirstChild; defined $i; $i = $i->getNextSibling) {
+        if ($i->getNodeType == TEXT_NODE) {
+            spellcheck($i);
+        }
+    }
+};
+
+sub parse_with_dom {
+    my ($text) = @_;
+    $text = '<spellchecker>'.$text.'</spellchecker>';
+
+    my $parser = new XML::DOM::Parser;
+    if ($debug) {
+        open(FOO, '>:utf8', '/tmp/foo');
+        print FOO $text;
+        close FOO;
+    }
+    my $doc = $parser->parse($text);
+    my $nodes = $doc->getElementsByTagName('*');
+    my $n = $nodes->getLength;
+
+    for (my $i = 0; $i < $n; ++$i) {
+        my $node = $nodes->item($i);
+        if ($node->getNodeType == ELEMENT_NODE) {
+            check_inner_text($node);
+        }
+    }
+
+    my $ret = $doc->toString;
+    $ret =~ s{<spellchecker>(.*)</spellchecker>}{$1}sg;
+    return $ret;
+};
+
+sub make_js_hash {
+    my ($hash) = @_;
+    my $js_hash = '';
+    while (my ($key, $val) = each %$hash) {
+        $js_hash .= ',' if $js_hash;
+        $js_hash .= '"'.$key.'":"'.$val.'"';
+    }
+    return $js_hash;
+};
+
+sub make_js_hash_from_array {
+    my ($array) = @_;
+    my $js_hash = '';
+    foreach my $i (@$array) {
+        $js_hash .= ',' if $js_hash;
+        $js_hash .= '"'.$i->[0].'":"'.$i->[1].'"';
+    }
+    return $js_hash;
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/spell-check-style.css b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/spell-check-style.css
new file mode 100644 (file)
index 0000000..1408ba0
--- /dev/null
@@ -0,0 +1,10 @@
+.HA-spellcheck-error { border-bottom: 1px dashed #f00; cursor: default; }
+.HA-spellcheck-same { background-color: #cef; color: #000; }
+.HA-spellcheck-hover { background-color: #433; color: white; }
+.HA-spellcheck-fixed { border-bottom: 1px dashed #0b8; }
+.HA-spellcheck-current { background-color: #9be; color: #000; }
+.HA-spellcheck-suggestions { display: none; }
+
+#HA-spellcheck-dictionaries { display: none; }
+
+a:link, a:visited { color: #55e; }
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/spell-check-ui.html b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/spell-check-ui.html
new file mode 100644 (file)
index 0000000..a008bf4
--- /dev/null
@@ -0,0 +1,122 @@
+<!--
+
+  Strangely, IE sucks with or without the DOCTYPE switch.
+  I thought it would only suck without it.
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+
+   Spell Checker Plugin for HTMLArea-3.0
+   Sponsored by www.americanbible.org
+   Implementation by Mihai Bazon, http://dynarch.com/mishoo/
+  
+   (c) dynarch.com 2003.
+   Distributed under the same terms as HTMLArea itself.
+   This notice MUST stay intact for use (see license.txt).
+
+   $Id: spell-check-ui.html,v 1.2 2004/05/03 15:30:38 bruno Exp $
+
+-->
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+  <head>
+    <title>Spell Checker</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <script type="text/javascript" src="spell-check-ui.js"></script>
+
+    <style type="text/css">
+      html, body { height: 100%; margin: 0px; padding: 0px; background-color: #fff;
+      color: #000; }
+      a:link, a:visited { color: #00f; text-decoration: none; }
+      a:hover { color: #f00; text-decoration: underline; }
+
+      table { background-color: ButtonFace; color: ButtonText;
+      font-family: tahoma,verdana,sans-serif; font-size: 11px; }
+
+      iframe { background-color: #fff; color: #000; height: 100%; width: 100%; }
+
+      .controls { width: 13em; }
+      .controls .sectitle { /* background-color: #736c6c; color: #fff;
+      border-top: 1px solid #000; border-bottom: 1px solid #fff; */
+      text-align: center;
+      font-weight: bold; padding: 2px 4px; }
+      .controls .secbody { margin-bottom: 10px; }
+
+      button, select { font-family: tahoma,verdana,sans-serif; font-size: 11px; }
+      button { width: 6em; padding: 0px; }
+
+      input, select { font-family: fixed,"andale mono",monospace; }
+
+      #v_currentWord { color: #f00; font-weight: bold; }
+      #statusbar { padding: 7px 0px 0px 5px; }
+      #status { font-weight: bold; }
+    </style>
+
+  </head>
+
+  <body onload="initDocument()">
+
+    <form style="display: none;" action="spell-check-logic.cgi"
+          method="post" target="framecontent"
+          accept-charset="UTF-8"
+          ><input type="hidden" name="content" id="f_content"
+          /><input type="hidden" name="dictionary" id="f_dictionary"
+          /><input type="hidden" name="init" id="f_init" value="1"
+    /></form>
+
+    <table style="height: 100%; width: 100%; border-collapse: collapse;" cellspacing="0" cellpadding="0">
+      <tr>
+        <td colspan="2" style="height: 1em; padding: 2px;">
+          <div style="float: right; padding: 2px;"><span>Dictionary</span>
+            <select id="v_dictionaries" style="width: 10em"></select>
+            <button id="b_recheck">Re-check</button>
+          </div>
+          <span id="status">Please wait.  Calling spell checker.</span>
+        </td>
+      </tr>
+      <tr>
+        <td valign="top" class="controls">
+          <div class="secbody" style="text-align: center">
+            <button id="b_info">Info</button>
+          </div>
+          <div class="sectitle">Original word</div>
+          <div class="secbody" id="v_currentWord" style="text-align:
+          center; margin-bottom: 0px;">pliz weit ;-)</div>
+          <div class="secbody" style="text-align: center">
+            <button id="b_revert">Revert</button>
+          </div>
+          <div class="sectitle">Replace with</div>
+          <div class="secbody">
+            <input type="text" id="v_replacement" style="width: 94%; margin-left: 3%;" /><br />
+            <div style="text-align: center; margin-top: 2px;">
+              <button id="b_replace">Replace</button><button
+                id="b_replall">Replace all</button><br /><button
+                id="b_ignore">Ignore</button><button
+                id="b_ignall">Ignore all</button>
+            </div>
+          </div>
+          <div class="sectitle">Suggestions</div>
+          <div class="secbody">
+            <select size="11" style="width: 94%; margin-left: 3%;" id="v_suggestions"></select>
+          </div>
+        </td>
+
+        <td>
+          <iframe src="about:blank" width="100%" height="100%"
+            id="i_framecontent" name="framecontent"></iframe>
+        </td>
+      </tr>
+      <tr>
+        <td style="height: 1em;" colspan="2">
+          <div style="padding: 4px 2px 2px 2px; float: right;">
+            <button id="b_ok">OK</button>
+            <button id="b_cancel">Cancel</button>
+          </div>
+          <div id="statusbar"></div>
+        </td>
+      </tr>
+    </table>
+
+  </body>
+
+</html>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/spell-check-ui.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/spell-check-ui.js
new file mode 100644 (file)
index 0000000..7bea11f
--- /dev/null
@@ -0,0 +1,397 @@
+// Spell Checker Plugin for HTMLArea-3.0
+// Sponsored by www.americanbible.org
+// Implementation by Mihai Bazon, http://dynarch.com/mishoo/
+//
+// (c) dynarch.com 2003.
+// Distributed under the same terms as HTMLArea itself.
+// This notice MUST stay intact for use (see license.txt).
+//
+// $Id: spell-check-ui.js 30938 2004-07-29 19:08:16Z vgritsenko $
+
+// internationalization file was already loaded in parent ;-)
+var SpellChecker = window.opener.SpellChecker;
+var i18n = SpellChecker.I18N;
+
+var HTMLArea = window.opener.HTMLArea;
+var is_ie = HTMLArea.is_ie;
+var editor = SpellChecker.editor;
+var frame = null;
+var currentElement = null;
+var wrongWords = null;
+var modified = false;
+var allWords = {};
+var fixedWords = [];
+var suggested_words = {};
+
+function makeCleanDoc(leaveFixed) {
+       // document.getElementById("status").innerHTML = 'Please wait: rendering valid HTML';
+       var words = wrongWords.concat(fixedWords);
+       for (var i = words.length; --i >= 0;) {
+               var el = words[i];
+               if (!(leaveFixed && /HA-spellcheck-fixed/.test(el.className))) {
+                       el.parentNode.insertBefore(el.firstChild, el);
+                       el.parentNode.removeChild(el);
+               } else
+                       el.className = "HA-spellcheck-fixed";
+       }
+       // we should use innerHTML here, but IE6's implementation fucks up the
+       // HTML to such extent that our poor Perl parser doesn't understand it
+       // anymore.
+       return window.opener.HTMLArea.getHTML(frame.contentWindow.document.body, false, editor);
+};
+
+function recheckClicked() {
+       document.getElementById("status").innerHTML = i18n["Please wait: changing dictionary to"] + ': "' + document.getElementById("f_dictionary").value + '".';
+       var field = document.getElementById("f_content");
+       field.value = makeCleanDoc(true);
+       field.form.submit();
+};
+
+function saveClicked() {
+       if (modified) {
+               editor.setHTML(makeCleanDoc(false));
+       }
+       window.close();
+       return false;
+};
+
+function cancelClicked() {
+       var ok = true;
+       if (modified) {
+               ok = confirm(i18n["QUIT_CONFIRMATION"]);
+       }
+       if (ok) {
+               window.close();
+       }
+       return false;
+};
+
+function replaceWord(el) {
+       var replacement = document.getElementById("v_replacement").value;
+       var this_word_modified = (el.innerHTML != replacement);
+       if (this_word_modified)
+               modified = true;
+       if (el) {
+               el.className = el.className.replace(/\s*HA-spellcheck-(hover|fixed)\s*/g, " ");
+       }
+       el.className += " HA-spellcheck-fixed";
+       el.__msh_fixed = true;
+       if (!this_word_modified) {
+               return false;
+       }
+       el.innerHTML = replacement;
+};
+
+function replaceClicked() {
+       replaceWord(currentElement);
+       var start = currentElement.__msh_id;
+       var index = start;
+       do {
+               ++index;
+               if (index == wrongWords.length) {
+                       index = 0;
+               }
+       } while ((index != start) && wrongWords[index].__msh_fixed);
+       if (index == start) {
+               index = 0;
+               alert(i18n["Finished list of mispelled words"]);
+       }
+       wrongWords[index].__msh_wordClicked(true);
+       return false;
+};
+
+function revertClicked() {
+       document.getElementById("v_replacement").value = currentElement.__msh_origWord;
+       replaceWord(currentElement);
+       currentElement.className = "HA-spellcheck-error HA-spellcheck-current";
+       return false;
+};
+
+function replaceAllClicked() {
+       var replacement = document.getElementById("v_replacement").value;
+       var ok = true;
+       var spans = allWords[currentElement.__msh_origWord];
+       if (spans.length == 0) {
+               alert("An impossible condition just happened.  Call FBI.  ;-)");
+       } else if (spans.length == 1) {
+               replaceClicked();
+               return false;
+       }
+       /*
+       var message = "The word \"" + currentElement.__msh_origWord + "\" occurs " + spans.length + " times.\n";
+       if (replacement == currentElement.__msh_origWord) {
+               ok = confirm(message + "Ignore all occurrences?");
+       } else {
+               ok = confirm(message + "Replace all occurrences with \"" + replacement + "\"?");
+       }
+       */
+       if (ok) {
+               for (var i in spans) {
+                       if (spans[i] != currentElement) {
+                               replaceWord(spans[i]);
+                       }
+               }
+               // replace current element the last, so that we jump to the next word ;-)
+               replaceClicked();
+       }
+       return false;
+};
+
+function ignoreClicked() {
+       document.getElementById("v_replacement").value = currentElement.__msh_origWord;
+       replaceClicked();
+       return false;
+};
+
+function ignoreAllClicked() {
+       document.getElementById("v_replacement").value = currentElement.__msh_origWord;
+       replaceAllClicked();
+       return false;
+};
+
+function learnClicked() {
+       alert("Not [yet] implemented");
+       return false;
+};
+
+function internationalizeWindow() {
+       var types = ["div", "span", "button"];
+       for (var i in types) {
+               var tag = types[i];
+               var els = document.getElementsByTagName(tag);
+               for (var j = els.length; --j >= 0;) {
+                       var el = els[j];
+                       if (el.childNodes.length == 1 && /\S/.test(el.innerHTML)) {
+                               var txt = el.innerHTML;
+                               if (typeof i18n[txt] != "undefined") {
+                                       el.innerHTML = i18n[txt];
+                               }
+                       }
+               }
+       }
+};
+
+function initDocument() {
+       internationalizeWindow();
+       modified = false;
+       frame = document.getElementById("i_framecontent");
+       var field = document.getElementById("f_content");
+       field.value = HTMLArea.getHTML(editor._doc.body, false, editor);
+       field.form.submit();
+       document.getElementById("f_init").value = "0";
+
+       // assign some global event handlers
+
+       var select = document.getElementById("v_suggestions");
+       select.onchange = function() {
+               document.getElementById("v_replacement").value = this.value;
+       };
+       if (is_ie) {
+               select.attachEvent("ondblclick", replaceClicked);
+       } else {
+               select.addEventListener("dblclick", replaceClicked, true);
+       }
+
+       document.getElementById("b_replace").onclick = replaceClicked;
+       // document.getElementById("b_learn").onclick = learnClicked;
+       document.getElementById("b_replall").onclick = replaceAllClicked;
+       document.getElementById("b_ignore").onclick = ignoreClicked;
+       document.getElementById("b_ignall").onclick = ignoreAllClicked;
+       document.getElementById("b_recheck").onclick = recheckClicked;
+       document.getElementById("b_revert").onclick = revertClicked;
+       document.getElementById("b_info").onclick = displayInfo;
+
+       document.getElementById("b_ok").onclick = saveClicked;
+       document.getElementById("b_cancel").onclick = cancelClicked;
+
+       select = document.getElementById("v_dictionaries");
+       select.onchange = function() {
+               document.getElementById("f_dictionary").value = this.value;
+       };
+};
+
+function getAbsolutePos(el) {
+       var r = { x: el.offsetLeft, y: el.offsetTop };
+       if (el.offsetParent) {
+               var tmp = getAbsolutePos(el.offsetParent);
+               r.x += tmp.x;
+               r.y += tmp.y;
+       }
+       return r;
+};
+
+function wordClicked(scroll) {
+       var self = this;
+       if (scroll) (function() {
+               var pos = getAbsolutePos(self);
+               var ws = { x: frame.offsetWidth - 4,
+                          y: frame.offsetHeight - 4 };
+               var wp = { x: frame.contentWindow.document.body.scrollLeft,
+                          y: frame.contentWindow.document.body.scrollTop };
+               pos.x -= Math.round(ws.x/2);
+               if (pos.x < 0) pos.x = 0;
+               pos.y -= Math.round(ws.y/2);
+               if (pos.y < 0) pos.y = 0;
+               frame.contentWindow.scrollTo(pos.x, pos.y);
+       })();
+       if (currentElement) {
+               var a = allWords[currentElement.__msh_origWord];
+               currentElement.className = currentElement.className.replace(/\s*HA-spellcheck-current\s*/g, " ");
+               for (var i in a) {
+                       var el = a[i];
+                       if (el != currentElement) {
+                               el.className = el.className.replace(/\s*HA-spellcheck-same\s*/g, " ");
+                       }
+               }
+       }
+       currentElement = this;
+       this.className += " HA-spellcheck-current";
+       var a = allWords[currentElement.__msh_origWord];
+       for (var i in a) {
+               var el = a[i];
+               if (el != currentElement) {
+                       el.className += " HA-spellcheck-same";
+               }
+       }
+       // document.getElementById("b_replall").disabled = (a.length <= 1);
+       // document.getElementById("b_ignall").disabled = (a.length <= 1);
+       var txt;
+       if (a.length == 1) {
+               txt = "one occurrence";
+       } else if (a.length == 2) {
+               txt = "two occurrences";
+       } else {
+               txt = a.length + " occurrences";
+       }
+       var suggestions = suggested_words[this.__msh_origWord];
+       if (suggestions)
+               suggestions = suggestions.split(/,/);
+       else
+               suggestions = [];
+       var select = document.getElementById("v_suggestions");
+       document.getElementById("statusbar").innerHTML = "Found " + txt +
+               ' for word "<b>' + currentElement.__msh_origWord + '</b>"';
+       for (var i = select.length; --i >= 0;) {
+               select.remove(i);
+       }
+       for (var i = 0; i < suggestions.length; ++i) {
+               var txt = suggestions[i];
+               var option = document.createElement("option");
+               option.value = txt;
+               option.appendChild(document.createTextNode(txt));
+               select.appendChild(option);
+       }
+       document.getElementById("v_currentWord").innerHTML = this.__msh_origWord;
+       if (suggestions.length > 0) {
+               select.selectedIndex = 0;
+               select.onchange();
+       } else {
+               document.getElementById("v_replacement").value = this.innerHTML;
+       }
+       select.style.display = "none";
+       select.style.display = "block";
+       return false;
+};
+
+function wordMouseOver() {
+       this.className += " HA-spellcheck-hover";
+};
+
+function wordMouseOut() {
+       this.className = this.className.replace(/\s*HA-spellcheck-hover\s*/g, " ");
+};
+
+function displayInfo() {
+       var info = frame.contentWindow.spellcheck_info;
+       if (!info)
+               alert("No information available");
+       else {
+               var txt = "** Document information **";
+               for (var i in info) {
+                       txt += "\n" + i + " : " + info[i];
+               }
+               alert(txt);
+       }
+       return false;
+};
+
+function finishedSpellChecking() {
+       // initialization of global variables
+       currentElement = null;
+       wrongWords = null;
+       allWords = {};
+       fixedWords = [];
+       suggested_words = frame.contentWindow.suggested_words;
+
+       document.getElementById("status").innerHTML = "HTMLArea Spell Checker (<a href='readme-tech.html' target='_blank' title='Technical information'>info</a>)";
+       var doc = frame.contentWindow.document;
+        var spans = doc.getElementsByTagName("span");
+        var sps = [];
+       var id = 0;
+        for (var i = 0; i < spans.length; ++i) {
+                var el = spans[i];
+                if (/HA-spellcheck-error/.test(el.className)) {
+                        sps.push(el);
+                       el.__msh_wordClicked = wordClicked;
+                       el.onclick = function(ev) {
+                               ev || (ev = window.event);
+                               ev && HTMLArea._stopEvent(ev);
+                               return this.__msh_wordClicked(false);
+                       };
+                       el.onmouseover = wordMouseOver;
+                       el.onmouseout = wordMouseOut;
+                       el.__msh_id = id++;
+                       var txt = (el.__msh_origWord = el.firstChild.data);
+                       el.__msh_fixed = false;
+                       if (typeof allWords[txt] == "undefined") {
+                               allWords[txt] = [el];
+                       } else {
+                               allWords[txt].push(el);
+                       }
+                } else if (/HA-spellcheck-fixed/.test(el.className)) {
+                       fixedWords.push(el);
+               }
+        }
+       wrongWords = sps;
+       if (sps.length == 0) {
+               if (!modified) {
+                       alert(i18n["NO_ERRORS_CLOSING"]);
+                       window.close();
+               } else {
+                       alert(i18n["NO_ERRORS"]);
+               }
+               return false;
+       }
+       (currentElement = sps[0]).__msh_wordClicked(true);
+       var as = doc.getElementsByTagName("a");
+       for (var i = as.length; --i >= 0;) {
+               var a = as[i];
+               a.onclick = function() {
+                       if (confirm(i18n["CONFIRM_LINK_CLICK"] + ":\n" +
+                                   this.href + "\n" + i18n["I will open it in a new page."])) {
+                               window.open(this.href);
+                       }
+                       return false;
+               };
+       }
+       var dicts = doc.getElementById("HA-spellcheck-dictionaries");
+       if (dicts) {
+               dicts.parentNode.removeChild(dicts);
+               dicts = dicts.innerHTML.split(/,/);
+               var select = document.getElementById("v_dictionaries");
+               for (var i = select.length; --i >= 0;) {
+                       select.remove(i);
+               }
+               for (var i = 0; i < dicts.length; ++i) {
+                       var txt = dicts[i];
+                       var option = document.createElement("option");
+                       if (/^@(.*)$/.test(txt)) {
+                               txt = RegExp.$1;
+                               option.selected = true;
+                       }
+                       option.value = txt;
+                       option.appendChild(document.createTextNode(txt));
+                       select.appendChild(option);
+               }
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/spell-checker.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/SpellChecker/spell-checker.js
new file mode 100644 (file)
index 0000000..646969e
--- /dev/null
@@ -0,0 +1,79 @@
+// Spell Checker Plugin for HTMLArea-3.0
+// Sponsored by www.americanbible.org
+// Implementation by Mihai Bazon, http://dynarch.com/mishoo/
+//
+// (c) dynarch.com 2003.
+// Distributed under the same terms as HTMLArea itself.
+// This notice MUST stay intact for use (see license.txt).
+//
+// $Id: spell-checker.js 30938 2004-07-29 19:08:16Z vgritsenko $
+
+function SpellChecker(editor) {
+       this.editor = editor;
+
+       var cfg = editor.config;
+       var tt = SpellChecker.I18N;
+       var bl = SpellChecker.btnList;
+       var self = this;
+
+       // register the toolbar buttons provided by this plugin
+       var toolbar = [];
+       for (var i in bl) {
+               var btn = bl[i];
+               if (!btn) {
+                       toolbar.push("separator");
+               } else {
+                       var id = "SC-" + btn[0];
+                       cfg.registerButton(id, tt[id], editor.imgURL(btn[0] + ".gif", "SpellChecker"), false,
+                                          function(editor, id) {
+                                                  // dispatch button press event
+                                                  self.buttonPress(editor, id);
+                                          }, btn[1]);
+                       toolbar.push(id);
+               }
+       }
+
+       for (var i in toolbar) {
+               cfg.toolbar[0].push(toolbar[i]);
+       }
+};
+
+SpellChecker._pluginInfo = {
+       name          : "SpellChecker",
+       version       : "1.0",
+       developer     : "Mihai Bazon",
+       developer_url : "http://dynarch.com/mishoo/",
+       c_owner       : "Mihai Bazon",
+       sponsor       : "American Bible Society",
+       sponsor_url   : "http://www.americanbible.org",
+       license       : "htmlArea"
+};
+
+SpellChecker.btnList = [
+       null, // separator
+       ["spell-check"]
+       ];
+
+SpellChecker.prototype.buttonPress = function(editor, id) {
+       switch (id) {
+           case "SC-spell-check":
+               SpellChecker.editor = editor;
+               SpellChecker.init = true;
+               var uiurl = _editor_url + "plugins/SpellChecker/spell-check-ui.html";
+               var win;
+               if (HTMLArea.is_ie) {
+                       win = window.open(uiurl, "SC_spell_checker",
+                                         "toolbar=no,location=no,directories=no,status=no,menubar=no," +
+                                         "scrollbars=no,resizable=yes,width=600,height=450");
+               } else {
+                       win = window.open(uiurl, "SC_spell_checker",
+                                         "toolbar=no,menubar=no,personalbar=no,width=600,height=450," +
+                                         "scrollbars=no,resizable=yes");
+               }
+               win.focus();
+               break;
+       }
+};
+
+// this needs to be global, it's accessed from spell-check-ui.html
+SpellChecker.editor = null;
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-delete.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-delete.gif
new file mode 100644 (file)
index 0000000..df9594f
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-delete.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-insert-after.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-insert-after.gif
new file mode 100644 (file)
index 0000000..6ff2154
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-insert-after.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-insert-before.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-insert-before.gif
new file mode 100644 (file)
index 0000000..632b315
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-insert-before.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-merge.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-merge.gif
new file mode 100644 (file)
index 0000000..35e4af1
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-merge.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-prop.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-prop.gif
new file mode 100644 (file)
index 0000000..2f71bae
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-prop.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-split.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-split.gif
new file mode 100644 (file)
index 0000000..8bd011e
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/cell-split.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/col-delete.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/col-delete.gif
new file mode 100644 (file)
index 0000000..565afdc
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/col-delete.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/col-insert-after.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/col-insert-after.gif
new file mode 100644 (file)
index 0000000..648e54f
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/col-insert-after.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/col-insert-before.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/col-insert-before.gif
new file mode 100644 (file)
index 0000000..9be8a6e
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/col-insert-before.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/col-split.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/col-split.gif
new file mode 100644 (file)
index 0000000..83f21d1
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/col-split.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/makefile.xml b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/makefile.xml
new file mode 100644 (file)
index 0000000..19e075f
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<files>
+  <file name="*.{gif,jpg,jpeg}" />
+</files>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/row-delete.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/row-delete.gif
new file mode 100644 (file)
index 0000000..e649d9f
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/row-delete.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/row-insert-above.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/row-insert-above.gif
new file mode 100644 (file)
index 0000000..e39c948
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/row-insert-above.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/row-insert-under.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/row-insert-under.gif
new file mode 100644 (file)
index 0000000..2005358
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/row-insert-under.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/row-prop.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/row-prop.gif
new file mode 100644 (file)
index 0000000..7639725
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/row-prop.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/row-split.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/row-split.gif
new file mode 100644 (file)
index 0000000..0df4697
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/row-split.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/table-prop.gif b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/table-prop.gif
new file mode 100644 (file)
index 0000000..e15a4a4
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/img/table-prop.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/cz.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/cz.js
new file mode 100644 (file)
index 0000000..d407dae
--- /dev/null
@@ -0,0 +1,90 @@
+// I18N constants
+
+// LANG: "cz", ENCODING: UTF-8 | ISO-8859-2
+// Author: Jiri Löw, <jirilow@jirilow.com>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+TableOperations.I18N = {
+       "Align":                                          "Zarovnání",
+       "All four sides":                                 "Všechny čtyři strany",
+       "Background":                                     "Pozadí",
+       "Baseline":                                       "Základní linka",
+       "Border":                                         "Obrys",
+       "Borders":                                        "Obrysy",
+       "Bottom":                                         "Dolů",
+       "CSS Style":                                      "Kaskádové styly (CSS)",
+       "Caption":                                        "Titulek",
+       "Cell Properties":                                "Vlastnosti buňky",
+       "Center":                                         "Na střed",
+       "Char":                                           "Znak",
+       "Collapsed borders":                              "Stlačené okraje",
+       "Color":                                          "Barva",
+       "Description":                                    "Popis",
+       "FG Color":                                       "Barva popředí",
+       "Float":                                          "Obtékání",
+       "Frames":                                         "Rámečky",
+       "Height":                                         "Výška",
+       "How many columns would you like to merge?":      "Kolik sloupců si přejete spojit?",
+       "How many rows would you like to merge?":         "Kolik řádků si přejete spojit?",
+       "Image URL":                                      "Adresa obrázku",
+       "Justify":                                        "Do stran",
+       "Layout":                                         "Rozložení",
+       "Left":                                           "Vlevo",
+       "Margin":                                         "Okraj",
+       "Middle":                                         "Na střed",
+       "No rules":                                       "Žádné čáry",
+       "No sides":                                       "Žádné strany",
+       "None":                                           "Žádné",
+       "Padding":                                        "Odsazování",
+       "Please click into some cell":                    "Prosím klikněte do některé buňky",
+       "Right":                                          "Vpravo",
+       "Row Properties":                                 "Vlastnosti řádku",
+       "Rules will appear between all rows and columns": "Čáry mezi všemi řádky i sloupci",
+       "Rules will appear between columns only":         "Čáry pouze mezi sloupci",
+       "Rules will appear between rows only":            "Čáry pouze mezi řádky",
+       "Rules":                                          "Čáry",
+       "Spacing and padding":                            "Mezery a odsazování",
+       "Spacing":                                        "Mezery",
+       "Summary":                                        "Shrnutí",
+       "TO-cell-delete":                                 "Smazat buňku",
+       "TO-cell-insert-after":                           "Vložit buňku za",
+       "TO-cell-insert-before":                          "Vložit buňku před",
+       "TO-cell-merge":                                  "Spojit buňky",
+       "TO-cell-prop":                                   "Vlastnosti buňky",
+       "TO-cell-split":                                  "Rozdělit buňku",
+       "TO-col-delete":                                  "Smazat sloupec",
+       "TO-col-insert-after":                            "Vložit sloupec za",
+       "TO-col-insert-before":                           "Vložit sloupec před",
+       "TO-col-split":                                   "Rozdělit sloupec",
+       "TO-row-delete":                                  "Smazat řádek",
+       "TO-row-insert-above":                            "Smazat řádek nad",
+       "TO-row-insert-under":                            "Smazat řádek pod",
+       "TO-row-prop":                                    "Vlastnosti řádku",
+       "TO-row-split":                                   "Rozdělit řádek",
+       "TO-table-prop":                                  "Vlastnosti tabulky",
+       "Table Properties":                               "Vlastnosti tabulky",
+       "Text align":                                     "Zarovnání textu",
+       "The bottom side only":                           "Pouze spodní strana",
+       "The left-hand side only":                        "Pouze levá strana",
+       "The right and left sides only":                  "Pouze levá a pravá strana",
+       "The right-hand side only":                       "Pouze pravá strana",
+       "The top and bottom sides only":                  "Pouze horní a dolní strana",
+       "The top side only":                              "Pouze horní strana",
+       "Top":                                            "Nahoru",     
+       "Unset color":                                    "Zrušit barvu",
+       "Vertical align":                                 "Svislé zarovnání",
+       "Width":                                          "Šířka",
+       "not-del-last-cell":                              "HTMLArea zbaběle odmítá smazat poslední buňku v řádku.",
+       "not-del-last-col":                               "HTMLArea zbaběle odmítá smazat poslední sloupec v tabulce.",
+       "not-del-last-row":                               "HTMLArea zbaběle odmítá smazat poslední řádek v tabulce.",
+       "percent":                                        "procent",
+       "pixels":                                         "pixelů"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/da.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/da.js
new file mode 100644 (file)
index 0000000..08a6f1b
--- /dev/null
@@ -0,0 +1,90 @@
+// I18N constants
+
+// LANG: "da", ENCODING: UTF-8 | ISO-8859-1
+// Author: Steen Sønderup, <steen@soenderup.com>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+TableOperations.I18N = {
+       "Align":                                                                                        "Placer",
+       "All four sides":                                                                       "Alle fire sider",
+       "Background":                                                                           "Baggrund",
+       "Baseline":                                                                                     "Bundlinie",
+       "Border":                                                                                       "Kant",
+       "Borders":                                                                                      "Kanter",
+       "Bottom":                                                                                       "Bund",
+       "CSS Style":                                                                            "Stil [CSS]",
+       "Caption":                                                                                      "Titel",
+       "Cell Properties":                                                                      "Celle egenskaber",
+       "Center":                                                                                       "Centrer",
+       "Char":                                                                                         "Plads",
+       "Collapsed borders":                                                            "Sammensmelt rammer",
+       "Color":                                                                                        "Farve",
+       "Description":                                                                          "Beskrivelse",
+       "FG Color":                                                                                     "Font farve",
+       "Float":                                                                                        "Justering",
+       "Frames":                                                                                       "Udvendig",
+       "Height":                                                                                       "Højde",
+       "How many columns would you like to merge?":            "Hvor mange kollonner vil du samle?",
+       "How many rows would you like to merge?":                       "Hvor mange rækker vil du samle?",
+       "Image URL":                                                                            "Billede URL",
+       "Justify":                                                                                      "Lige margener",
+       "Layout":                                                                                       "Opsætning",
+       "Left":                                                                                         "Venstre",
+       "Margin":                                                                                       "Margen",
+       "Middle":                                                                                       "Centrer",
+       "No rules":                                                                                     "Ingen rammer",
+       "No sides":                                                                                     "Ingen sider",
+       "None":                                                                                         "Ingen",
+       "Padding":                                                                                      "Margen",
+       "Please click into some cell":                                          "Klik på en celle",
+       "Right":                                                                                        "Højre",
+       "Row Properties":                                                                       "Række egenskaber",
+       "Rules will appear between all rows and columns":       "Rammer mellem rækker og kolonner",
+       "Rules will appear between columns only":                       "Kun rammer mellem kolonner",
+       "Rules will appear between rows only":                          "Kun rammer mellem rækker",
+       "Rules":                                                                                        "Invendig",
+       "Spacing and padding":                                                          "Afstand og margen",
+       "Spacing":                                                                                      "Afstand",
+       "Summary":                                                                                      "Beskrivelse",
+       "TO-cell-delete":                                                                       "Slet celle",
+       "TO-cell-insert-after":                                                         "Indsæt celle efter",
+       "TO-cell-insert-before":                                                        "Indsæt celle før",
+       "TO-cell-merge":                                                                        "Sammensæt celler",
+       "TO-cell-prop":                                                                         "Celle egenskaber",
+       "TO-cell-split":                                                                        "Opdel celle",
+       "TO-col-delete":                                                                        "Slet kollonne",
+       "TO-col-insert-after":                                                          "Indsæt kolonne efter",
+       "TO-col-insert-before":                                                         "Indsæt kolonne før",
+       "TO-col-split":                                                                         "Opdel kolonne",
+       "TO-row-delete":                                                                        "Slet række",
+       "TO-row-insert-above":                                                          "Indsæt række før",
+       "TO-row-insert-under":                                                          "Indsæt række efter",
+       "TO-row-prop":                                                                          "Række egenskaber",
+       "TO-row-split":                                                                         "Opdel række",
+       "TO-table-prop":                                                                        "Tabel egenskaber",
+       "Table Properties":                                                                     "Tabel egenskaber",
+       "Text align":                                                                           "Tekst",
+       "The bottom side only":                                                         "Kun i bunden",
+       "The left-hand side only":                                                      "Kun i højre side",
+       "The right and left sides only":                                        "Kun i siderne",
+       "The right-hand side only":                                                     "Kun i venstre side",
+       "The top and bottom sides only":                                        "Kun i top og bund",
+       "The top side only":                                                            "Kun i toppen",
+       "Top":                                                                                          "Top",  
+       "Unset color":                                                                          "Farve ikke valgt",
+       "Vertical align":                                                                       "Vertikal placering",
+       "Width":                                                                                        "Bredde",
+       "not-del-last-cell":                                                            "Du kan ikke slette den sidste celle i en række.",
+       "not-del-last-col":                                                                     "Du kan ikke slette den sidste kolonne i en tabel.",
+       "not-del-last-row":                                                                     "Du kan ikke slette den sidste række i en tabel.",
+       "percent":                                                                                      "procent",
+       "pixels":                                                                                       "pixel"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/de.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/de.js
new file mode 100644 (file)
index 0000000..1128cff
--- /dev/null
@@ -0,0 +1,81 @@
+// I18N constants
+
+// LANG: "de", ENCODING: UTF-8 | ISO-8859-1
+// Author: broxx, <broxx@broxx.com>
+
+TableOperations.I18N = {
+       "Align":                                          "Ausrichten",
+       "All four sides":                                 "Alle 4 Seiten",
+       "Background":                                     "Hintergrund",
+       "Baseline":                                       "Basislinie",
+       "Border":                                         "Rand",
+       "Borders":                                        "Raender",
+       "Bottom":                                         "Unten",
+       "CSS Style":                                      "Style [CSS]",
+       "Caption":                                        "Ueberschrift",
+       "Cell Properties":                                "Zellen",
+       "Center":                                         "Zentrieren",
+       "Char":                                           "Zeichen",
+       "Collapsed borders":                              "Collapsed borders",
+       "Color":                                          "Farbe",
+       "Description":                                    "Beschreibung",
+       "FG Color":                                       "FG Farbe",
+       "Float":                                          "Ausrichtung",
+       "Frames":                                         "Rahmen",
+       "Height":                                         "Hoehe",
+       "How many columns would you like to merge?":      "Wieviele Spalten willst du verbinden?",
+       "How many rows would you like to merge?":         "Wieviele Zeilen willst du verbinden?",
+       "Image URL":                                      "Bild URL",
+       "Justify":                                        "Justieren",
+       "Layout":                                         "Layout",
+       "Left":                                           "Links",
+       "Margin":                                         "Rand",
+       "Middle":                                         "Mitte",
+       "No rules":                                       "Keine Balken",
+       "No sides":                                       "Keine Seiten",
+       "None":                                           "Keine",
+       "Padding":                                        "Auffuellung",
+       "Please click into some cell":                    "Waehle eine Zelle",
+       "Right":                                          "Rechts",
+       "Row Properties":                                 "Reihen",
+       "Rules will appear between all rows and columns": "Balken zwischen Reihen und Spalten",
+       "Rules will appear between columns only":         "Balken zwischen Spalten",
+       "Rules will appear between rows only":            "Balken zwischen Reihen",
+       "Rules":                                          "Balken",
+       "Spacing and padding":                            "Abstaende",
+       "Spacing":                                        "Abstand",
+       "Summary":                                        "Zusammenfassung",
+       "TO-cell-delete":                                 "Zelle loeschen",
+       "TO-cell-insert-after":                           "Zelle einfuegen nach",
+       "TO-cell-insert-before":                          "Zelle einfuegen bevor",
+       "TO-cell-merge":                                  "Zellen zusammenfuegen",
+       "TO-cell-prop":                                   "Zelleinstellungen",
+       "TO-cell-split":                                  "Zellen aufteilen",
+       "TO-col-delete":                                  "Spalte loeschen",
+       "TO-col-insert-after":                            "Spalte einfuegen nach",
+       "TO-col-insert-before":                           "Spalte einfuegen bevor",
+       "TO-col-split":                                   "Spalte aufteilen",
+       "TO-row-delete":                                  "Reihe loeschen",
+       "TO-row-insert-above":                            "Reihe einfuegen vor",
+       "TO-row-insert-under":                            "Reihe einfuegen nach",
+       "TO-row-prop":                                    "Reiheneinstellungen",
+       "TO-row-split":                                   "Reihen aufteilen",
+       "TO-table-prop":                                  "Tabelle",
+       "Table Properties":                               "Tabelle",
+       "Text align":                                     "Ausrichtung",
+       "The bottom side only":                           "Nur untere Seite",
+       "The left-hand side only":                        "Nur linke Seite",
+       "The right and left sides only":                  "Nur linke und rechte Seite",
+       "The right-hand side only":                       "Nur rechte Seite",
+       "The top and bottom sides only":                  "Nur obere und untere Seite",
+       "The top side only":                              "Nur obere Seite",
+       "Top":                                            "Oben",       
+       "Unset color":                                    "Farbe",
+       "Vertical align":                                 "Ausrichtung",
+       "Width":                                          "Breite",
+       "not-del-last-cell":                              "Letzte Zelle in dieser Reihe!",
+       "not-del-last-col":                               "Letzte Spalte in dieser Tabelle!",
+       "not-del-last-row":                               "Letzte Reihe in dieser Tabelle",
+       "percent":                                        "%",
+       "pixels":                                         "pixels"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/el.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/el.js
new file mode 100644 (file)
index 0000000..06bae5c
--- /dev/null
@@ -0,0 +1,81 @@
+// I18N constants
+
+// LANG: "el", ENCODING: UTF-8 | ISO-8859-7
+// Author: Dimitris Glezos, dimitris@glezos.com
+
+TableOperations.I18N = {
+       "Align":                                          "Στοίχηση",
+       "All four sides":                                 "Και οι 4 πλευρές",
+       "Background":                                     "Φόντο",
+       "Baseline":                                       "Baseline",
+       "Border":                                         "Περίγραμμα",
+       "Borders":                                        "Περιγράμματα",
+       "Bottom":                                         "Κάτω μέρος",
+       "CSS Style":                                      "Στυλ [CSS]",
+       "Caption":                                        "Λεζάντα",
+       "Cell Properties":                                "Ιδιότητες Κελιού",
+       "Center":                                         "Κέντρο",
+       "Char":                                           "Χαρακτήρας",
+       "Collapsed borders":                              "Συμπτυγμένα περιγράμματα",
+       "Color":                                          "Χρώμα",
+       "Description":                                    "Περιγραφή",
+       "FG Color":                                       "Χρώμα αντικειμένων",
+       "Float":                                          "Float",
+       "Frames":                                         "Frames",
+       "Height":                                         "Ύψος",
+       "How many columns would you like to merge?":      "Πόσες στήλες θέλετε να ενώσετε;",
+       "How many rows would you like to merge?":         "Πόσες γραμμές θέλετε να ενώσετε;",
+       "Image URL":                                      "URL εικόνας",
+       "Justify":                                        "Πλήρης στοίχηση",
+       "Layout":                                         "Διάταξη",
+       "Left":                                           "Αριστερά",
+       "Margin":                                         "Περιθώριο",
+       "Middle":                                         "Κέντρο",
+       "No rules":                                       "Χωρίς Γραμμές",
+       "No sides":                                       "No sides",
+       "None":                                           "Τίποτα",
+       "Padding":                                        "Εσοχή",
+       "Please click into some cell":                    "Κάντε κλικ μέσα σε κάποιο κελί",
+       "Right":                                          "Δεξιά",
+       "Row Properties":                                 "Ιδιότητες Γραμμής",
+       "Rules will appear between all rows and columns": "Γραμμές θα εμφανίζονται μεταξύ όλων των γραμμών και στηλών",
+       "Rules will appear between columns only":         "Γραμμές θα εμφανίζονται μόνο μεταξύ στηλών",
+       "Rules will appear between rows only":            "Γραμμές θα εμφανίζονται μόνο μεταξύ γραμμών",
+       "Rules":                                          "Γραμμές",
+       "Spacing and padding":                            "Αποστάσεις και εσοχές",
+       "Spacing":                                        "Αποστάσεις",
+       "Summary":                                        "Σύνοψη",
+       "TO-cell-delete":                                 "Διαγραφή κελιού",
+       "TO-cell-insert-after":                           "Εισαγωγή κελιού μετά",
+       "TO-cell-insert-before":                          "Εισαγωγή κελιού πριν",
+       "TO-cell-merge":                                  "Συγχώνευση κελιών",
+       "TO-cell-prop":                                   "Ιδιότητες κελιού",
+       "TO-cell-split":                                  "Διαίρεση κελιού",
+       "TO-col-delete":                                  "Διαγραφή στήλης",
+       "TO-col-insert-after":                            "Εισαγωγή στήλης μετά",
+       "TO-col-insert-before":                           "Εισαγωγή στήλης πριν",
+       "TO-col-split":                                   "Διαίρεση στήλης",
+       "TO-row-delete":                                  "Διαγραφή γραμμής",
+       "TO-row-insert-above":                            "Εισαγωγή γραμμής μετά",
+       "TO-row-insert-under":                            "Εισαγωγή γραμμής πριν",
+       "TO-row-prop":                                    "Ιδιότητες γραμμής",
+       "TO-row-split":                                   "Διαίρεση γραμμής",
+       "TO-table-prop":                                  "Ιδιότητες πίνακα",
+       "Table Properties":                               "Ιδιότητες πίνακα",
+       "Text align":                                     "Στοίχηση κειμένου",
+       "The bottom side only":                           "Η κάτω πλευρά μόνο",
+       "The left-hand side only":                        "Η αριστερή πλευρά μόνο",
+       "The right and left sides only":                  "Οι δεξιές και αριστερές πλευρές μόνο",
+       "The right-hand side only":                       "Η δεξιά πλευρά μόνο",
+       "The top and bottom sides only":                  "Οι πάνω και κάτω πλευρές μόνο",
+       "The top side only":                              "Η πάνω πλευρά μόνο",
+       "Top":                                            "Πάνω",   
+       "Unset color":                                    "Αναίρεση χρώματος",
+       "Vertical align":                                 "Κατακόρυφη στοίχηση",
+       "Width":                                          "Πλάτος",
+       "not-del-last-cell":                              "Δεν μπορεί να διαγραφεί το τελευταίο κελί σε μια γραμμή.",
+       "not-del-last-col":                               "Δεν μπορεί να διαγραφεί η τελευταία στήλη σε ένα πίνακα.",
+       "not-del-last-row":                               "Δεν μπορεί να διαγραφεί η τελευταία γραμμή σε ένα πίνακα.",
+       "percent":                                        "τοις εκατόν",
+       "pixels":                                         "pixels"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/en.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/en.js
new file mode 100644 (file)
index 0000000..7168e09
--- /dev/null
@@ -0,0 +1,90 @@
+// I18N constants
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+TableOperations.I18N = {
+       "Align":                                          "Align",
+       "All four sides":                                 "All four sides",
+       "Background":                                     "Background",
+       "Baseline":                                       "Baseline",
+       "Border":                                         "Border",
+       "Borders":                                        "Borders",
+       "Bottom":                                         "Bottom",
+       "CSS Style":                                      "Style [CSS]",
+       "Caption":                                        "Caption",
+       "Cell Properties":                                "Cell Properties",
+       "Center":                                         "Center",
+       "Char":                                           "Char",
+       "Collapsed borders":                              "Collapsed borders",
+       "Color":                                          "Color",
+       "Description":                                    "Description",
+       "FG Color":                                       "FG Color",
+       "Float":                                          "Float",
+       "Frames":                                         "Frames",
+       "Height":                                         "Height",
+       "How many columns would you like to merge?":      "How many columns would you like to merge?",
+       "How many rows would you like to merge?":         "How many rows would you like to merge?",
+       "Image URL":                                      "Image URL",
+       "Justify":                                        "Justify",
+       "Layout":                                         "Layout",
+       "Left":                                           "Left",
+       "Margin":                                         "Margin",
+       "Middle":                                         "Middle",
+       "No rules":                                       "No rules",
+       "No sides":                                       "No sides",
+       "None":                                           "None",
+       "Padding":                                        "Padding",
+       "Please click into some cell":                    "Please click into some cell",
+       "Right":                                          "Right",
+       "Row Properties":                                 "Row Properties",
+       "Rules will appear between all rows and columns": "Rules will appear between all rows and columns",
+       "Rules will appear between columns only":         "Rules will appear between columns only",
+       "Rules will appear between rows only":            "Rules will appear between rows only",
+       "Rules":                                          "Rules",
+       "Spacing and padding":                            "Spacing and padding",
+       "Spacing":                                        "Spacing",
+       "Summary":                                        "Summary",
+       "TO-cell-delete":                                 "Delete cell",
+       "TO-cell-insert-after":                           "Insert cell after",
+       "TO-cell-insert-before":                          "Insert cell before",
+       "TO-cell-merge":                                  "Merge cells",
+       "TO-cell-prop":                                   "Cell properties",
+       "TO-cell-split":                                  "Split cell",
+       "TO-col-delete":                                  "Delete column",
+       "TO-col-insert-after":                            "Insert column after",
+       "TO-col-insert-before":                           "Insert column before",
+       "TO-col-split":                                   "Split column",
+       "TO-row-delete":                                  "Delete row",
+       "TO-row-insert-above":                            "Insert row before",
+       "TO-row-insert-under":                            "Insert row after",
+       "TO-row-prop":                                    "Row properties",
+       "TO-row-split":                                   "Split row",
+       "TO-table-prop":                                  "Table properties",
+       "Table Properties":                               "Table Properties",
+       "Text align":                                     "Text align",
+       "The bottom side only":                           "The bottom side only",
+       "The left-hand side only":                        "The left-hand side only",
+       "The right and left sides only":                  "The right and left sides only",
+       "The right-hand side only":                       "The right-hand side only",
+       "The top and bottom sides only":                  "The top and bottom sides only",
+       "The top side only":                              "The top side only",
+       "Top":                                            "Top",        
+       "Unset color":                                    "Unset color",
+       "Vertical align":                                 "Vertical align",
+       "Width":                                          "Width",
+       "not-del-last-cell":                              "HTMLArea cowardly refuses to delete the last cell in row.",
+       "not-del-last-col":                               "HTMLArea cowardly refuses to delete the last column in table.",
+       "not-del-last-row":                               "HTMLArea cowardly refuses to delete the last row in table.",
+       "percent":                                        "percent",
+       "pixels":                                         "pixels"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/fi.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/fi.js
new file mode 100644 (file)
index 0000000..891f168
--- /dev/null
@@ -0,0 +1,66 @@
+TableOperations.I18N = {
+       "Align":                                          "Kohdistus",
+       "All four sides":                                 "Kaikki neljä sivua",
+       "Background":                                     "Tausta",
+       "Baseline":                                       "Takaraja",
+       "Border":                                         "Reuna",
+       "Borders":                                        "Reunat",
+       "Bottom":                                         "Alle",
+       "CSS Style":                                      "Tyyli [CSS]",
+       "Caption":                                        "Otsikko",
+       "Cell Properties":                                "Solun asetukset",
+       "Center":                                         "Keskelle",
+       "Char":                                           "Merkki",
+       "Collapsed borders":                              "Luhistetut reunat",
+       "Color":                                          "Väri",
+       "Description":                                    "Kuvaus",
+       "FG Color":                                       "FG Väri",
+       "Frames":                                         "Kehykset",
+       "Image URL":                                      "Kuvan osoite",
+       "Layout":                                         "Sommittelu",
+       "Left":                                           "Vasen",
+       "Margin":                                         "Marginaali",
+       "Middle":                                         "Keskelle",
+       "No rules":                                       "Ei viivoja",
+       "No sides":                                       "Ei sivuja",
+       "Padding":                                        "Palstantäyte",
+       "Right":                                          "Oikea",
+       "Row Properties":                                 "Rivin asetukset",
+       "Rules will appear between all rows and columns": "Viivat jokaisen rivin ja sarakkeen välillä",
+       "Rules will appear between columns only":         "Viivat ainoastaan sarakkeiden välillä",
+       "Rules will appear between rows only":            "Viivat ainoastaan rivien välillä",
+       "Rules":                                          "Viivat",
+       "Spacing":                                        "Palstatila",
+       "Summary":                                        "Yhteenveto",
+       "TO-cell-delete":                                 "Poista solu",
+       "TO-cell-insert-after":                           "Lisää solu perään",
+       "TO-cell-insert-before":                          "Lisää solu ennen",
+       "TO-cell-merge":                                  "Yhdistä solut",
+       "TO-cell-prop":                                   "Solun asetukset",
+       "TO-cell-split":                                  "Jaa solu",
+       "TO-col-delete":                                  "Poista sarake",
+       "TO-col-insert-after":                            "Lisää sarake perään",
+       "TO-col-insert-before":                           "Lisää sarake ennen",
+       "TO-col-split":                                   "Jaa sarake",
+       "TO-row-delete":                                  "Poista rivi",
+       "TO-row-insert-above":                            "Lisää rivi yläpuolelle",
+       "TO-row-insert-under":                            "Lisää rivi alapuolelle",
+       "TO-row-prop":                                    "Rivin asetukset",
+       "TO-row-split":                                   "Jaa rivi",
+       "TO-table-prop":                                  "Taulukon asetukset",
+       "Top":                                            "Ylös",       
+       "Table Properties":                               "Taulukon asetukset",
+       "The bottom side only":                           "Ainoastaan alapuolelle",
+       "The left-hand side only":                        "Ainoastaan vasenreuna",
+       "The right and left sides only":                  "Oikea- ja vasenreuna",
+       "The right-hand side only":                       "Ainoastaan oikeareuna",
+       "The top and bottom sides only":                  "Ylä- ja alapuoli.",
+       "The top side only":                              "Ainoastaan yläpuoli",
+       "Vertical align":                                 "Vertikaali kohdistus",
+       "Width":                                          "Leveys",
+       "not-del-last-cell":                              "Ei voida poistaa viimeistä solua rivistä.",
+       "not-del-last-col":                               "Ei voida poistaa viimeistä saraketta taulusta.",
+       "not-del-last-row":                               "Ei voida poistaa viimeistä riviä taulusta.",
+       "percent":                                        "prosenttia",
+       "pixels":                                         "pikseliä"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/hu.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/hu.js
new file mode 100644 (file)
index 0000000..828aec1
--- /dev/null
@@ -0,0 +1,63 @@
+// I18N constants
+
+// LANG: "hu", ENCODING: UTF-8
+// Author: Miklós Somogyi, <somogyine@vnet.hu>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "hu",
+
+       tooltips: {
+               bold:           "Félkövér",
+               italic:         "Dőlt",
+               underline:      "Aláhúzott",
+               strikethrough:  "Áthúzott",
+               subscript:      "Alsó index",
+               superscript:    "Felső index",
+               justifyleft:    "Balra zárt",
+               justifycenter:  "Középre zárt",
+               justifyright:   "Jobbra zárt",
+               justifyfull:    "Sorkizárt",
+               orderedlist:    "Számozott lista",
+               unorderedlist:  "Számozatlan lista",
+               outdent:        "Behúzás csökkentése",
+               indent:         "Behúzás növelése",
+               forecolor:      "Karakterszín",
+               hilitecolor:    "Háttérszín",
+               horizontalrule: "Elválasztó vonal",
+               createlink:     "Hiperhivatkozás beszúrása",
+               insertimage:    "Kép beszúrása",
+               inserttable:    "Táblázat beszúrása",
+               htmlmode:       "HTML forrás be/ki",
+               popupeditor:    "Szerkesztő külön ablakban",
+               about:          "Névjegy",
+               showhelp:       "Súgó",
+               textindicator:  "Aktuális stílus",
+               undo:           "Visszavonás",
+               redo:           "Újra végrehajtás",
+               cut:            "Kivágás",
+               copy:           "Másolás",
+               paste:          "Beillesztés"
+       },
+
+       buttons: {
+               "ok":           "Rendben",
+               "cancel":       "Mégsem"
+       },
+
+       msg: {
+               "Path":         "Hierarchia",
+               "TEXT_MODE":    "Forrás mód. Visszaváltás [<>] gomb"
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/it.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/it.js
new file mode 100644 (file)
index 0000000..ccbdc94
--- /dev/null
@@ -0,0 +1,81 @@
+// I18N constants
+
+// LANG: "it", ENCODING: UTF-8 | ISO-8859-1
+// Author: Fabio Rotondo <fabio@rotondo.it>
+
+TableOperations.I18N = {
+       "Align":                                          "Allinea",
+       "All four sides":                                 "Tutti e quattro i lati",
+       "Background":                                     "Sfondo",
+       "Baseline":                                       "Allineamento",
+       "Border":                                         "Bordo",
+       "Borders":                                        "Bordi",
+       "Bottom":                                         "Basso",
+       "CSS Style":                                      "Stile [CSS]",
+       "Caption":                                        "Titolo",
+       "Cell Properties":                                "Proprietà della Cella",
+       "Center":                                         "Centra",
+       "Char":                                           "Carattere",
+       "Collapsed borders":                              "Bordi chiusi",
+       "Color":                                          "Colore",
+       "Description":                                    "Descrizione",
+       "FG Color":                                       "Colore Principale",
+       "Float":                                          "Fluttuante",
+       "Frames":                                         "Frames",
+       "Height":                                         "Altezza",
+       "How many columns would you like to merge?":      "Quante colonne vuoi unire?",
+       "How many rows would you like to merge?":         "Quante righe vuoi unire?",
+       "Image URL":                                      "URL dell'Immagine",
+       "Justify":                                        "Justifica",
+       "Layout":                                         "Layout",
+       "Left":                                           "Sinistra",
+       "Margin":                                         "Margine",
+       "Middle":                                         "Centrale",
+       "No rules":                                       "Nessun righello",
+       "No sides":                                       "Nessun lato",
+       "None":                                           "Nulla",
+       "Padding":                                        "Padding",
+       "Please click into some cell":                    "Per favore, clicca in una cella",
+       "Right":                                          "Destra",
+       "Row Properties":                                 "Proprietà della Riga",
+       "Rules will appear between all rows and columns": "Le linee appariranno tra tutte le righe e colonne",
+       "Rules will appear between columns only":         "Le linee appariranno solo tra le colonne",
+       "Rules will appear between rows only":            "Le linee appariranno solo tra le righe",
+       "Rules":                                          "Linee",
+       "Spacing and padding":                            "Spaziatura e Padding",
+       "Spacing":                                        "Spaziatura",
+       "Summary":                                        "Sommario",
+       "TO-cell-delete":                                 "Cancella cella",
+       "TO-cell-insert-after":                           "Inserisci cella dopo",
+       "TO-cell-insert-before":                          "Inserisci cella prima",
+       "TO-cell-merge":                                  "Unisci celle",
+       "TO-cell-prop":                                   "Proprietà della cella",
+       "TO-cell-split":                                  "Dividi cella",
+       "TO-col-delete":                                  "Cancella colonna",
+       "TO-col-insert-after":                            "Inserisci colonna dopo",
+       "TO-col-insert-before":                           "Inserisci colonna prima",
+       "TO-col-split":                                   "Dividi colonna",
+       "TO-row-delete":                                  "Cancella riga",
+       "TO-row-insert-above":                            "Inserisci riga prima",
+       "TO-row-insert-under":                            "Inserisci riga dopo",
+       "TO-row-prop":                                    "Proprietà della riga",
+       "TO-row-split":                                   "Dividi riga",
+       "TO-table-prop":                                  "Proprietà della Tabella",
+       "Table Properties":                               "Proprietà della Tabella",
+       "Text align":                                     "Allineamento del Testo",
+       "The bottom side only":                           "Solo la parte inferiore",
+       "The left-hand side only":                        "Solo la parte sinistra",
+       "The right and left sides only":                  "Solo destra e sinistra",
+       "The right-hand side only":                       "Solo la parte destra",
+       "The top and bottom sides only":                  "Solo sopra e sotto",
+       "The top side only":                              "Solo la parte sopra",
+       "Top":                                            "Alto",       
+       "Unset color":                                    "Rimuovi colore",
+       "Vertical align":                                 "Allineamento verticale",
+       "Width":                                          "Larghezza",
+       "not-del-last-cell":                              "HTMLArea si rifiuta codardamente di cancellare l'ultima cella nella riga.",
+       "not-del-last-col":                               "HTMLArea si rifiuta codardamente di cancellare l'ultima colonna nella tabella.",
+       "not-del-last-row":                               "HTMLArea si rifiuta codardamente di cancellare l'ultima riga nella tabella.",
+       "percent":                                        "percento",
+       "pixels":                                         "pixels"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/makefile.xml b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/makefile.xml
new file mode 100644 (file)
index 0000000..0d645c9
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<files>
+  <file name="*.js" />
+</files>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/nl.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/nl.js
new file mode 100644 (file)
index 0000000..ce9eb30
--- /dev/null
@@ -0,0 +1,90 @@
+// I18N constants
+
+// LANG: "nl", ENCODING: UTF-8 | ISO-8859-1
+// Author: Michel Weegeerink (info@mmc-shop.nl), http://mmc-shop.nl
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+TableOperations.I18N = {
+       "Align":                                                                                        "Uitlijning",
+       "All four sides":                                                                       "Alle 4 zijden",
+       "Background":                                                                           "Achtergrond",
+       "Baseline":                                                                                     "Basis",
+       "Border":                                                                                       "Rand",
+       "Borders":                                                                                      "Randen",
+       "Bottom":                                                                                       "Onder",
+       "CSS Style":                                                                            "CSS Style",
+       "Caption":                                                                                      "Opmerking",
+       "Cell Properties":                                                                      "Celeigenschappen",
+       "Center":                                                                                       "Centreren",
+       "Char":                                                                                         "Karakter",
+       "Collapsed borders":                                                            "Geen randen",
+       "Color":                                                                                        "Kleur",
+       "Description":                                                                          "Omschrijving",
+       "FG Color":                                                                                     "Voorgrond",
+       "Float":                                                                                        "Zwevend",
+       "Frames":                                                                                       "Frames",
+       "Height":                                                                                       "Hoogte",
+       "How many columns would you like to merge?":            "Hoeveel kolommen wilt u samenvoegen?",
+       "How many rows would you like to merge?":                       "Hoeveel rijen wilt u samenvoegen?",
+       "Image URL":                                                                            "Afbeelding URL",
+       "Justify":                                                                                      "Uitvullen",
+       "Layout":                                                                                       "Opmaak",
+       "Left":                                                                                         "Links",
+       "Margin":                                                                                       "Marge",
+       "Middle":                                                                                       "Midden",
+       "No rules":                                                                                     "Geen regels",
+       "No sides":                                                                                     "Geen zijlijnen",
+       "None":                                                                                         "Geen",
+       "Padding":                                                                                      "Celmarge",
+       "Please click into some cell":                                          "Klik in een cel a.u.b.",
+       "Right":                                                                                        "Rechts",
+       "Row Properties":                                                                       "Rijeigenschappen",
+       "Rules will appear between all rows and columns":       "Regels verschijnen tussen alle rijen en kolommen",
+       "Rules will appear between columns only":                       "Regels verschijnen enkel tussen de kolommen",
+       "Rules will appear between rows only":                          "Regels verschijnen enkel tussen de rijen",
+       "Rules":                                                                                        "Regels",
+       "Spacing and padding":                                  "Celmarge en afstand tussen cellen",
+       "Spacing":                                                                                      "marge",
+       "Summary":                                                                                      "Overzicht",
+       "TO-cell-delete":                                                                       "Cel verwijderen",
+       "TO-cell-insert-after":                                                         "Voeg cel toe achter",
+       "TO-cell-insert-before":                                                        "Voeg cel toe voor",
+       "TO-cell-merge":                                                                        "Cellen samenvoegen",
+       "TO-cell-prop":                                                                         "Celeigenschappen",
+       "TO-cell-split":                                                                        "Cel splitsen",
+       "TO-col-delete":                                                                        "Kolom verwijderen",
+       "TO-col-insert-after":                                                          "Kolom invoegen achter",
+       "TO-col-insert-before":                                                         "Kolom invoegen voor",
+       "TO-col-split":                                                                         "Kolom splitsen",
+       "TO-row-delete":                                                                        "Rij verwijderen",
+       "TO-row-insert-above":                                                          "Rij invoegen boven",
+       "TO-row-insert-under":                                                          "Rij invoegen onder",
+       "TO-row-prop":                                                                          "Rij eigenschappen",
+       "TO-row-split":                                                                         "Rij splitsen",
+       "TO-table-prop":                                                                        "Tabel eigenschappen",
+       "Table Properties":                                                                     "Tabel eigenschappen",
+       "Text align":                                           "Text uitlijning",
+       "The bottom side only":                                                         "Enkel aan de onderkant",
+       "The left-hand side only":                                                      "Enkel aan de linkerkant",
+       "The right and left sides only":                                        "Enkel aan de linker en rechterkant",
+       "The right-hand side only":                                                     "Enkel aan de rechterkant",
+       "The top and bottom sides only":                                        "Enkel aan de bovenen onderkant",
+       "The top side only":                                                            "Enkel aan de bovenkant",
+       "Top":                                                                                          "Boven",
+       "Unset color":                                                                          "Wis kleur",
+       "Vertical align":                                                                       "Vertikale uitlijning",
+       "Width":                                                                                        "Breedte",
+       "not-del-last-cell":                                                            "HTMLArea kan de laatste cel in deze tabel niet verwijderen.",
+       "not-del-last-col":                                                                     "HTMLArea kan de laatste kolom in deze tabel niet verwijderen.",
+       "not-del-last-row":                                                                     "HTMLArea kan de laatste rij in deze tabel niet verwijderen.",
+       "percent":                                                                                      "procent",
+       "pixels":                                                                                       "pixels"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/no.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/no.js
new file mode 100644 (file)
index 0000000..a29e903
--- /dev/null
@@ -0,0 +1,91 @@
+// I18N constants
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Mihai Bazon, <mishoo@infoiasi.ro>
+// translated into Norwegia: ses@online.no  11.11.03
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+TableOperations.I18N = {
+       "Align":                                                "Juster",
+       "All four sides":                               "Alle fire sider",
+       "Background":                                   "Bakgrund",
+       "Baseline":                     "Grunnlinje",
+       "Border":                                               "Kantlinje",
+       "Borders":                                              "Kantlinjer",
+       "Bottom":                       "Bunn",
+       "CSS Style":                                    "Stil [CSS]",
+       "Caption":                                              "Overskrift",
+       "Cell Properties":              "Celleegenskaper",
+       "Center":                                               "Sentrer",
+       "Char":                         "Tegn",
+       "Collapsed borders":            "Fjern kantlinjer",
+       "Color":                                                "Farge",
+       "Description":                                  "Beskrivelse",
+       "FG Color":                                             "FG farge",
+       "Float":                        "Flytende",
+       "Frames":                                               "rammer",
+       "Height":                       "Høyde",
+       "How many columns would you like to merge?":      "Hvor mange kolonner vil du slå sammen?",
+       "How many rows would you like to merge?":         "Hvor mange rader vil du slå sammen?",
+       "Image URL":                                    "Bildets URL",
+       "Justify":                      "Juster",
+       "Layout":                                               "Layout",
+       "Left":                                                 "Venstre",
+       "Margin":                       "Marg",
+       "Middle":                       "Midten",
+       "No rules":                                             "Ingen linjal",
+       "No sides":                                             "Ingen sider",
+       "None":                         "Ingen",
+       "Padding":                                              "Luft",
+       "Please click into some cell":  "Klikk i en eller annen celle",
+       "Right":                                                "Høyre",
+       "Row Properties":               "Egenskaper for rad",
+       "Rules will appear between all rows and columns": "Linjer vil synes mellom alle rader og kolonner",
+       "Rules will appear between columns only":         "Linjer vil synes kun mellom kolonner",
+       "Rules will appear between rows only":            "Linjer vil synes kun mellom rader",
+       "Rules":                                                "Linjer",
+       "Spacing and padding":          "Luft",
+       "Spacing":                                              "Luft",
+       "Summary":                                              "Sammendrag",
+       "TO-cell-delete":                               "Slett celle",
+       "TO-cell-insert-after":                 "Sett inn celle etter",
+       "TO-cell-insert-before":                "Sett inn celle foran",
+       "TO-cell-merge":                                "Slå sammen celler",
+       "TO-cell-prop":                                 "Egenskaper for celle",
+       "TO-cell-split":                                "Del celle",
+       "TO-col-delete":                                "Slett kolonne",
+       "TO-col-insert-after":                  "Skyt inn kolonne etter",
+       "TO-col-insert-before":                 "Skyt inn kolonne før",
+       "TO-col-split":                                 "Del kolonne",
+       "TO-row-delete":                                "Slett rad",
+       "TO-row-insert-above":                  "Skyt inn rad foran",
+       "TO-row-insert-under":                  "Skyt inn rad etter",
+       "TO-row-prop":                                  "Egenskaper for rad",
+       "TO-row-split":                                 "Del rad",
+       "TO-table-prop":                                "Tabellegenskaper",
+       "Table Properties":                             "Tabellegenskaper",
+       "Text align":                   "Juster tekst",
+       "The bottom side only":                 "Bunnen kun",
+       "The left-hand side only":              "Venstresiden kun",
+       "The right and left sides only":        "Høyre- og venstresiden kun",
+       "The right-hand side only":                     "Høyresiden kun",
+       "The top and bottom sides only":        "The top and bottom sides only",
+       "The top side only":                            "Overkanten kun",
+       "Top":                          "Overkant",     
+       "Unset color":                  "Ikke-bestemt farge",
+       "Vertical align":               "Vertikal justering",
+       "Width":                                                "Bredde",
+       "not-del-last-cell":                    "HTMLArea nekter å slette siste cellen i tabellen.",
+       "not-del-last-col":                             "HTMLArea nekter å slette siste kolonnen i tabellen.",
+       "not-del-last-row":                             "HTMLArea nekter å slette siste raden i tabellen.",
+       "percent":                                              "prosent",
+       "pixels":                                               "billedpunkter"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/ro.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/lang/ro.js
new file mode 100644 (file)
index 0000000..a008f21
--- /dev/null
@@ -0,0 +1,90 @@
+// I18N constants
+
+// LANG: "ro", ENCODING: UTF-8
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+TableOperations.I18N = {
+       "Align":                                          "Aliniere",
+       "All four sides":                                 "Toate părţile",
+       "Background":                                     "Fundal",
+       "Baseline":                                       "Baseline",
+       "Border":                                         "Chenar",
+       "Borders":                                        "Chenare",
+       "Bottom":                                         "Jos",
+       "CSS Style":                                      "Stil [CSS]",
+       "Caption":                                        "Titlu de tabel",
+       "Cell Properties":                                "Proprietăţile celulei",
+       "Center":                                         "Centru",
+       "Char":                                           "Caracter",
+       "Collapsed borders":                              "Chenare asimilate",
+       "Color":                                          "Culoare",
+       "Description":                                    "Descriere",
+       "FG Color":                                       "Culoare text",
+       "Float":                                          "Poziţie",
+       "Frames":                                         "Chenare",
+       "Height":                                         "Înălţimea",
+       "How many columns would you like to merge?":      "Câte coloane vrei să uneşti?",
+       "How many rows would you like to merge?":         "Câte linii vrei să uneşti?",
+       "Image URL":                                      "URL-ul imaginii",
+       "Justify":                                        "Justify",
+       "Layout":                                         "Aranjament",
+       "Left":                                           "Stânga",
+       "Margin":                                         "Margine",
+       "Middle":                                         "Mijloc",
+       "No rules":                                       "Fără linii",
+       "No sides":                                       "Fără părţi",
+       "None":                                           "Nimic",
+       "Padding":                                        "Spaţiere",
+       "Please click into some cell":                    "Vă rog să daţi click într-o celulă",
+       "Right":                                          "Dreapta",
+       "Row Properties":                                 "Proprietăţile liniei",
+       "Rules will appear between all rows and columns": "Vor apărea linii între toate rândurile şi coloanele",
+       "Rules will appear between columns only":         "Vor apărea doar linii verticale",
+       "Rules will appear between rows only":            "Vor apărea doar linii orizontale",
+       "Rules":                                          "Linii",
+       "Spacing and padding":                            "Spaţierea",
+       "Spacing":                                        "Între celule",
+       "Summary":                                        "Sumar",
+       "TO-cell-delete":                                 "Şterge celula",
+       "TO-cell-insert-after":                           "Inserează o celulă la dreapta",
+       "TO-cell-insert-before":                          "Inserează o celulă la stânga",
+       "TO-cell-merge":                                  "Uneşte celulele",
+       "TO-cell-prop":                                   "Proprietăţile celulei",
+       "TO-cell-split":                                  "Împarte celula",
+       "TO-col-delete":                                  "Şterge coloana",
+       "TO-col-insert-after":                            "Inserează o coloană la dreapta",
+       "TO-col-insert-before":                           "Inserează o coloană la stânga",
+       "TO-col-split":                                   "Împarte coloana",
+       "TO-row-delete":                                  "Şterge rândul",
+       "TO-row-insert-above":                            "Inserează un rând înainte",
+       "TO-row-insert-under":                            "Inserează un rând după",
+       "TO-row-prop":                                    "Proprietăţile rândului",
+       "TO-row-split":                                   "Împarte rândul",
+       "TO-table-prop":                                  "Proprietăţile tabelei",
+       "Table Properties":                               "Proprietăţile tabelei",
+       "Text align":                                     "Aliniere",
+       "The bottom side only":                           "Doar partea de jos",
+       "The left-hand side only":                        "Doar partea din stânga",
+       "The right and left sides only":                  "Partea din stânga şi cea din dreapta",
+       "The right-hand side only":                       "Doar partea din dreapta",
+       "The top and bottom sides only":                  "Partea de sus si cea de jos",
+       "The top side only":                              "Doar partea de sus",
+       "Top":                                            "Sus",        
+       "Unset color":                                    "Dezactivează culoarea",
+       "Vertical align":                                 "Aliniere pe verticală",
+       "Width":                                          "Lăţime",
+       "not-del-last-cell":                              "HTMLArea refuză cu laşitate să şteargă ultima celulă din rând.",
+       "not-del-last-col":                               "HTMLArea refuză cu laşitate să şteargă ultima coloamă din tabela.",
+       "not-del-last-row":                               "HTMLArea refuză cu laşitate să şteargă ultimul rând din tabela.",
+       "percent":                                        "procente",
+       "pixels":                                         "pixeli"
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/makefile.xml b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/makefile.xml
new file mode 100644 (file)
index 0000000..cf040f5
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<files>
+  <file name="*.{js,html,cgi,css}" />
+
+  <dir name="lang" />
+  <dir name="img" />
+</files>
+
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/table-operations.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/TableOperations/table-operations.js
new file mode 100644 (file)
index 0000000..05908d6
--- /dev/null
@@ -0,0 +1,1160 @@
+// Table Operations Plugin for HTMLArea-3.0
+// Implementation by Mihai Bazon.  Sponsored by http://www.bloki.com
+//
+// htmlArea v3.0 - Copyright (c) 2002 interactivetools.com, inc.
+// This notice MUST stay intact for use (see license.txt).
+//
+// A free WYSIWYG editor replacement for <textarea> fields.
+// For full source code and docs, visit http://www.interactivetools.com/
+//
+// Version 3.0 developed by Mihai Bazon for InteractiveTools.
+//   http://dynarch.com/mishoo
+//
+// $Id: table-operations.js 30938 2004-07-29 19:08:16Z vgritsenko $
+
+// Object that will encapsulate all the table operations provided by
+// HTMLArea-3.0 (except "insert table" which is included in the main file)
+function TableOperations(editor) {
+       this.editor = editor;
+
+       var cfg = editor.config;
+       var tt = TableOperations.I18N;
+       var bl = TableOperations.btnList;
+       var self = this;
+
+       // register the toolbar buttons provided by this plugin
+       var toolbar = ["linebreak"];
+       for (var i in bl) {
+               var btn = bl[i];
+               if (!btn) {
+                       toolbar.push("separator");
+               } else {
+                       var id = "TO-" + btn[0];
+                       cfg.registerButton(id, tt[id], editor.imgURL(btn[0] + ".gif", "TableOperations"), false,
+                                          function(editor, id) {
+                                                  // dispatch button press event
+                                                  self.buttonPress(editor, id);
+                                          }, btn[1]);
+                       toolbar.push(id);
+               }
+       }
+
+       // add a new line in the toolbar
+       cfg.toolbar.push(toolbar);
+};
+
+TableOperations._pluginInfo = {
+       name          : "TableOperations",
+       version       : "1.0",
+       developer     : "Mihai Bazon",
+       developer_url : "http://dynarch.com/mishoo/",
+       c_owner       : "Mihai Bazon",
+       sponsor       : "Zapatec Inc.",
+       sponsor_url   : "http://www.bloki.com",
+       license       : "htmlArea"
+};
+
+/************************
+ * UTILITIES
+ ************************/
+
+// retrieves the closest element having the specified tagName in the list of
+// ancestors of the current selection/caret.
+TableOperations.prototype.getClosest = function(tagName) {
+       var editor = this.editor;
+       var ancestors = editor.getAllAncestors();
+       var ret = null;
+       tagName = ("" + tagName).toLowerCase();
+       for (var i in ancestors) {
+               var el = ancestors[i];
+               if (el.tagName.toLowerCase() == tagName) {
+                       ret = el;
+                       break;
+               }
+       }
+       return ret;
+};
+
+// this function requires the file PopupDiv/PopupWin to be loaded from browser
+TableOperations.prototype.dialogTableProperties = function() {
+       var i18n = TableOperations.I18N;
+       // retrieve existing values
+       var table = this.getClosest("table");
+       // this.editor.selectNodeContents(table);
+       // this.editor.updateToolbar();
+
+       var dialog = new PopupWin(this.editor, i18n["Table Properties"], function(dialog, params) {
+               TableOperations.processStyle(params, table);
+               for (var i in params) {
+                       var val = params[i];
+                       switch (i) {
+                           case "f_caption":
+                               if (/\S/.test(val)) {
+                                       // contains non white-space characters
+                                       var caption = table.getElementsByTagName("caption")[0];
+                                       if (!caption) {
+                                               caption = dialog.editor._doc.createElement("caption");
+                                               table.insertBefore(caption, table.firstChild);
+                                       }
+                                       caption.innerHTML = val;
+                               } else {
+                                       // search for caption and delete it if found
+                                       var caption = table.getElementsByTagName("caption")[0];
+                                       if (caption) {
+                                               caption.parentNode.removeChild(caption);
+                                       }
+                               }
+                               break;
+                           case "f_summary":
+                               table.summary = val;
+                               break;
+                           case "f_width":
+                               table.style.width = ("" + val) + params.f_unit;
+                               break;
+                           case "f_align":
+                               table.align = val;
+                               break;
+                           case "f_spacing":
+                               table.cellSpacing = val;
+                               break;
+                           case "f_padding":
+                               table.cellPadding = val;
+                               break;
+                           case "f_borders":
+                               table.border = val;
+                               break;
+                           case "f_frames":
+                               table.frame = val;
+                               break;
+                           case "f_rules":
+                               table.rules = val;
+                               break;
+                       }
+               }
+               // various workarounds to refresh the table display (Gecko,
+               // what's going on?! do not disappoint me!)
+               dialog.editor.forceRedraw();
+               dialog.editor.focusEditor();
+               dialog.editor.updateToolbar();
+               var save_collapse = table.style.borderCollapse;
+               table.style.borderCollapse = "collapse";
+               table.style.borderCollapse = "separate";
+               table.style.borderCollapse = save_collapse;
+       },
+
+       // this function gets called when the dialog needs to be initialized
+       function (dialog) {
+
+               var f_caption = "";
+               var capel = table.getElementsByTagName("caption")[0];
+               if (capel) {
+                       f_caption = capel.innerHTML;
+               }
+               var f_summary = table.summary;
+               var f_width = parseInt(table.style.width);
+               isNaN(f_width) && (f_width = "");
+               var f_unit = /%/.test(table.style.width) ? 'percent' : 'pixels';
+               var f_align = table.align;
+               var f_spacing = table.cellSpacing;
+               var f_padding = table.cellPadding;
+               var f_borders = table.border;
+               var f_frames = table.frame;
+               var f_rules = table.rules;
+
+               function selected(val) {
+                       return val ? " selected" : "";
+               };
+
+               // dialog contents
+               dialog.content.style.width = "400px";
+               dialog.content.innerHTML = " \
+<div class='title'\
+ style='background: url(" + dialog.baseURL + dialog.editor.imgURL("table-prop.gif", "TableOperations") + ") #fff 98% 50% no-repeat'>" + i18n["Table Properties"] + "\
+</div> \
+<table style='width:100%'> \
+  <tr> \
+    <td> \
+      <fieldset><legend>" + i18n["Description"] + "</legend> \
+       <table style='width:100%'> \
+        <tr> \
+          <td class='label'>" + i18n["Caption"] + ":</td> \
+          <td class='value'><input type='text' name='f_caption' value='" + f_caption + "'/></td> \
+        </tr><tr> \
+          <td class='label'>" + i18n["Summary"] + ":</td> \
+          <td class='value'><input type='text' name='f_summary' value='" + f_summary + "'/></td> \
+        </tr> \
+       </table> \
+      </fieldset> \
+    </td> \
+  </tr> \
+  <tr><td id='--HA-layout'></td></tr> \
+  <tr> \
+    <td> \
+      <fieldset><legend>" + i18n["Spacing and padding"] + "</legend> \
+       <table style='width:100%'> \
+"+//        <tr> \
+//           <td class='label'>" + i18n["Width"] + ":</td> \
+//           <td><input type='text' name='f_width' value='" + f_width + "' size='5' /> \
+//             <select name='f_unit'> \
+//               <option value='%'" + selected(f_unit == "percent") + ">" + i18n["percent"] + "</option> \
+//               <option value='px'" + selected(f_unit == "pixels") + ">" + i18n["pixels"] + "</option> \
+//             </select> &nbsp;&nbsp;" + i18n["Align"] + ": \
+//             <select name='f_align'> \
+//               <option value='left'" + selected(f_align == "left") + ">" + i18n["Left"] + "</option> \
+//               <option value='center'" + selected(f_align == "center") + ">" + i18n["Center"] + "</option> \
+//               <option value='right'" + selected(f_align == "right") + ">" + i18n["Right"] + "</option> \
+//             </select> \
+//           </td> \
+//         </tr> \
+"        <tr> \
+          <td class='label'>" + i18n["Spacing"] + ":</td> \
+          <td><input type='text' name='f_spacing' size='5' value='" + f_spacing + "' /> &nbsp;" + i18n["Padding"] + ":\
+            <input type='text' name='f_padding' size='5' value='" + f_padding + "' /> &nbsp;&nbsp;" + i18n["pixels"] + "\
+          </td> \
+        </tr> \
+       </table> \
+      </fieldset> \
+    </td> \
+  </tr> \
+  <tr> \
+    <td> \
+      <fieldset><legend>Frame and borders</legend> \
+        <table width='100%'> \
+          <tr> \
+            <td class='label'>" + i18n["Borders"] + ":</td> \
+            <td><input name='f_borders' type='text' size='5' value='" + f_borders + "' /> &nbsp;&nbsp;" + i18n["pixels"] + "</td> \
+          </tr> \
+          <tr> \
+            <td class='label'>" + i18n["Frames"] + ":</td> \
+            <td> \
+              <select name='f_frames'> \
+                <option value='void'" + selected(f_frames == "void") + ">" + i18n["No sides"] + "</option> \
+                <option value='above'" + selected(f_frames == "above") + ">" + i18n["The top side only"] + "</option> \
+                <option value='below'" + selected(f_frames == "below") + ">" + i18n["The bottom side only"] + "</option> \
+                <option value='hsides'" + selected(f_frames == "hsides") + ">" + i18n["The top and bottom sides only"] + "</option> \
+                <option value='vsides'" + selected(f_frames == "vsides") + ">" + i18n["The right and left sides only"] + "</option> \
+                <option value='lhs'" + selected(f_frames == "lhs") + ">" + i18n["The left-hand side only"] + "</option> \
+                <option value='rhs'" + selected(f_frames == "rhs") + ">" + i18n["The right-hand side only"] + "</option> \
+                <option value='box'" + selected(f_frames == "box") + ">" + i18n["All four sides"] + "</option> \
+              </select> \
+            </td> \
+          </tr> \
+          <tr> \
+            <td class='label'>" + i18n["Rules"] + ":</td> \
+            <td> \
+              <select name='f_rules'> \
+                <option value='none'" + selected(f_rules == "none") + ">" + i18n["No rules"] + "</option> \
+                <option value='rows'" + selected(f_rules == "rows") + ">" + i18n["Rules will appear between rows only"] + "</option> \
+                <option value='cols'" + selected(f_rules == "cols") + ">" + i18n["Rules will appear between columns only"] + "</option> \
+                <option value='all'" + selected(f_rules == "all") + ">" + i18n["Rules will appear between all rows and columns"] + "</option> \
+              </select> \
+            </td> \
+          </tr> \
+        </table> \
+      </fieldset> \
+    </td> \
+  </tr> \
+  <tr> \
+    <td id='--HA-style'></td> \
+  </tr> \
+</table> \
+";
+               var st_prop = TableOperations.createStyleFieldset(dialog.doc, dialog.editor, table);
+               var p = dialog.doc.getElementById("--HA-style");
+               p.appendChild(st_prop);
+               var st_layout = TableOperations.createStyleLayoutFieldset(dialog.doc, dialog.editor, table);
+               p = dialog.doc.getElementById("--HA-layout");
+               p.appendChild(st_layout);
+               dialog.modal = true;
+               dialog.addButtons("ok", "cancel");
+               dialog.showAtElement(dialog.editor._iframe, "c");
+       });
+};
+
+// this function requires the file PopupDiv/PopupWin to be loaded from browser
+TableOperations.prototype.dialogRowCellProperties = function(cell) {
+       var i18n = TableOperations.I18N;
+       // retrieve existing values
+       var element = this.getClosest(cell ? "td" : "tr");
+       var table = this.getClosest("table");
+       // this.editor.selectNodeContents(element);
+       // this.editor.updateToolbar();
+
+       var dialog = new PopupWin(this.editor, i18n[cell ? "Cell Properties" : "Row Properties"], function(dialog, params) {
+               TableOperations.processStyle(params, element);
+               for (var i in params) {
+                       var val = params[i];
+                       switch (i) {
+                           case "f_align":
+                               element.align = val;
+                               break;
+                           case "f_char":
+                               element.ch = val;
+                               break;
+                           case "f_valign":
+                               element.vAlign = val;
+                               break;
+                       }
+               }
+               // various workarounds to refresh the table display (Gecko,
+               // what's going on?! do not disappoint me!)
+               dialog.editor.forceRedraw();
+               dialog.editor.focusEditor();
+               dialog.editor.updateToolbar();
+               var save_collapse = table.style.borderCollapse;
+               table.style.borderCollapse = "collapse";
+               table.style.borderCollapse = "separate";
+               table.style.borderCollapse = save_collapse;
+       },
+
+       // this function gets called when the dialog needs to be initialized
+       function (dialog) {
+
+               var f_align = element.align;
+               var f_valign = element.vAlign;
+               var f_char = element.ch;
+
+               function selected(val) {
+                       return val ? " selected" : "";
+               };
+
+               // dialog contents
+               dialog.content.style.width = "400px";
+               dialog.content.innerHTML = " \
+<div class='title'\
+ style='background: url(" + dialog.baseURL + dialog.editor.imgURL(cell ? "cell-prop.gif" : "row-prop.gif", "TableOperations") + ") #fff 98% 50% no-repeat'>" + i18n[cell ? "Cell Properties" : "Row Properties"] + "</div> \
+<table style='width:100%'> \
+  <tr> \
+    <td id='--HA-layout'> \
+"+//      <fieldset><legend>" + i18n["Layout"] + "</legend> \
+//        <table style='width:100%'> \
+//         <tr> \
+//           <td class='label'>" + i18n["Align"] + ":</td> \
+//           <td> \
+//             <select name='f_align'> \
+//               <option value='left'" + selected(f_align == "left") + ">" + i18n["Left"] + "</option> \
+//               <option value='center'" + selected(f_align == "center") + ">" + i18n["Center"] + "</option> \
+//               <option value='right'" + selected(f_align == "right") + ">" + i18n["Right"] + "</option> \
+//               <option value='char'" + selected(f_align == "char") + ">" + i18n["Char"] + "</option> \
+//             </select> \
+//             &nbsp;&nbsp;" + i18n["Char"] + ": \
+//             <input type='text' style='font-family: monospace; text-align: center' name='f_char' size='1' value='" + f_char + "' /> \
+//           </td> \
+//         </tr><tr> \
+//           <td class='label'>" + i18n["Vertical align"] + ":</td> \
+//           <td> \
+//             <select name='f_valign'> \
+//               <option value='top'" + selected(f_valign == "top") + ">" + i18n["Top"] + "</option> \
+//               <option value='middle'" + selected(f_valign == "middle") + ">" + i18n["Middle"] + "</option> \
+//               <option value='bottom'" + selected(f_valign == "bottom") + ">" + i18n["Bottom"] + "</option> \
+//               <option value='baseline'" + selected(f_valign == "baseline") + ">" + i18n["Baseline"] + "</option> \
+//             </select> \
+//           </td> \
+//         </tr> \
+//        </table> \
+//       </fieldset> \
+"    </td> \
+  </tr> \
+  <tr> \
+    <td id='--HA-style'></td> \
+  </tr> \
+</table> \
+";
+               var st_prop = TableOperations.createStyleFieldset(dialog.doc, dialog.editor, element);
+               var p = dialog.doc.getElementById("--HA-style");
+               p.appendChild(st_prop);
+               var st_layout = TableOperations.createStyleLayoutFieldset(dialog.doc, dialog.editor, element);
+               p = dialog.doc.getElementById("--HA-layout");
+               p.appendChild(st_layout);
+               dialog.modal = true;
+               dialog.addButtons("ok", "cancel");
+               dialog.showAtElement(dialog.editor._iframe, "c");
+       });
+};
+
+// this function gets called when some button from the TableOperations toolbar
+// was pressed.
+TableOperations.prototype.buttonPress = function(editor, button_id) {
+       this.editor = editor;
+       var mozbr = HTMLArea.is_gecko ? "<br />" : "";
+       var i18n = TableOperations.I18N;
+
+       // helper function that clears the content in a table row
+       function clearRow(tr) {
+               var tds = tr.getElementsByTagName("td");
+               for (var i = tds.length; --i >= 0;) {
+                       var td = tds[i];
+                       td.rowSpan = 1;
+                       td.innerHTML = mozbr;
+               }
+       };
+
+       function splitRow(td) {
+               var n = parseInt("" + td.rowSpan);
+               var nc = parseInt("" + td.colSpan);
+               td.rowSpan = 1;
+               tr = td.parentNode;
+               var itr = tr.rowIndex;
+               var trs = tr.parentNode.rows;
+               var index = td.cellIndex;
+               while (--n > 0) {
+                       tr = trs[++itr];
+                       var otd = editor._doc.createElement("td");
+                       otd.colSpan = td.colSpan;
+                       otd.innerHTML = mozbr;
+                       tr.insertBefore(otd, tr.cells[index]);
+               }
+               editor.forceRedraw();
+               editor.updateToolbar();
+       };
+
+       function splitCol(td) {
+               var nc = parseInt("" + td.colSpan);
+               td.colSpan = 1;
+               tr = td.parentNode;
+               var ref = td.nextSibling;
+               while (--nc > 0) {
+                       var otd = editor._doc.createElement("td");
+                       otd.rowSpan = td.rowSpan;
+                       otd.innerHTML = mozbr;
+                       tr.insertBefore(otd, ref);
+               }
+               editor.forceRedraw();
+               editor.updateToolbar();
+       };
+
+       function splitCell(td) {
+               var nc = parseInt("" + td.colSpan);
+               splitCol(td);
+               var items = td.parentNode.cells;
+               var index = td.cellIndex;
+               while (nc-- > 0) {
+                       splitRow(items[index++]);
+               }
+       };
+
+       function selectNextNode(el) {
+               var node = el.nextSibling;
+               while (node && node.nodeType != 1) {
+                       node = node.nextSibling;
+               }
+               if (!node) {
+                       node = el.previousSibling;
+                       while (node && node.nodeType != 1) {
+                               node = node.previousSibling;
+                       }
+               }
+               if (!node) {
+                       node = el.parentNode;
+               }
+               editor.selectNodeContents(node);
+       };
+
+       switch (button_id) {
+               // ROWS
+
+           case "TO-row-insert-above":
+           case "TO-row-insert-under":
+               var tr = this.getClosest("tr");
+               if (!tr) {
+                       break;
+               }
+               var otr = tr.cloneNode(true);
+               clearRow(otr);
+               tr.parentNode.insertBefore(otr, /under/.test(button_id) ? tr.nextSibling : tr);
+               editor.forceRedraw();
+               editor.focusEditor();
+               break;
+           case "TO-row-delete":
+               var tr = this.getClosest("tr");
+               if (!tr) {
+                       break;
+               }
+               var par = tr.parentNode;
+               if (par.rows.length == 1) {
+                       alert(i18n["not-del-last-row"]);
+                       break;
+               }
+               // set the caret first to a position that doesn't
+               // disappear.
+               selectNextNode(tr);
+               par.removeChild(tr);
+               editor.forceRedraw();
+               editor.focusEditor();
+               editor.updateToolbar();
+               break;
+           case "TO-row-split":
+               var td = this.getClosest("td");
+               if (!td) {
+                       break;
+               }
+               splitRow(td);
+               break;
+
+               // COLUMNS
+
+           case "TO-col-insert-before":
+           case "TO-col-insert-after":
+               var td = this.getClosest("td");
+               if (!td) {
+                       break;
+               }
+               var rows = td.parentNode.parentNode.rows;
+               var index = td.cellIndex;
+               for (var i = rows.length; --i >= 0;) {
+                       var tr = rows[i];
+                       var ref = tr.cells[index + (/after/.test(button_id) ? 1 : 0)];
+                       var otd = editor._doc.createElement("td");
+                       otd.innerHTML = mozbr;
+                       tr.insertBefore(otd, ref);
+               }
+               editor.focusEditor();
+               break;
+           case "TO-col-split":
+               var td = this.getClosest("td");
+               if (!td) {
+                       break;
+               }
+               splitCol(td);
+               break;
+           case "TO-col-delete":
+               var td = this.getClosest("td");
+               if (!td) {
+                       break;
+               }
+               var index = td.cellIndex;
+               if (td.parentNode.cells.length == 1) {
+                       alert(i18n["not-del-last-col"]);
+                       break;
+               }
+               // set the caret first to a position that doesn't disappear
+               selectNextNode(td);
+               var rows = td.parentNode.parentNode.rows;
+               for (var i = rows.length; --i >= 0;) {
+                       var tr = rows[i];
+                       tr.removeChild(tr.cells[index]);
+               }
+               editor.forceRedraw();
+               editor.focusEditor();
+               editor.updateToolbar();
+               break;
+
+               // CELLS
+
+           case "TO-cell-split":
+               var td = this.getClosest("td");
+               if (!td) {
+                       break;
+               }
+               splitCell(td);
+               break;
+           case "TO-cell-insert-before":
+           case "TO-cell-insert-after":
+               var td = this.getClosest("td");
+               if (!td) {
+                       break;
+               }
+               var tr = td.parentNode;
+               var otd = editor._doc.createElement("td");
+               otd.innerHTML = mozbr;
+               tr.insertBefore(otd, /after/.test(button_id) ? td.nextSibling : td);
+               editor.forceRedraw();
+               editor.focusEditor();
+               break;
+           case "TO-cell-delete":
+               var td = this.getClosest("td");
+               if (!td) {
+                       break;
+               }
+               if (td.parentNode.cells.length == 1) {
+                       alert(i18n["not-del-last-cell"]);
+                       break;
+               }
+               // set the caret first to a position that doesn't disappear
+               selectNextNode(td);
+               td.parentNode.removeChild(td);
+               editor.forceRedraw();
+               editor.updateToolbar();
+               break;
+           case "TO-cell-merge":
+               // !! FIXME: Mozilla specific !!
+               var sel = editor._getSelection();
+               var range, i = 0;
+               var rows = [];
+               var row = null;
+               var cells = null;
+               if (!HTMLArea.is_ie) {
+                       try {
+                               while (range = sel.getRangeAt(i++)) {
+                                       var td = range.startContainer.childNodes[range.startOffset];
+                                       if (td.parentNode != row) {
+                                               row = td.parentNode;
+                                               (cells) && rows.push(cells);
+                                               cells = [];
+                                       }
+                                       cells.push(td);
+                               }
+                       } catch(e) {/* finished walking through selection */}
+                       rows.push(cells);
+               } else {
+                       // Internet Explorer "browser"
+                       var td = this.getClosest("td");
+                       if (!td) {
+                               alert(i18n["Please click into some cell"]);
+                               break;
+                       }
+                       var tr = td.parentElement;
+                       var no_cols = prompt(i18n["How many columns would you like to merge?"], 2);
+                       if (!no_cols) {
+                               // cancelled
+                               break;
+                       }
+                       var no_rows = prompt(i18n["How many rows would you like to merge?"], 2);
+                       if (!no_rows) {
+                               // cancelled
+                               break;
+                       }
+                       var cell_index = td.cellIndex;
+                       while (no_rows-- > 0) {
+                               td = tr.cells[cell_index];
+                               cells = [td];
+                               for (var i = 1; i < no_cols; ++i) {
+                                       td = td.nextSibling;
+                                       if (!td) {
+                                               break;
+                                       }
+                                       cells.push(td);
+                               }
+                               rows.push(cells);
+                               tr = tr.nextSibling;
+                               if (!tr) {
+                                       break;
+                               }
+                       }
+               }
+               var HTML = "";
+               for (i = 0; i < rows.length; ++i) {
+                       // i && (HTML += "<br />");
+                       var cells = rows[i];
+                       for (var j = 0; j < cells.length; ++j) {
+                               // j && (HTML += "&nbsp;");
+                               var cell = cells[j];
+                               HTML += cell.innerHTML;
+                               (i || j) && (cell.parentNode.removeChild(cell));
+                       }
+               }
+               var td = rows[0][0];
+               td.innerHTML = HTML;
+               td.rowSpan = rows.length;
+               td.colSpan = rows[0].length;
+               editor.selectNodeContents(td);
+               editor.forceRedraw();
+               editor.focusEditor();
+               break;
+
+               // PROPERTIES
+
+           case "TO-table-prop":
+               this.dialogTableProperties();
+               break;
+
+           case "TO-row-prop":
+               this.dialogRowCellProperties(false);
+               break;
+
+           case "TO-cell-prop":
+               this.dialogRowCellProperties(true);
+               break;
+
+           default:
+               alert("Button [" + button_id + "] not yet implemented");
+       }
+};
+
+// the list of buttons added by this plugin
+TableOperations.btnList = [
+       // table properties button
+       ["table-prop",       "table"],
+       null,                   // separator
+
+       // ROWS
+       ["row-prop",         "tr"],
+       ["row-insert-above", "tr"],
+       ["row-insert-under", "tr"],
+       ["row-delete",       "tr"],
+       ["row-split",        "td[rowSpan!=1]"],
+       null,
+
+       // COLS
+       ["col-insert-before", "td"],
+       ["col-insert-after",  "td"],
+       ["col-delete",        "td"],
+       ["col-split",         "td[colSpan!=1]"],
+       null,
+
+       // CELLS
+       ["cell-prop",          "td"],
+       ["cell-insert-before", "td"],
+       ["cell-insert-after",  "td"],
+       ["cell-delete",        "td"],
+       ["cell-merge",         "tr"],
+       ["cell-split",         "td[colSpan!=1,rowSpan!=1]"]
+       ];
+
+
+
+//// GENERIC CODE [style of any element; this should be moved into a separate
+//// file as it'll be very useful]
+//// BEGIN GENERIC CODE -----------------------------------------------------
+
+TableOperations.getLength = function(value) {
+       var len = parseInt(value);
+       if (isNaN(len)) {
+               len = "";
+       }
+       return len;
+};
+
+// Applies the style found in "params" to the given element.
+TableOperations.processStyle = function(params, element) {
+       var style = element.style;
+       for (var i in params) {
+               var val = params[i];
+               switch (i) {
+                   case "f_st_backgroundColor":
+                       style.backgroundColor = val;
+                       break;
+                   case "f_st_color":
+                       style.color = val;
+                       break;
+                   case "f_st_backgroundImage":
+                       if (/\S/.test(val)) {
+                               style.backgroundImage = "url(" + val + ")";
+                       } else {
+                               style.backgroundImage = "none";
+                       }
+                       break;
+                   case "f_st_borderWidth":
+                       style.borderWidth = val;
+                       break;
+                   case "f_st_borderStyle":
+                       style.borderStyle = val;
+                       break;
+                   case "f_st_borderColor":
+                       style.borderColor = val;
+                       break;
+                   case "f_st_borderCollapse":
+                       style.borderCollapse = val ? "collapse" : "";
+                       break;
+                   case "f_st_width":
+                       if (/\S/.test(val)) {
+                               style.width = val + params["f_st_widthUnit"];
+                       } else {
+                               style.width = "";
+                       }
+                       break;
+                   case "f_st_height":
+                       if (/\S/.test(val)) {
+                               style.height = val + params["f_st_heightUnit"];
+                       } else {
+                               style.height = "";
+                       }
+                       break;
+                   case "f_st_textAlign":
+                       if (val == "char") {
+                               var ch = params["f_st_textAlignChar"];
+                               if (ch == '"') {
+                                       ch = '\\"';
+                               }
+                               style.textAlign = '"' + ch + '"';
+                       } else {
+                               style.textAlign = val;
+                       }
+                       break;
+                   case "f_st_verticalAlign":
+                       style.verticalAlign = val;
+                       break;
+                   case "f_st_float":
+                       style.cssFloat = val;
+                       break;
+//                 case "f_st_margin":
+//                     style.margin = val + "px";
+//                     break;
+//                 case "f_st_padding":
+//                     style.padding = val + "px";
+//                     break;
+               }
+       }
+};
+
+// Returns an HTML element for a widget that allows color selection.  That is,
+// a button that contains the given color, if any, and when pressed will popup
+// the sooner-or-later-to-be-rewritten select_color.html dialog allowing user
+// to select some color.  If a color is selected, an input field with the name
+// "f_st_"+name will be updated with the color value in #123456 format.
+TableOperations.createColorButton = function(doc, editor, color, name) {
+       if (!color) {
+               color = "";
+       } else if (!/#/.test(color)) {
+               color = HTMLArea._colorToRgb(color);
+       }
+
+       var df = doc.createElement("span");
+       var field = doc.createElement("input");
+       field.type = "hidden";
+       df.appendChild(field);
+       field.name = "f_st_" + name;
+       field.value = color;
+       var button = doc.createElement("span");
+       button.className = "buttonColor";
+       df.appendChild(button);
+       var span = doc.createElement("span");
+       span.className = "chooser";
+       // span.innerHTML = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
+       span.style.backgroundColor = color;
+       button.appendChild(span);
+       button.onmouseover = function() { if (!this.disabled) { this.className += " buttonColor-hilite"; }};
+       button.onmouseout = function() { if (!this.disabled) { this.className = "buttonColor"; }};
+       span.onclick = function() {
+               if (this.parentNode.disabled) {
+                       return false;
+               }
+               editor._popupDialog("select_color.html", function(color) {
+                       if (color) {
+                               span.style.backgroundColor = "#" + color;
+                               field.value = "#" + color;
+                       }
+               }, color);
+       };
+       var span2 = doc.createElement("span");
+       span2.innerHTML = "&#x00d7;";
+       span2.className = "nocolor";
+       span2.title = TableOperations.I18N["Unset color"];
+       button.appendChild(span2);
+       span2.onmouseover = function() { if (!this.parentNode.disabled) { this.className += " nocolor-hilite"; }};
+       span2.onmouseout = function() { if (!this.parentNode.disabled) { this.className = "nocolor"; }};
+       span2.onclick = function() {
+               span.style.backgroundColor = "";
+               field.value = "";
+       };
+       return df;
+};
+
+TableOperations.createStyleLayoutFieldset = function(doc, editor, el) {
+       var i18n = TableOperations.I18N;
+       var fieldset = doc.createElement("fieldset");
+       var legend = doc.createElement("legend");
+       fieldset.appendChild(legend);
+       legend.innerHTML = i18n["Layout"];
+       var table = doc.createElement("table");
+       fieldset.appendChild(table);
+       table.style.width = "100%";
+       var tbody = doc.createElement("tbody");
+       table.appendChild(tbody);
+
+       var tagname = el.tagName.toLowerCase();
+       var tr, td, input, select, option, options, i;
+
+       if (tagname != "td" && tagname != "tr" && tagname != "th") {
+               tr = doc.createElement("tr");
+               tbody.appendChild(tr);
+               td = doc.createElement("td");
+               td.className = "label";
+               tr.appendChild(td);
+               td.innerHTML = i18n["Float"] + ":";
+               td = doc.createElement("td");
+               tr.appendChild(td);
+               select = doc.createElement("select");
+               td.appendChild(select);
+               select.name = "f_st_float";
+               options = ["None", "Left", "Right"];
+               for (i in options) {
+                       var Val = options[i];
+                       var val = options[i].toLowerCase();
+                       option = doc.createElement("option");
+                       option.innerHTML = i18n[Val];
+                       option.value = val;
+                       option.selected = (("" + el.style.cssFloat).toLowerCase() == val);
+                       select.appendChild(option);
+               }
+       }
+
+       tr = doc.createElement("tr");
+       tbody.appendChild(tr);
+       td = doc.createElement("td");
+       td.className = "label";
+       tr.appendChild(td);
+       td.innerHTML = i18n["Width"] + ":";
+       td = doc.createElement("td");
+       tr.appendChild(td);
+       input = doc.createElement("input");
+       input.type = "text";
+       input.value = TableOperations.getLength(el.style.width);
+       input.size = "5";
+       input.name = "f_st_width";
+       input.style.marginRight = "0.5em";
+       td.appendChild(input);
+       select = doc.createElement("select");
+       select.name = "f_st_widthUnit";
+       option = doc.createElement("option");
+       option.innerHTML = i18n["percent"];
+       option.value = "%";
+       option.selected = /%/.test(el.style.width);
+       select.appendChild(option);
+       option = doc.createElement("option");
+       option.innerHTML = i18n["pixels"];
+       option.value = "px";
+       option.selected = /px/.test(el.style.width);
+       select.appendChild(option);
+       td.appendChild(select);
+
+       select.style.marginRight = "0.5em";
+       td.appendChild(doc.createTextNode(i18n["Text align"] + ":"));
+       select = doc.createElement("select");
+       select.style.marginLeft = select.style.marginRight = "0.5em";
+       td.appendChild(select);
+       select.name = "f_st_textAlign";
+       options = ["Left", "Center", "Right", "Justify"];
+       if (tagname == "td") {
+               options.push("Char");
+       }
+       input = doc.createElement("input");
+       input.name = "f_st_textAlignChar";
+       input.size = "1";
+       input.style.fontFamily = "monospace";
+       td.appendChild(input);
+       for (i in options) {
+               var Val = options[i];
+               var val = Val.toLowerCase();
+               option = doc.createElement("option");
+               option.value = val;
+               option.innerHTML = i18n[Val];
+               option.selected = (el.style.textAlign.toLowerCase() == val);
+               select.appendChild(option);
+       }
+       function setCharVisibility(value) {
+               input.style.visibility = value ? "visible" : "hidden";
+               if (value) {
+                       input.focus();
+                       input.select();
+               }
+       };
+       select.onchange = function() { setCharVisibility(this.value == "char"); };
+       setCharVisibility(select.value == "char");
+
+       tr = doc.createElement("tr");
+       tbody.appendChild(tr);
+       td = doc.createElement("td");
+       td.className = "label";
+       tr.appendChild(td);
+       td.innerHTML = i18n["Height"] + ":";
+       td = doc.createElement("td");
+       tr.appendChild(td);
+       input = doc.createElement("input");
+       input.type = "text";
+       input.value = TableOperations.getLength(el.style.height);
+       input.size = "5";
+       input.name = "f_st_height";
+       input.style.marginRight = "0.5em";
+       td.appendChild(input);
+       select = doc.createElement("select");
+       select.name = "f_st_heightUnit";
+       option = doc.createElement("option");
+       option.innerHTML = i18n["percent"];
+       option.value = "%";
+       option.selected = /%/.test(el.style.height);
+       select.appendChild(option);
+       option = doc.createElement("option");
+       option.innerHTML = i18n["pixels"];
+       option.value = "px";
+       option.selected = /px/.test(el.style.height);
+       select.appendChild(option);
+       td.appendChild(select);
+
+       select.style.marginRight = "0.5em";
+       td.appendChild(doc.createTextNode(i18n["Vertical align"] + ":"));
+       select = doc.createElement("select");
+       select.name = "f_st_verticalAlign";
+       select.style.marginLeft = "0.5em";
+       td.appendChild(select);
+       options = ["Top", "Middle", "Bottom", "Baseline"];
+       for (i in options) {
+               var Val = options[i];
+               var val = Val.toLowerCase();
+               option = doc.createElement("option");
+               option.value = val;
+               option.innerHTML = i18n[Val];
+               option.selected = (el.style.verticalAlign.toLowerCase() == val);
+               select.appendChild(option);
+       }
+
+       return fieldset;
+};
+
+// Returns an HTML element containing the style attributes for the given
+// element.  This can be easily embedded into any dialog; the functionality is
+// also provided.
+TableOperations.createStyleFieldset = function(doc, editor, el) {
+       var i18n = TableOperations.I18N;
+       var fieldset = doc.createElement("fieldset");
+       var legend = doc.createElement("legend");
+       fieldset.appendChild(legend);
+       legend.innerHTML = i18n["CSS Style"];
+       var table = doc.createElement("table");
+       fieldset.appendChild(table);
+       table.style.width = "100%";
+       var tbody = doc.createElement("tbody");
+       table.appendChild(tbody);
+
+       var tr, td, input, select, option, options, i;
+
+       tr = doc.createElement("tr");
+       tbody.appendChild(tr);
+       td = doc.createElement("td");
+       tr.appendChild(td);
+       td.className = "label";
+       td.innerHTML = i18n["Background"] + ":";
+       td = doc.createElement("td");
+       tr.appendChild(td);
+       var df = TableOperations.createColorButton(doc, editor, el.style.backgroundColor, "backgroundColor");
+       df.firstChild.nextSibling.style.marginRight = "0.5em";
+       td.appendChild(df);
+       td.appendChild(doc.createTextNode(i18n["Image URL"] + ": "));
+       input = doc.createElement("input");
+       input.type = "text";
+       input.name = "f_st_backgroundImage";
+       if (el.style.backgroundImage.match(/url\(\s*(.*?)\s*\)/)) {
+               input.value = RegExp.$1;
+       }
+       // input.style.width = "100%";
+       td.appendChild(input);
+
+       tr = doc.createElement("tr");
+       tbody.appendChild(tr);
+       td = doc.createElement("td");
+       tr.appendChild(td);
+       td.className = "label";
+       td.innerHTML = i18n["FG Color"] + ":";
+       td = doc.createElement("td");
+       tr.appendChild(td);
+       td.appendChild(TableOperations.createColorButton(doc, editor, el.style.color, "color"));
+
+       // for better alignment we include an invisible field.
+       input = doc.createElement("input");
+       input.style.visibility = "hidden";
+       input.type = "text";
+       td.appendChild(input);
+
+       tr = doc.createElement("tr");
+       tbody.appendChild(tr);
+       td = doc.createElement("td");
+       tr.appendChild(td);
+       td.className = "label";
+       td.innerHTML = i18n["Border"] + ":";
+       td = doc.createElement("td");
+       tr.appendChild(td);
+
+       var colorButton = TableOperations.createColorButton(doc, editor, el.style.borderColor, "borderColor");
+       var btn = colorButton.firstChild.nextSibling;
+       td.appendChild(colorButton);
+       // borderFields.push(btn);
+       btn.style.marginRight = "0.5em";
+
+       select = doc.createElement("select");
+       var borderFields = [];
+       td.appendChild(select);
+       select.name = "f_st_borderStyle";
+       options = ["none", "dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset"];
+       var currentBorderStyle = el.style.borderStyle;
+       // Gecko reports "solid solid solid solid" for "border-style: solid".
+       // That is, "top right bottom left" -- we only consider the first
+       // value.
+       (currentBorderStyle.match(/([^\s]*)\s/)) && (currentBorderStyle = RegExp.$1);
+       for (i in options) {
+               var val = options[i];
+               option = doc.createElement("option");
+               option.value = val;
+               option.innerHTML = val;
+               (val == currentBorderStyle) && (option.selected = true);
+               select.appendChild(option);
+       }
+       select.style.marginRight = "0.5em";
+       function setBorderFieldsStatus(value) {
+               for (i in borderFields) {
+                       var el = borderFields[i];
+                       el.style.visibility = value ? "hidden" : "visible";
+                       if (!value && (el.tagName.toLowerCase() == "input")) {
+                               el.focus();
+                               el.select();
+                       }
+               }
+       };
+       select.onchange = function() { setBorderFieldsStatus(this.value == "none"); };
+
+       input = doc.createElement("input");
+       borderFields.push(input);
+       input.type = "text";
+       input.name = "f_st_borderWidth";
+       input.value = TableOperations.getLength(el.style.borderWidth);
+       input.size = "5";
+       td.appendChild(input);
+       input.style.marginRight = "0.5em";
+       var span = doc.createElement("span");
+       span.innerHTML = i18n["pixels"];
+       td.appendChild(span);
+       borderFields.push(span);
+
+       setBorderFieldsStatus(select.value == "none");
+
+       if (el.tagName.toLowerCase() == "table") {
+               // the border-collapse style is only for tables
+               tr = doc.createElement("tr");
+               tbody.appendChild(tr);
+               td = doc.createElement("td");
+               td.className = "label";
+               tr.appendChild(td);
+               input = doc.createElement("input");
+               input.type = "checkbox";
+               input.name = "f_st_borderCollapse";
+               input.id = "f_st_borderCollapse";
+               var val = (/collapse/i.test(el.style.borderCollapse));
+               input.checked = val ? 1 : 0;
+               td.appendChild(input);
+
+               td = doc.createElement("td");
+               tr.appendChild(td);
+               var label = doc.createElement("label");
+               label.htmlFor = "f_st_borderCollapse";
+               label.innerHTML = i18n["Collapsed borders"];
+               td.appendChild(label);
+       }
+
+//     tr = doc.createElement("tr");
+//     tbody.appendChild(tr);
+//     td = doc.createElement("td");
+//     td.className = "label";
+//     tr.appendChild(td);
+//     td.innerHTML = i18n["Margin"] + ":";
+//     td = doc.createElement("td");
+//     tr.appendChild(td);
+//     input = doc.createElement("input");
+//     input.type = "text";
+//     input.size = "5";
+//     input.name = "f_st_margin";
+//     td.appendChild(input);
+//     input.style.marginRight = "0.5em";
+//     td.appendChild(doc.createTextNode(i18n["Padding"] + ":"));
+
+//     input = doc.createElement("input");
+//     input.type = "text";
+//     input.size = "5";
+//     input.name = "f_st_padding";
+//     td.appendChild(input);
+//     input.style.marginLeft = "0.5em";
+//     input.style.marginRight = "0.5em";
+//     td.appendChild(doc.createTextNode(i18n["pixels"]));
+
+       return fieldset;
+};
+
+//// END GENERIC CODE -------------------------------------------------------
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/makefile.xml b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/plugins/makefile.xml
new file mode 100644 (file)
index 0000000..b1e7693
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<files>
+  <dir name="SpellChecker" />
+  <dir name="TableOperations" />
+  <dir name="FullPage" />
+  <dir name="CSS" />
+  <dir name="ContextMenu" />
+</files>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popupdiv.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popupdiv.js
new file mode 100644 (file)
index 0000000..084ff8e
--- /dev/null
@@ -0,0 +1,369 @@
+/** This file is derived from PopupDiv, developed by Mihai Bazon for
+ * SamWare.net.  Modifications were needed to make it usable in HTMLArea.
+ * HTMLArea is a free WYSIWYG online HTML editor from InteractiveTools.com.
+ *
+ * This file does not function standalone.  It is dependent of global functions
+ * defined in HTMLArea-3.0 (htmlarea.js).
+ *
+ * Please see file htmlarea.js for further details.
+ **/
+
+var is_ie = ( (navigator.userAgent.toLowerCase().indexOf("msie") != -1) &&
+             (navigator.userAgent.toLowerCase().indexOf("opera") == -1) );
+var is_compat = (document.compatMode == "BackCompat");
+
+function PopupDiv(editor, titleText, handler, initFunction) {
+       var self = this;
+
+       this.editor = editor;
+       this.doc = editor._mdoc;
+       this.handler = handler;
+
+       var el = this.doc.createElement("div");
+       el.className = "content";
+
+       var popup = this.doc.createElement("div");
+       popup.className = "dialog popupdiv";
+       this.element = popup;
+       var s = popup.style;
+       s.position = "absolute";
+       s.left = "0px";
+       s.top = "0px";
+
+       var title = this.doc.createElement("div");
+       title.className = "title";
+       this.title = title;
+       popup.appendChild(title);
+
+       HTMLArea._addEvent(title, "mousedown", function(ev) {
+               self._dragStart(is_ie ? window.event : ev);
+       });
+
+       var button = this.doc.createElement("div");
+       button.className = "button";
+       title.appendChild(button);
+       button.innerHTML = "&#x00d7;";
+       title.appendChild(this.doc.createTextNode(titleText));
+       this.titleText = titleText;
+
+       button.onmouseover = function() {
+               this.className += " button-hilite";
+       };
+       button.onmouseout = function() {
+               this.className = this.className.replace(/\s*button-hilite\s*/g, " ");
+       };
+       button.onclick = function() {
+               this.className = this.className.replace(/\s*button-hilite\s*/g, " ");
+               self.close();
+       };
+
+       popup.appendChild(el);
+       this.content = el;
+
+       this.doc.body.appendChild(popup);
+
+       this.dragging = false;
+       this.onShow = null;
+       this.onClose = null;
+       this.modal = false;
+
+       initFunction(this);
+};
+
+PopupDiv.currentPopup = null;
+
+PopupDiv.prototype.showAtElement = function(el, mode) {
+       this.defaultSize();
+       var pos, ew, eh;
+       var popup = this.element;
+       popup.style.display = "block";
+       var w = popup.offsetWidth;
+       var h = popup.offsetHeight;
+       popup.style.display = "none";
+       if (el != window) {
+               pos = PopupDiv.getAbsolutePos(el);
+               ew = el.offsetWidth;
+               eh = el.offsetHeight;
+       } else {
+               pos = {x:0, y:0};
+               var size = PopupDiv.getWindowSize();
+               ew = size.x;
+               eh = size.y;
+       }
+       var FX = false, FY = false;
+       if (mode.indexOf("l") != -1) {
+               pos.x -= w;
+               FX = true;
+       }
+       if (mode.indexOf("r") != -1) {
+               pos.x += ew;
+               FX = true;
+       }
+       if (mode.indexOf("t") != -1) {
+               pos.y -= h;
+               FY = true;
+       }
+       if (mode.indexOf("b") != -1) {
+               pos.y += eh;
+               FY = true;
+       }
+       if (mode.indexOf("c") != -1) {
+               FX || (pos.x += Math.round((ew - w) / 2));
+               FY || (pos.y += Math.round((eh - h) / 2));
+       }
+       this.showAt(pos.x, pos.y);
+};
+
+PopupDiv.prototype.defaultSize = function() {
+       var s = this.element.style;
+       var cs = this.element.currentStyle;
+       var addX = (is_ie && is_compat) ? (parseInt(cs.borderLeftWidth) +
+                                          parseInt(cs.borderRightWidth) +
+                                          parseInt(cs.paddingLeft) +
+                                          parseInt(cs.paddingRight)) : 0;
+       var addY = (is_ie && is_compat) ? (parseInt(cs.borderTopWidth) +
+                                          parseInt(cs.borderBottomWidth) +
+                                          parseInt(cs.paddingTop) +
+                                          parseInt(cs.paddingBottom)) : 0;
+       s.display = "block";
+       s.width = (this.content.offsetWidth + addX) + "px";
+       s.height = (this.content.offsetHeight + this.title.offsetHeight) + "px";
+       s.display = "none";
+};
+
+PopupDiv.prototype.showAt = function(x, y) {
+       this.defaultSize();
+       var s = this.element.style;
+       s.display = "block";
+       s.left = x + "px";
+       s.top = y + "px";
+       this.hideShowCovered();
+
+       PopupDiv.currentPopup = this;
+       HTMLArea._addEvents(this.doc.body, ["mousedown", "click"], PopupDiv.checkPopup);
+       HTMLArea._addEvents(this.editor._doc.body, ["mousedown", "click"], PopupDiv.checkPopup);
+       if (is_ie && this.modal) {
+               this.doc.body.setCapture(false);
+               this.doc.body.onlosecapture = function() {
+                       (PopupDiv.currentPopup) && (this.doc.body.setCapture(false));
+               };
+       }
+       window.event && HTMLArea._stopEvent(window.event);
+
+       if (typeof this.onShow == "function") {
+               this.onShow();
+       } else if (typeof this.onShow == "string") {
+               eval(this.onShow);
+       }
+
+       var field = this.element.getElementsByTagName("input")[0];
+       if (!field) {
+               field = this.element.getElementsByTagName("select")[0];
+       }
+       if (!field) {
+               field = this.element.getElementsByTagName("textarea")[0];
+       }
+       if (field) {
+               field.focus();
+       }
+};
+
+PopupDiv.prototype.close = function() {
+       this.element.style.display = "none";
+       PopupDiv.currentPopup = null;
+       this.hideShowCovered();
+       HTMLArea._removeEvents(this.doc.body, ["mousedown", "click"], PopupDiv.checkPopup);
+       HTMLArea._removeEvents(this.editor._doc.body, ["mousedown", "click"], PopupDiv.checkPopup);
+       is_ie && this.modal && this.doc.body.releaseCapture();
+       if (typeof this.onClose == "function") {
+               this.onClose();
+       } else if (typeof this.onClose == "string") {
+               eval(this.onClose);
+       }
+       this.element.parentNode.removeChild(this.element);
+};
+
+PopupDiv.prototype.getForm = function() {
+       var forms = this.content.getElementsByTagName("form");
+       return (forms.length > 0) ? forms[0] : null;
+};
+
+PopupDiv.prototype.callHandler = function() {
+       var tags = ["input", "textarea", "select"];
+       var params = new Object();
+       for (var ti in tags) {
+               var tag = tags[ti];
+               var els = this.content.getElementsByTagName(tag);
+               for (var j = 0; j < els.length; ++j) {
+                       var el = els[j];
+                       params[el.name] = el.value;
+               }
+       }
+       this.handler(this, params);
+       return false;
+};
+
+PopupDiv.getAbsolutePos = function(el) {
+       var r = { x: el.offsetLeft, y: el.offsetTop };
+       if (el.offsetParent) {
+               var tmp = PopupDiv.getAbsolutePos(el.offsetParent);
+               r.x += tmp.x;
+               r.y += tmp.y;
+       }
+       return r;
+};
+
+PopupDiv.getWindowSize = function() {
+       if (window.innerHeight) {
+               return { y: window.innerHeight, x: window.innerWidth };
+       }
+       if (this.doc.body.clientHeight) {
+               return { y: this.doc.body.clientHeight, x: this.doc.body.clientWidth };
+       }
+       return { y: this.doc.documentElement.clientHeight, x: this.doc.documentElement.clientWidth };
+};
+
+PopupDiv.prototype.hideShowCovered = function () {
+       var self = this;
+       function isContained(el) {
+               while (el) {
+                       if (el == self.element) {
+                               return true;
+                       }
+                       el = el.parentNode;
+               }
+               return false;
+       };
+       var tags = new Array("applet", "select");
+       var el = this.element;
+
+       var p = PopupDiv.getAbsolutePos(el);
+       var EX1 = p.x;
+       var EX2 = el.offsetWidth + EX1;
+       var EY1 = p.y;
+       var EY2 = el.offsetHeight + EY1;
+
+       if (el.style.display == "none") {
+               EX1 = EX2 = EY1 = EY2 = 0;
+       }
+
+       for (var k = tags.length; k > 0; ) {
+               var ar = this.doc.getElementsByTagName(tags[--k]);
+               var cc = null;
+
+               for (var i = ar.length; i > 0;) {
+                       cc = ar[--i];
+                       if (isContained(cc)) {
+                               cc.style.visibility = "visible";
+                               continue;
+                       }
+
+                       p = PopupDiv.getAbsolutePos(cc);
+                       var CX1 = p.x;
+                       var CX2 = cc.offsetWidth + CX1;
+                       var CY1 = p.y;
+                       var CY2 = cc.offsetHeight + CY1;
+
+                       if ((CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) {
+                               cc.style.visibility = "visible";
+                       } else {
+                               cc.style.visibility = "hidden";
+                       }
+               }
+       }
+};
+
+PopupDiv.prototype._dragStart = function (ev) {
+       if (this.dragging) {
+               return false;
+       }
+       this.dragging = true;
+       PopupDiv.currentPopup = this;
+       var posX = ev.clientX;
+       var posY = ev.clientY;
+       if (is_ie) {
+               posY += this.doc.body.scrollTop;
+               posX += this.doc.body.scrollLeft;
+       } else {
+               posY += window.scrollY;
+               posX += window.scrollX;
+       }
+       var st = this.element.style;
+       this.xOffs = posX - parseInt(st.left);
+       this.yOffs = posY - parseInt(st.top);
+       HTMLArea._addEvent(this.doc, "mousemove", PopupDiv.dragIt);
+       HTMLArea._addEvent(this.doc, "mouseover", HTMLArea._stopEvent);
+       HTMLArea._addEvent(this.doc, "mouseup", PopupDiv.dragEnd);
+       HTMLArea._stopEvent(ev);
+};
+
+PopupDiv.dragIt = function (ev) {
+       var popup = PopupDiv.currentPopup;
+       if (!(popup && popup.dragging)) {
+               return false;
+       }
+       is_ie && (ev = window.event);
+       var posX = ev.clientX;
+       var posY = ev.clientY;
+       if (is_ie) {
+               posY += this.doc.body.scrollTop;
+               posX += this.doc.body.scrollLeft;
+       } else {
+               posY += window.scrollY;
+               posX += window.scrollX;
+       }
+       popup.hideShowCovered();
+       var st = popup.element.style;
+       st.left = (posX - popup.xOffs) + "px";
+       st.top = (posY - popup.yOffs) + "px";
+       HTMLArea._stopEvent(ev);
+};
+
+PopupDiv.dragEnd = function () {
+       var popup = PopupDiv.currentPopup;
+       if (!popup) {
+               return false;
+       }
+       popup.dragging = false;
+       HTMLArea._removeEvent(popup.doc, "mouseup", PopupDiv.dragEnd);
+       HTMLArea._removeEvent(popup.doc, "mouseover", HTMLArea._stopEvent);
+       HTMLArea._removeEvent(popup.doc, "mousemove", PopupDiv.dragIt);
+       popup.hideShowCovered();
+};
+
+PopupDiv.checkPopup = function (ev) {
+       is_ie && (ev = window.event);
+       var el = is_ie ? ev.srcElement : ev.target;
+       var cp = PopupDiv.currentPopup;
+       for (; (el != null) && (el != cp.element); el = el.parentNode);
+       if (el == null) {
+               cp.modal || ev.type == "mouseover" || cp.close();
+               HTMLArea._stopEvent(ev);
+       }
+};
+
+PopupDiv.prototype.addButtons = function() {
+       var self = this;
+       var div = this.doc.createElement("div");
+       this.content.appendChild(div);
+       div.className = "buttons";
+       for (var i = 0; i < arguments.length; ++i) {
+               var btn = arguments[i];
+               var button = this.doc.createElement("button");
+               div.appendChild(button);
+               button.innerHTML = HTMLArea.I18N.buttons[btn];
+               switch (btn) {
+                   case "ok":
+                       button.onclick = function() {
+                               self.callHandler();
+                               self.close();
+                       };
+                       break;
+                   case "cancel":
+                       button.onclick = function() {
+                               self.close();
+                       };
+                       break;
+               }
+       }
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/about.html b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/about.html
new file mode 100644 (file)
index 0000000..c23f4d7
--- /dev/null
@@ -0,0 +1,378 @@
+<!--
+
+(c) dynarch.com, 2003-2004
+Author: Mihai Bazon, http://dynarch.com/mishoo
+Distributed as part of HTMLArea 3.0
+
+"You are not expected to understand this...  I don't neither."
+
+                      (from The Linux Kernel Source Code,
+                            ./arch/x86_64/ia32/ptrace.c:90)
+
+;-)
+
+-->
+
+<html style="height: 100%">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>About HTMLArea</title>
+<script type="text/javascript" src="popup.js"></script>
+<script type="text/javascript">
+window.resizeTo(450, 250);
+var TABS = [];
+var CURRENT_TAB = 0;
+var CONTENT_HEIGHT_DIFF = 0;
+var CONTENT_WIDTH_DIFF = 0;
+function selectTab(idx) {
+  var ct = TABS[CURRENT_TAB];
+  ct.className = ct.className.replace(/\s*tab-current\s*/, ' ');
+  ct = TABS[CURRENT_TAB = idx];
+  ct.className += ' tab-current';
+  for (var i = TABS.length; --i >= 0;) {
+    var area = document.getElementById("tab-area-" + i);
+    if (CURRENT_TAB == i) {
+      area.style.display = "block";
+    } else {
+      area.style.display = "none";
+    }
+  }
+  document.body.style.visibility = "hidden";
+  document.body.style.visibility = "visible";
+  document.cookie = "HTMLAREA-ABOUT-TAB=" + idx;
+}
+var editor = null;
+function initDocument() {
+  editor = window.dialogArguments;
+  HTMLArea = window.opener.HTMLArea;
+
+  var plugins = document.getElementById("plugins");
+  var j = 0;
+  var html = "<table width='99%' cellpadding='0' style='margin-top: 1em; collapse-borders: collapse; border: 1px solid #8b8;'>" +
+         "<thead><tr>" +
+         "<td>Name</td>" +
+         "<td>Developer</td>" +
+         "<td>Sponsored by</td>" +
+         "<td>License<sup>*</sup></td>" +
+         "</tr></thead><tbody>";
+  for (var i in editor.plugins) {
+    var info = editor.plugins[i];
+    html += "<tr><td>" + info.name + " v" + info.version + "</td>" + 
+            "<td><a href='" + info.developer_url + "' target='_blank' title='Visit developer website'>" +
+           info.developer + "</a></td>" +
+           "<td><a href='" + info.sponsor_url + "' target='_blank' title='Visit sponsor website'>" +
+           info.sponsor + "</a></td>" +
+           "<td>" + info.license + "</td></tr>";
+    ++j;
+  }
+
+  if (j) {
+          html += "</tbody></table>" +
+                 "<p><sup>*</sup> License \"htmlArea\" means that the plugin is distributed under the same terms " +
+                 "as HTMLArea itself.  Such plugins are likely to be those included in the official " +
+                 "HTMLArea distribution</p>";
+         plugins.innerHTML = "<p>The following plugins have been loaded.</p>" + html;
+  } else {
+         plugins.innerHTML = "<p>No plugins have been loaded</p>";
+  }
+
+  plugins.innerHTML += "<p>User agent reports:<br/>" + navigator.userAgent + "</p>";
+
+  var content = document.getElementById("content");
+  if (window.innerHeight) {
+    CONTENT_HEIGHT_DIFF = window.innerHeight - 250;
+    CONTENT_WIDTH_DIFF = window.innerWidth - content.offsetWidth;
+  } else {
+    CONTENT_HEIGHT_DIFF = document.body.offsetHeight - 250;
+    CONTENT_WIDTH_DIFF = document.body.offsetWidth - 400;
+  }
+  window.onresize();
+  var bar = document.getElementById("tabbar");
+  j = 0;
+  for (var i = bar.firstChild; i; i = i.nextSibling) {
+    TABS.push(i);
+    i.__msh_tab = j;
+    i.onmousedown = function(ev) { selectTab(this.__msh_tab); HTMLArea._stopEvent(ev || window.event); };
+    var area = document.getElementById("tab-area-" + j);
+    if (/tab-current/.test(i.className)) {
+      CURRENT_TAB = j;
+      area.style.display = "block";
+    } else {
+      area.style.display = "none";
+    }
+    ++j;
+  }
+  if (document.cookie.match(/HTMLAREA-ABOUT-TAB=([0-9]+)/))
+    selectTab(RegExp.$1);
+}
+window.onresize = function() {
+  var content = document.getElementById("content");
+  if (window.innerHeight) {
+    content.style.height = (window.innerHeight - CONTENT_HEIGHT_DIFF) + "px";
+    content.style.width = (window.innerWidth - CONTENT_WIDTH_DIFF) + "px";
+  } else {
+    content.style.height = (document.body.offsetHeight - CONTENT_HEIGHT_DIFF) + "px";
+    //content.style.width = (document.body.offsetWidth - CONTENT_WIDTH_DIFF) + "px";
+  }
+}
+</script>
+<style>
+  html,body,textarea,table { font-family: tahoma,verdana,arial; font-size: 11px;
+padding: 0px; margin: 0px; }
+  tt { font-size: 120%; }
+  body { padding: 0px; background: #cea; color: 000; }
+  a:link, a:visited { color: #00f; }
+  a:hover { color: #f00; }
+  a:active { color: #f80; }
+  button { font: 11px tahoma,verdana,sans-serif; background-color: #cea;
+      border-width: 1px; }
+
+  p { margin: 0.5em 0px; }
+
+  h1 { font: bold 130% georgia,"times new roman",serif; margin: 0px; border-bottom: 1px solid #6a6; }
+  h2 { font: bold 110% georgia,"times new roman",serif; margin: 0.7em 0px; }
+
+  thead {
+    font-weight: bold;
+    background-color: #dfb;
+  }
+
+  .logo, .logo-hover {
+    white-space: nowrap;
+    background-color: #8f4; color: #040; padding: 3px; border-bottom: 1px solid #555;
+    height: 5em;
+  }
+  .logo .brand, .logo-hover .brand {
+    margin-left: 0.5em; margin-right: 0.5em; padding-bottom: 0.1em;
+    font-family: impact,'arial black',arial,sans-serif; font-size: 28px;
+    border-bottom: 1px solid #595; text-align: center;
+    cursor: pointer;
+  }
+  .logo-hover {
+    background-color: #fff;
+  }
+  .logo-hover .brand {
+    color: #800;
+    border-color: #04f;
+  }
+  .logo .letter, .logo-hover .letter { position: relative; font-family: monospace; }
+  .logo .letter1 { top: 0.1em; }
+  .logo .letter2 { top: 0.05em; }
+  .logo .letter3 { top: -0.05em; }
+  .logo .letter4 { top: -0.1em; }
+
+  .logo-hover .letter1 { top: -0.1em; }
+  .logo-hover .letter2 { top: -0.05em; }
+  .logo-hover .letter3 { top: 0.05em; }
+  .logo-hover .letter4 { top: 0.1em; }
+  .logo .version, .logo-hover .version { font-family: georgia,"times new roman",serif; }
+  .logo .release {
+    font-size: 90%; margin-bottom: 1em;
+    text-align: center; color: #484;
+  }
+  .logo .visit { display: none; }
+  .logo-hover .release { display: none; }
+  .logo-hover .visit {
+    font-size: 90%; margin-bottom: 1em;
+    text-align: center; color: #448;
+  }
+  .buttons {
+    text-align: right; padding: 3px; background-color: #8f4;
+    border-top: 1px solid #555;
+  }
+  #tabbar {
+    position: relative;
+    left: 10px;
+  }
+  .tab {
+    color: #454;
+    cursor: pointer;
+    margin-left: -5px;
+    float: left; position: relative;
+    border: 1px solid #555;
+    top: -3px; left: -2px;
+    padding: 2px 10px 3px 10px;
+    border-top: none; background-color: #9b7;
+    -moz-border-radius: 0px 0px 4px 4px;
+    z-index: 0;
+  }
+  .tab-current {
+    color: #000;
+    top: -4px;
+    background-color: #cea;
+    padding: 3px 10px 4px 10px;
+    z-index: 10;
+  }
+  table.sponsors { border-top: 1px solid #aca; }
+  table.sponsors td {
+    border-bottom: 1px solid #aca; vertical-align: top;
+  }
+  table.sponsors tr td { padding: 2px 0px; }
+  table.sponsors tr td.sponsor { text-align: right; padding-right: 0.3em; white-space: nowrap; }
+  li, ol, ul { margin-top: 0px; margin-bottom: 0px; }
+</style></head>
+<body onload="__dlg_init(); initDocument();"
+><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;
+      width: 100%; height: 100%;">
+
+<tr style="height: 1em"><td id="tdheader">
+
+<div class="logo">
+<div class="brand"
+onmouseover="this.parentNode.className='logo-hover';"
+onmouseout="this.parentNode.className='logo';"
+onclick="window.open('http://dynarch.com/htmlarea/');">
+<span class="letter letter1">&lt;H</span><span
+class="letter letter2">T</span><span
+class="letter letter3">M</span><span
+class="letter letter4">L</span>Area <span class="letter">/&gt;</span>
+<span class="version">3.0 <span style="position: relative; top: -0.6em; font-size: 50%; font-weight: normal">[ rev. rc1 ]</span></span></div>
+<div class="release">Compiled on Mar  1, 2004 19:37 GMT</div>
+<div class="visit">Go to http://dynarch.com/htmlarea/ [latest milestone release]</div>
+</div>
+
+</td></tr>
+<tr><td id="tdcontent" style="padding: 0.5em;">
+
+<div style="overflow: auto; height: 250px;" id="content">
+<div id="tab-areas">
+
+<div id="tab-area-0">
+
+  <h1>HTMLArea</h1>
+  
+  <p>A free WYSIWYG editor replacement for <tt>&lt;textarea&gt;</tt> fields.<br />
+  For Mozilla 1.3+ (any platform) or Internet Explorer 5.5+ (Windows).
+  </p>
+
+  <p style="text-align: center"
+  >&copy; 2002-2004 <a href="http://interactivetools.com" target="_blank">interactivetools.com</a>, inc.<br />
+  &copy; 2003-2004 <a href="http://dynarch.com" target="_blank">dynarch.com</a> LLC.<br />
+  All Rights Reserved.</p>
+
+  <h2>Project resources</h2>
+
+  <ul>
+  <li><a href="http://sourceforge.net/projects/itools-htmlarea/" target="_blank"
+  >Project page</a> (@ sourceforge.net)</li>
+  <li><a href="http://sourceforge.net/cvs/?group_id=69750" target="_blank"
+  >Anonymous CVS access</a> (@ sourceforge.net)</li>
+  <li><a href="http://sourceforge.net/tracker/?atid=525656&group_id=69750&func=browse" target="_blank"
+  >Bug system</a> (@ sourceforge.net)</li>
+  <li><a href="http://www.interactivetools.com/forum/gforum.cgi?forum=14;" target="_blank"
+  >Forum</a> (@ interactivetools.com)</li>
+  <li><a href="http://www.dynarch.com/htmlarea/" target="_blank"
+  >Last public release</a> (@ dynarch.com)</li>
+  </ul>
+
+  <p>
+  For download section please see the <a href="http://sourceforge.net/projects/itools-htmlarea/" target="_blank"
+  >project page @ SourceForge</a>.
+  </p>
+
+<p style="margin-top: 1em; text-align: center;">Version 3.0 developed and maintained by <a
+href="http://dynarch.com/mishoo/" title="http://dynarch.com/mishoo/" target="_blank">Mihai Bazon</a> / <a
+href="http://dynarch.com" title="http://dynarch.com/" target="_blank">dynarch.com</a></p>
+
+</div>
+
+<div id="tab-area-1">
+<h1>Thank you</h1>
+
+  <p>
+  <a href="http://dynarch.com" target="_blank">dynarch.com</a> would like to thank the following
+  companies/persons for their <em>donations</em> to support development of HTMLArea (listed alphabetically):
+  </p>
+
+  <ul>
+    <li><a href="http://www.neomedia.ro">Neomedia</a> (Romania)</li>
+    <li><a href="http://www.os3.it" target="_blank">OS3</a> (Italy)</li>
+    <li><a href="http://www.softwerk.net">SoftWerk</a> (Italy)</li>
+  </ul>
+
+  <p>Also many thanks to all people at InteractiveTools.com
+  <a href="http://www.interactivetools.com/forum/gforum.cgi?forum=14;">HTMLArea forums</a> for
+  contributing translations, feedback, bug reports and fixes.</p>
+
+  <p>
+  Last but not least, this project wouldn't have existed without
+  <a href="http://interactivetools.com" target="_blank">InteractiveTools.com</a>.
+  </p>
+
+</div>
+
+<div id="tab-area-2">
+<h1>htmlArea License (based on BSD license)</h1>
+
+<p style="text-align: center">© 2002-2004, interactivetools.com, inc.<br />
+  © 2003-2004 dynarch.com LLC<br />
+  All rights reserved.</p>
+
+<p>
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+</p>
+
+<ol>
+<li>
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+</li>
+
+<li>
+Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+</li>
+
+<li>
+Neither the name of interactivetools.com, inc. nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+</li>
+</ol>
+
+<p>
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+</p>
+
+</div>
+
+<div id="tab-area-3">
+<h1>Plugins</h1>
+<div id="plugins">
+</div>
+</div>
+
+</div></div>
+
+
+</tr></td>
+<tr style="height: 1em"><td id="tdfooter">
+
+
+<div class="buttons">
+<div id="tabbar"
+><div class="tab tab-current"
+>About</div><div class="tab"
+>Thanks</div><div class="tab"
+>License</div><div class="tab"
+>Plugins</div></div>
+<button type="button" onclick="__dlg_close(null);">I agree it's cool</button>
+</div>
+
+</td></tr></table>
+
+</body></html>
+
+
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/blank.html b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/blank.html
new file mode 100644 (file)
index 0000000..8c7fe21
--- /dev/null
@@ -0,0 +1,2 @@
+<html>
+</html>
\ No newline at end of file
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/custom2.html b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/custom2.html
new file mode 100644 (file)
index 0000000..5591f6c
--- /dev/null
@@ -0,0 +1,35 @@
+<html style="width:300px; Height: 60px;">
+ <head>
+  <title>Select Phrase</title>
+<script language="javascript">
+
+var myTitle = window.dialogArguments;
+document.title = myTitle;
+
+
+function returnSelected() {
+  var idx  = document.all.textPulldown.selectedIndex;
+  var text = document.all.textPulldown[idx].text;
+
+  window.returnValue = text;          // set return value
+  window.close();                     // close dialog
+}
+
+</script>
+</head>
+<body bgcolor="#FFFFFF" topmargin=15 leftmargin=0>
+
+<form method=get onSubmit="Set(document.all.ColorHex.value); return false;">
+<div align=center>
+
+<select name="textPulldown">
+<option>The quick brown</option>
+<option>fox jumps over</option>
+<option>the lazy dog.</option>
+</select>
+
+<input type="button" value=" Go " onClick="returnSelected()">
+
+</div>
+</form>
+</body></html>
\ No newline at end of file
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/editor_help.html b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/editor_help.html
new file mode 100644 (file)
index 0000000..b34de82
--- /dev/null
@@ -0,0 +1,16 @@
+<html>
+ <head>
+  <title>Editor Help</title>
+  <style>
+    body, td, p, div { font-family: arial; font-size: x-small; }
+  </style>
+ </head>
+<body>
+
+<h2>Editor Help<hr></h2>
+
+Todo...
+
+
+</body>
+</html>
\ No newline at end of file
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/fullscreen.html b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/fullscreen.html
new file mode 100644 (file)
index 0000000..8a9f27f
--- /dev/null
@@ -0,0 +1,133 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html>
+  <head>
+    <title>Fullscreen HTMLArea</title>
+    <script type="text/javascript">
+      _editor_url = window.opener._editor_url;
+      _editor_lang = window.opener._editor_lang;
+      var BASE = window.opener.document.baseURI || window.opener.document.URL;
+      var head = document.getElementsByTagName("head")[0];
+      var base = document.createElement("base");
+      base.href = BASE;
+      head.appendChild(base);
+    </script>
+
+    <script type="text/javascript" src="../htmlarea.js"></script>
+
+    <script type="text/javascript">
+       // load HTMLArea scripts that are present in the opener frame
+       var scripts = window.opener.HTMLArea._scripts;
+       for (var i = 4; i < scripts.length; ++i) {
+           document.write("<scr" + "ipt type='text/javascript' src='" + scripts[i] + "'></scr" + "ipt>");
+        }
+    </script>
+
+    <!-- browser takes a coffee break here -->
+    <script type="text/javascript">
+var parent_object  = null;
+var editor        = null;      // to be initialized later [ function init() ]
+
+/* ---------------------------------------------------------------------- *\
+   Function    : 
+   Description : 
+\* ---------------------------------------------------------------------- */
+
+function _CloseOnEsc(ev) {
+       ev || (ev = window.event);
+       if (ev.keyCode == 27) {
+               // update_parent();
+               window.close();
+               return;
+       }
+}
+
+/* ---------------------------------------------------------------------- *\
+   Function    : resize_editor
+   Description : resize the editor when the user resizes the popup
+\* ---------------------------------------------------------------------- */
+
+function resize_editor() {  // resize editor to fix window
+       var newHeight;
+       if (document.all) {
+               // IE
+               newHeight = document.body.offsetHeight - editor._toolbar.offsetHeight;
+               if (newHeight < 0) { newHeight = 0; }
+       } else {
+               // Gecko
+               newHeight = window.innerHeight - editor._toolbar.offsetHeight;
+       }
+       if (editor.config.statusBar) {
+               newHeight -= editor._statusBar.offsetHeight;
+       }
+       editor._textArea.style.height = editor._iframe.style.height = newHeight + "px";
+}
+
+/* ---------------------------------------------------------------------- *\
+   Function    : init
+   Description : run this code on page load
+\* ---------------------------------------------------------------------- */
+
+function init() {
+       parent_object      = opener.HTMLArea._object;
+       var config         = HTMLArea.cloneObject( parent_object.config );
+       config.width       = "100%";
+       config.height      = "auto";
+
+       // change maximize button to minimize button
+       config.btnList["popupeditor"] = [ 'Minimize Editor', _editor_url + 'images/fullscreen_minimize.gif', true,
+                                         function() { window.close(); } ];
+
+       // generate editor and resize it
+       editor = new HTMLArea("editor", config);
+
+       // register the plugins, if any
+       for (var i in parent_object.plugins) {
+               var plugin = parent_object.plugins[i];
+               editor.registerPlugin2(plugin.name, plugin.args);
+       }
+       // and restore the original toolbar
+        config.toolbar = parent_object.config.toolbar;
+       editor.generate();
+       editor._iframe.style.width = "100%";
+       editor._textArea.style.width = "100%";
+       resize_editor();
+
+       editor.doctype = parent_object.doctype;
+
+       // set child window contents and event handlers, after a small delay
+       setTimeout(function() {
+                          editor.setHTML(parent_object.getInnerHTML());
+
+                          // switch mode if needed
+                          if (parent_object._mode == "textmode") { editor.setMode("textmode"); }
+
+                          // continuously update parent editor window
+                          setInterval(update_parent, 500);
+
+                          // setup event handlers
+                          document.body.onkeypress = _CloseOnEsc;
+                          editor._doc.body.onkeypress = _CloseOnEsc;
+                          editor._textArea.onkeypress = _CloseOnEsc;
+                          window.onresize = resize_editor;
+                  }, 333);                      // give it some time to meet the new frame
+}
+
+/* ---------------------------------------------------------------------- *\
+   Function    : update_parent
+   Description : update parent window editor field with contents from child window
+   \* ---------------------------------------------------------------------- */
+
+function update_parent() {
+       // use the fast version
+       parent_object.setHTML(editor.getInnerHTML());
+}
+
+    </script>
+    <style type="text/css"> html, body { height: 100%; margin: 0px; border: 0px; background-color: buttonface; } </style>
+  </head>
+  <body scroll="no" onload="setTimeout(function(){init();}, 500)" onunload="update_parent()">
+    <form style="margin: 0px; border: 1px solid; border-color: threedshadow threedhighlight threedhighlight threedshadow;">
+      <textarea name="editor" id="editor" style="width:100%; height:300px">&nbsp;</textarea>
+    </form>
+  </body>
+</html>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/insert_image.html b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/insert_image.html
new file mode 100644 (file)
index 0000000..1a0e960
--- /dev/null
@@ -0,0 +1,191 @@
+<html>
+
+<head>
+  <title>Insert Image</title>
+
+<script type="text/javascript" src="popup.js"></script>
+
+<script type="text/javascript">
+
+window.resizeTo(400, 100);
+
+function Init() {
+  __dlg_init();
+  var param = window.dialogArguments;
+  if (param) {
+      document.getElementById("f_url").value = param["f_url"];
+      document.getElementById("f_alt").value = param["f_alt"];
+      document.getElementById("f_border").value = param["f_border"];
+      document.getElementById("f_align").value = param["f_align"];
+      document.getElementById("f_vert").value = param["f_vert"];
+      document.getElementById("f_horiz").value = param["f_horiz"];
+      window.ipreview.location.replace(param.f_url);
+  }
+  document.getElementById("f_url").focus();
+};
+
+function onOK() {
+  var required = {
+    "f_url": "You must enter the URL"
+  };
+  for (var i in required) {
+    var el = document.getElementById(i);
+    if (!el.value) {
+      alert(required[i]);
+      el.focus();
+      return false;
+    }
+  }
+  // pass data back to the calling window
+  var fields = ["f_url", "f_alt", "f_align", "f_border",
+                "f_horiz", "f_vert"];
+  var param = new Object();
+  for (var i in fields) {
+    var id = fields[i];
+    var el = document.getElementById(id);
+    param[id] = el.value;
+  }
+  __dlg_close(param);
+  return false;
+};
+
+function onCancel() {
+  __dlg_close(null);
+  return false;
+};
+
+function onPreview() {
+  var f_url = document.getElementById("f_url");
+  var url = f_url.value;
+  if (!url) {
+    alert("You have to enter an URL first");
+    f_url.focus();
+    return false;
+  }
+  window.ipreview.location.replace(url);
+  return false;
+};
+</script>
+
+<style type="text/css">
+html, body {
+  background: ButtonFace;
+  color: ButtonText;
+  font: 11px Tahoma,Verdana,sans-serif;
+  margin: 0px;
+  padding: 0px;
+}
+body { padding: 5px; }
+table {
+  font: 11px Tahoma,Verdana,sans-serif;
+}
+form p {
+  margin-top: 5px;
+  margin-bottom: 5px;
+}
+.fl { width: 9em; float: left; padding: 2px 5px; text-align: right; }
+.fr { width: 6em; float: left; padding: 2px 5px; text-align: right; }
+fieldset { padding: 0px 10px 5px 5px; }
+select, input, button { font: 11px Tahoma,Verdana,sans-serif; }
+button { width: 70px; }
+.space { padding: 2px; }
+
+.title { background: #ddf; color: #000; font-weight: bold; font-size: 120%; padding: 3px 10px; margin-bottom: 10px;
+border-bottom: 1px solid black; letter-spacing: 2px;
+}
+form { padding: 0px; margin: 0px; }
+</style>
+
+</head>
+
+<body onload="Init()">
+
+<div class="title">Insert Image</div>
+<!--- new stuff --->
+<form action="" method="get">
+<table border="0" width="100%" style="padding: 0px; margin: 0px">
+  <tbody>
+
+  <tr>
+    <td style="width: 7em; text-align: right">Image URL:</td>
+    <td><input type="text" name="url" id="f_url" style="width:75%"
+      title="Enter the image URL here" />
+      <button name="preview" onclick="return onPreview();"
+      title="Preview the image in a new window">Preview</button>
+    </td>
+  </tr>
+  <tr>
+    <td style="width: 7em; text-align: right">Alternate text:</td>
+    <td><input type="text" name="alt" id="f_alt" style="width:100%"
+      title="For browsers that don't support images" /></td>
+  </tr>
+
+  </tbody>
+</table>
+
+<p />
+
+<fieldset style="float: left; margin-left: 5px;">
+<legend>Layout</legend>
+
+<div class="space"></div>
+
+<div class="fl">Alignment:</div>
+<select size="1" name="align" id="f_align"
+  title="Positioning of this image">
+  <option value=""                             >Not set</option>
+  <option value="left"                         >Left</option>
+  <option value="right"                        >Right</option>
+  <option value="texttop"                      >Texttop</option>
+  <option value="absmiddle"                    >Absmiddle</option>
+  <option value="baseline" selected="1"        >Baseline</option>
+  <option value="absbottom"                    >Absbottom</option>
+  <option value="bottom"                       >Bottom</option>
+  <option value="middle"                       >Middle</option>
+  <option value="top"                          >Top</option>
+</select>
+
+<p />
+
+<div class="fl">Border thickness:</div>
+<input type="text" name="border" id="f_border" size="5"
+title="Leave empty for no border" />
+
+<div class="space"></div>
+
+</fieldset>
+
+<fieldset style="float:right; margin-right: 5px;">
+<legend>Spacing</legend>
+
+<div class="space"></div>
+
+<div class="fr">Horizontal:</div>
+<input type="text" name="horiz" id="f_horiz" size="5"
+title="Horizontal padding" />
+
+<p />
+
+<div class="fr">Vertical:</div>
+<input type="text" name="vert" id="f_vert" size="5"
+title="Vertical padding" />
+
+<div class="space"></div>
+
+</fieldset>
+<br clear="all" />
+<table width="100%" style="margin-bottom: 0.2em">
+ <tr>
+  <td valign="bottom">
+    Image Preview:<br />
+    <iframe name="ipreview" id="ipreview" frameborder="0" style="border : 1px solid gray;" height="200" width="300" src=""></iframe>
+  </td>
+  <td valign="bottom" style="text-align: right">
+    <button type="button" name="ok" onclick="return onOK();">OK</button><br>
+    <button type="button" name="cancel" onclick="return onCancel();">Cancel</button>
+  </td>
+ </tr>
+</table>
+</form>
+</body>
+</html>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/insert_table.html b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/insert_table.html
new file mode 100644 (file)
index 0000000..508dbf8
--- /dev/null
@@ -0,0 +1,174 @@
+<html>
+
+<head>
+  <title>Insert Table</title>
+
+<script type="text/javascript" src="popup.js"></script>
+
+<script type="text/javascript">
+
+window.resizeTo(400, 100);
+
+function Init() {
+  __dlg_init();
+  document.getElementById("f_rows").focus();
+};
+
+function onOK() {
+  var required = {
+    "f_rows": "You must enter a number of rows",
+    "f_cols": "You must enter a number of columns"
+  };
+  for (var i in required) {
+    var el = document.getElementById(i);
+    if (!el.value) {
+      alert(required[i]);
+      el.focus();
+      return false;
+    }
+  }
+  var fields = ["f_rows", "f_cols", "f_width", "f_unit",
+                "f_align", "f_border", "f_spacing", "f_padding"];
+  var param = new Object();
+  for (var i in fields) {
+    var id = fields[i];
+    var el = document.getElementById(id);
+    param[id] = el.value;
+  }
+  __dlg_close(param);
+  return false;
+};
+
+function onCancel() {
+  __dlg_close(null);
+  return false;
+};
+
+</script>
+
+<style type="text/css">
+html, body {
+  background: ButtonFace;
+  color: ButtonText;
+  font: 11px Tahoma,Verdana,sans-serif;
+  margin: 0px;
+  padding: 0px;
+}
+body { padding: 5px; }
+table {
+  font: 11px Tahoma,Verdana,sans-serif;
+}
+form p {
+  margin-top: 5px;
+  margin-bottom: 5px;
+}
+.fl { width: 9em; float: left; padding: 2px 5px; text-align: right; }
+.fr { width: 7em; float: left; padding: 2px 5px; text-align: right; }
+fieldset { padding: 0px 10px 5px 5px; }
+select, input, button { font: 11px Tahoma,Verdana,sans-serif; }
+button { width: 70px; }
+.space { padding: 2px; }
+
+.title { background: #ddf; color: #000; font-weight: bold; font-size: 120%; padding: 3px 10px; margin-bottom: 10px;
+border-bottom: 1px solid black; letter-spacing: 2px;
+}
+form { padding: 0px; margin: 0px; }
+</style>
+
+</head>
+
+<body onload="Init()">
+
+<div class="title">Insert Table</div>
+
+<form action="" method="get">
+<table border="0" style="padding: 0px; margin: 0px">
+  <tbody>
+
+  <tr>
+    <td style="width: 4em; text-align: right">Rows:</td>
+    <td><input type="text" name="rows" id="f_rows" size="5" title="Number of rows" value="2" /></td>
+    <td></td>
+    <td></td>
+    <td></td>
+  </tr>
+  <tr>
+    <td style="width: 4em; text-align: right">Cols:</td>
+    <td><input type="text" name="cols" id="f_cols" size="5" title="Number of columns" value="4" /></td>
+    <td style="width: 4em; text-align: right">Width:</td>
+    <td><input type="text" name="width" id="f_width" size="5" title="Width of the table" value="100" /></td>
+    <td><select size="1" name="unit" id="f_unit" title="Width unit">
+      <option value="%" selected="1"  >Percent</option>
+      <option value="px"              >Pixels</option>
+      <option value="em"              >Em</option>
+    </select></td>
+  </tr>
+
+  </tbody>
+</table>
+
+<p />
+
+<fieldset style="float: left; margin-left: 5px;">
+<legend>Layout</legend>
+
+<div class="space"></div>
+
+<div class="fl">Alignment:</div>
+<select size="1" name="align" id="f_align"
+  title="Positioning of this image">
+  <option value="" selected="1"                >Not set</option>
+  <option value="left"                         >Left</option>
+  <option value="right"                        >Right</option>
+  <option value="texttop"                      >Texttop</option>
+  <option value="absmiddle"                    >Absmiddle</option>
+  <option value="baseline"                     >Baseline</option>
+  <option value="absbottom"                    >Absbottom</option>
+  <option value="bottom"                       >Bottom</option>
+  <option value="middle"                       >Middle</option>
+  <option value="top"                          >Top</option>
+</select>
+
+<p />
+
+<div class="fl">Border thickness:</div>
+<input type="text" name="border" id="f_border" size="5" value="1"
+title="Leave empty for no border" />
+<!--
+<p />
+
+<div class="fl">Collapse borders:</div>
+<input type="checkbox" name="collapse" id="f_collapse" />
+-->
+<div class="space"></div>
+
+</fieldset>
+
+<fieldset style="float:right; margin-right: 5px;">
+<legend>Spacing</legend>
+
+<div class="space"></div>
+
+<div class="fr">Cell spacing:</div>
+<input type="text" name="spacing" id="f_spacing" size="5" value="1"
+title="Space between adjacent cells" />
+
+<p />
+
+<div class="fr">Cell padding:</div>
+<input type="text" name="padding" id="f_padding" size="5" value="1"
+title="Space between content and border in cell" />
+
+<div class="space"></div>
+
+</fieldset>
+
+<div style="margin-top: 85px; border-top: 1px solid #999; padding: 2px; text-align: right;">
+<button type="button" name="ok" onclick="return onOK();">OK</button>
+<button type="button" name="cancel" onclick="return onCancel();">Cancel</button>
+</div>
+
+</form>
+
+</body>
+</html>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/link.html b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/link.html
new file mode 100644 (file)
index 0000000..41780e4
--- /dev/null
@@ -0,0 +1,142 @@
+<html>
+
+<head>
+  <title>Insert/Modify Link</title>
+  <script type="text/javascript" src="popup.js"></script>
+  <script type="text/javascript">
+    window.resizeTo(400, 200);
+
+I18N = window.opener.HTMLArea.I18N.dialogs;
+
+function i18n(str) {
+  return (I18N[str] || str);
+};
+
+function onTargetChanged() {
+  var f = document.getElementById("f_other_target");
+  if (this.value == "_other") {
+    f.style.visibility = "visible";
+    f.select();
+    f.focus();
+  } else f.style.visibility = "hidden";
+};
+
+function Init() {
+  __dlg_translate(I18N);
+  __dlg_init();
+  var param = window.dialogArguments;
+  var target_select = document.getElementById("f_target");
+  if (param) {
+      document.getElementById("f_href").value = param["f_href"];
+      document.getElementById("f_title").value = param["f_title"];
+      comboSelectValue(target_select, param["f_target"]);
+      if (target_select.value != param.f_target) {
+        var opt = document.createElement("option");
+        opt.value = param.f_target;
+        opt.innerHTML = opt.value;
+        target_select.appendChild(opt);
+        opt.selected = true;
+      }
+  }
+  var opt = document.createElement("option");
+  opt.value = "_other";
+  opt.innerHTML = i18n("Other");
+  target_select.appendChild(opt);
+  target_select.onchange = onTargetChanged;
+  document.getElementById("f_href").focus();
+  document.getElementById("f_href").select();
+};
+
+function onOK() {
+  var required = {
+    "f_href": i18n("You must enter the URL where this link points to")
+  };
+  for (var i in required) {
+    var el = document.getElementById(i);
+    if (!el.value) {
+      alert(required[i]);
+      el.focus();
+      return false;
+    }
+  }
+  // pass data back to the calling window
+  var fields = ["f_href", "f_title", "f_target" ];
+  var param = new Object();
+  for (var i in fields) {
+    var id = fields[i];
+    var el = document.getElementById(id);
+    param[id] = el.value;
+  }
+  if (param.f_target == "_other")
+    param.f_target = document.getElementById("f_other_target").value;
+  __dlg_close(param);
+  return false;
+};
+
+function onCancel() {
+  __dlg_close(null);
+  return false;
+};
+
+</script>
+
+<style type="text/css">
+html, body {
+  background: ButtonFace;
+  color: ButtonText;
+  font: 11px Tahoma,Verdana,sans-serif;
+  margin: 0px;
+  padding: 0px;
+}
+body { padding: 5px; }
+table {
+  font: 11px Tahoma,Verdana,sans-serif;
+}
+select, input, button { font: 11px Tahoma,Verdana,sans-serif; }
+button { width: 70px; }
+table .label { text-align: right; width: 8em; }
+
+.title { background: #ddf; color: #000; font-weight: bold; font-size: 120%; padding: 3px 10px; margin-bottom: 10px;
+border-bottom: 1px solid black; letter-spacing: 2px;
+}
+
+#buttons {
+      margin-top: 1em; border-top: 1px solid #999;
+      padding: 2px; text-align: right;
+}
+</style>
+
+</head>
+
+<body onload="Init()">
+<div class="title">Insert/Modify Link</div>
+
+<table border="0" style="width: 100%;">
+  <tr>
+    <td class="label">URL:</td>
+    <td><input type="text" id="f_href" style="width: 100%" /></td>
+  </tr>
+  <tr>
+    <td class="label">Title (tooltip):</td>
+    <td><input type="text" id="f_title" style="width: 100%" /></td>
+  </tr>
+  <tr>
+    <td class="label">Target:</td>
+    <td><select id="f_target">
+      <option value="">None (use implicit)</option>
+      <option value="_blank">New window (_blank)</option>
+      <option value="_self">Same frame (_self)</option>
+      <option value="_top">Top frame (_top)</option>
+    </select>
+    <input type="text" name="f_other_target" id="f_other_target" size="10" style="visibility: hidden" />
+    </td>
+  </tr>
+</table>
+
+<div id="buttons">
+  <button type="button" name="ok" onclick="return onOK();">OK</button>
+  <button type="button" name="cancel" onclick="return onCancel();">Cancel</button>
+</div>
+
+</body>
+</html>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/makefile.xml b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/makefile.xml
new file mode 100644 (file)
index 0000000..83bc7fb
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<files>
+  <file name="*.{js,html}" />
+  <file name="about.html" masonize="yes" args="version,release,basename" />
+</files>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/old-fullscreen.html b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/old-fullscreen.html
new file mode 100644 (file)
index 0000000..7c00d91
--- /dev/null
@@ -0,0 +1,131 @@
+<html>
+<head><title>Fullscreen Editor</title>
+<style type="text/css"> body { margin: 0px; border: 0px; background-color: buttonface; } </style>
+
+<script>
+
+// if we pass the "window" object as a argument and then set opener to
+// equal that we can refer to dialogWindows and popupWindows the same way
+if (window.dialogArguments) { opener = window.dialogArguments; }
+
+var _editor_url = "../";
+document.write('<scr'+'ipt src="' +_editor_url+ 'editor.js" language="Javascript1.2"></scr'+'ipt>');
+
+var parent_objname = location.search.substring(1,location.search.length);  // parent editor objname
+var parent_config  = opener.document.all[parent_objname].config;
+
+var config         = cloneObject( parent_config );
+var objname        = 'editor'; // name of this editor
+
+//  DOMViewerObj = config;
+//  DOMViewerName = 'config';
+//  window.open('/innerHTML/domviewer.htm');  
+
+/* ---------------------------------------------------------------------- *\
+  Function    : 
+  Description : 
+\* ---------------------------------------------------------------------- */
+
+function _CloseOnEsc() {
+  if (event.keyCode == 27) {
+    update_parent();
+    window.close();
+    return;
+  }
+}
+
+/* ---------------------------------------------------------------------- *\
+  Function    : cloneObject
+  Description : copy an object by value instead of by reference
+  Usage       : var newObj = cloneObject(oldObj);
+\* ---------------------------------------------------------------------- */
+
+function cloneObject(obj) {
+  var newObj          = new Object; 
+
+  // check for array objects
+  if (obj.constructor.toString().indexOf('function Array(') == 1) {
+    newObj = obj.constructor();
+  }
+
+  for (var n in obj) {
+    var node = obj[n];
+    if (typeof node == 'object') { newObj[n] = cloneObject(node); }
+    else                         { newObj[n] = node; }
+  }
+  
+  return newObj;
+}
+
+/* ---------------------------------------------------------------------- *\
+  Function    : resize_editor
+  Description : resize the editor when the user resizes the popup
+\* ---------------------------------------------------------------------- */
+
+function resize_editor() {  // resize editor to fix window
+  var editor = document.all['_editor_editor'];
+
+  newWidth  = document.body.offsetWidth;
+  newHeight = document.body.offsetHeight - editor.offsetTop;
+
+  if (newWidth < 0) { newWidth = 0; }
+  if (newHeight < 0) { newHeight = 0; }
+
+  editor.style.width  = newWidth;
+  editor.style.height = newHeight;
+}
+
+/* ---------------------------------------------------------------------- *\
+  Function    : init
+  Description : run this code on page load
+\* ---------------------------------------------------------------------- */
+
+function init() {
+  // change maximize button to minimize button
+  config.btnList["popupeditor"] = ['popupeditor', 'Minimize Editor',  'update_parent(); window.close();', 'fullscreen_minimize.gif'];
+
+  // set htmlmode button to refer to THIS editor
+  config.btnList["htmlmode"]    = ['HtmlMode',    'View HTML Source', 'editor_setmode(\'editor\')',  'ed_html.gif'];
+
+  // change image url to be relative to current path
+  config.imgURL = "../images/";
+  
+  // generate editor and resize it
+  editor_generate('editor', config);
+  resize_editor();
+
+  // switch mode if needed
+  if (parent_config.mode == 'textedit') { editor_setmode(objname, 'textedit'); }
+
+  // set child window contents
+  var parentHTML = opener.editor_getHTML(parent_objname);
+  editor_setHTML(objname, parentHTML);
+
+  // continuously update parent editor window
+  window.setInterval(update_parent, 333);
+
+  // setup event handlers
+  document.body.onkeypress = _CloseOnEsc;
+  window.onresize = resize_editor;
+}
+
+/* ---------------------------------------------------------------------- *\
+  Function    : update_parent
+  Description : update parent window editor field with contents from child window
+\* ---------------------------------------------------------------------- */
+
+function update_parent() {
+  var childHTML = editor_getHTML(objname);
+  opener.editor_setHTML(parent_objname, childHTML);
+}
+
+
+</script>
+</head>
+<body scroll="no" onload="init()" onunload="update_parent()">
+
+<div style="margin: 0 0 0 0; border-width: 1; border-style: solid; border-color: threedshadow threedhighlight threedhighlight threedshadow; "></div>
+
+<textarea name="editor" style="width:100%; height:300px"></textarea><br>
+
+</body></html>
\ No newline at end of file
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/old_insert_image.html b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/old_insert_image.html
new file mode 100644 (file)
index 0000000..613f460
--- /dev/null
@@ -0,0 +1,206 @@
+<!-- based on insimage.dlg -->
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD W3 HTML 3.2//EN">
+<HTML  id=dlgImage STYLE="width: 432px; height: 194px; ">
+<HEAD>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<meta http-equiv="MSThemeCompatible" content="Yes">
+<TITLE>Insert Image</TITLE>
+<style>
+  html, body, button, div, input, select, fieldset { font-family: MS Shell Dlg; font-size: 8pt; position: absolute; };
+</style>
+<SCRIPT defer>
+
+function _CloseOnEsc() {
+  if (event.keyCode == 27) { window.close(); return; }
+}
+
+function _getTextRange(elm) {
+  var r = elm.parentTextEdit.createTextRange();
+  r.moveToElementText(elm);
+  return r;
+}
+
+window.onerror = HandleError
+
+function HandleError(message, url, line) {
+  var str = "An error has occurred in this dialog." + "\n\n"
+  + "Error: " + line + "\n" + message;
+  alert(str);
+  window.close();
+  return true;
+}
+
+function Init() {
+  var elmSelectedImage;
+  var htmlSelectionControl = "Control";
+  var globalDoc = window.dialogArguments;
+  var grngMaster = globalDoc.selection.createRange();
+  
+  // event handlers  
+  document.body.onkeypress = _CloseOnEsc;
+  btnOK.onclick = new Function("btnOKClick()");
+
+  txtFileName.fImageLoaded = false;
+  txtFileName.intImageWidth = 0;
+  txtFileName.intImageHeight = 0;
+
+  if (globalDoc.selection.type == htmlSelectionControl) {
+    if (grngMaster.length == 1) {
+      elmSelectedImage = grngMaster.item(0);
+      if (elmSelectedImage.tagName == "IMG") {
+        txtFileName.fImageLoaded = true;
+        if (elmSelectedImage.src) {
+          txtFileName.value          = elmSelectedImage.src.replace(/^[^*]*(\*\*\*)/, "$1");  // fix placeholder src values that editor converted to abs paths
+          txtFileName.intImageHeight = elmSelectedImage.height;
+          txtFileName.intImageWidth  = elmSelectedImage.width;
+          txtVertical.value          = elmSelectedImage.vspace;
+          txtHorizontal.value        = elmSelectedImage.hspace;
+          txtBorder.value            = elmSelectedImage.border;
+          txtAltText.value           = elmSelectedImage.alt;
+          selAlignment.value         = elmSelectedImage.align;
+        }
+      }
+    }
+  }
+  txtFileName.value = txtFileName.value || "http://";
+  txtFileName.focus();
+}
+
+function _isValidNumber(txtBox) {
+  var val = parseInt(txtBox);
+  if (isNaN(val) || val < 0 || val > 999) { return false; }
+  return true;
+}
+
+function btnOKClick() {
+  var elmImage;
+  var intAlignment;
+  var htmlSelectionControl = "Control";
+  var globalDoc = window.dialogArguments;
+  var grngMaster = globalDoc.selection.createRange();
+  
+  // error checking
+
+  if (!txtFileName.value || txtFileName.value == "http://") { 
+    alert("Image URL must be specified.");
+    txtFileName.focus();
+    return;
+  }
+  if (txtHorizontal.value && !_isValidNumber(txtHorizontal.value)) {
+    alert("Horizontal spacing must be a number between 0 and 999.");
+    txtHorizontal.focus();
+    return;
+  }
+  if (txtBorder.value && !_isValidNumber(txtBorder.value)) {
+    alert("Border thickness must be a number between 0 and 999.");
+    txtBorder.focus();
+    return;
+  }
+  if (txtVertical.value && !_isValidNumber(txtVertical.value)) {
+    alert("Vertical spacing must be a number between 0 and 999.");
+    txtVertical.focus();
+    return;
+  }
+
+  // delete selected content and replace with image
+  if (globalDoc.selection.type == htmlSelectionControl && !txtFileName.fImageLoaded) {
+    grngMaster.execCommand('Delete');
+    grngMaster = globalDoc.selection.createRange();
+  }
+    
+  idstr = "\" id=\"556e697175657e537472696e67";     // new image creation ID
+  if (!txtFileName.fImageLoaded) {
+    grngMaster.execCommand("InsertImage", false, idstr);
+    elmImage = globalDoc.all['556e697175657e537472696e67'];
+    elmImage.removeAttribute("id");
+    elmImage.removeAttribute("src");
+    grngMaster.moveStart("character", -1);
+  } else {
+    elmImage = grngMaster.item(0);
+    if (elmImage.src != txtFileName.value) {
+      grngMaster.execCommand('Delete');
+      grngMaster = globalDoc.selection.createRange();
+      grngMaster.execCommand("InsertImage", false, idstr);
+      elmImage = globalDoc.all['556e697175657e537472696e67'];
+      elmImage.removeAttribute("id");
+      elmImage.removeAttribute("src");
+      grngMaster.moveStart("character", -1);
+      txtFileName.fImageLoaded = false;
+    }
+    grngMaster = _getTextRange(elmImage);
+  }
+
+  if (txtFileName.fImageLoaded) {
+    elmImage.style.width = txtFileName.intImageWidth;
+    elmImage.style.height = txtFileName.intImageHeight;
+  }
+
+  if (txtFileName.value.length > 2040) {
+    txtFileName.value = txtFileName.value.substring(0,2040);
+  }
+  
+  elmImage.src = txtFileName.value;
+  
+  if (txtHorizontal.value != "") { elmImage.hspace = parseInt(txtHorizontal.value); }
+  else                           { elmImage.hspace = 0; }
+
+  if (txtVertical.value != "") { elmImage.vspace = parseInt(txtVertical.value); }
+  else                         { elmImage.vspace = 0; }
+  
+  elmImage.alt = txtAltText.value;
+
+  if (txtBorder.value != "") { elmImage.border = parseInt(txtBorder.value); }
+  else                       { elmImage.border = 0; }
+
+  elmImage.align = selAlignment.value;
+  grngMaster.collapse(false);
+  grngMaster.select();
+  window.close();
+}
+</SCRIPT>
+</HEAD>
+<BODY id=bdy onload="Init()" style="background: threedface; color: windowtext;" scroll=no>
+
+<DIV id=divFileName style="left: 0.98em; top: 1.2168em; width: 7em; height: 1.2168em; ">Image URL:</DIV>
+<INPUT ID=txtFileName type=text style="left: 8.54em; top: 1.0647em; width: 21.5em;height: 2.1294em; " tabIndex=10 onfocus="select()">
+
+<DIV id=divAltText style="left: 0.98em; top: 4.1067em; width: 6.58em; height: 1.2168em; ">Alternate Text:</DIV>
+<INPUT type=text ID=txtAltText tabIndex=15 style="left: 8.54em; top: 3.8025em; width: 21.5em; height: 2.1294em; " onfocus="select()">
+
+<FIELDSET id=fldLayout style="left: .9em; top: 7.1em; width: 17.08em; height: 7.6em;">
+<LEGEND id=lgdLayout>Layout</LEGEND>
+</FIELDSET>
+
+<FIELDSET id=fldSpacing style="left: 18.9em; top: 7.1em; width: 11em; height: 7.6em;">
+<LEGEND id=lgdSpacing>Spacing</LEGEND>
+</FIELDSET>
+
+<DIV id=divAlign style="left: 1.82em; top: 9.126em; width: 4.76em; height: 1.2168em; ">Alignment:</DIV>
+<SELECT size=1 ID=selAlignment tabIndex=20 style="left: 10.36em; top: 8.8218em; width: 6.72em; height: 1.2168em; ">
+<OPTION id=optNotSet value=""> Not set </OPTION>
+<OPTION id=optLeft value=left> Left </OPTION>
+<OPTION id=optRight value=right> Right </OPTION>
+<OPTION id=optTexttop value=textTop> Texttop </OPTION>
+<OPTION id=optAbsMiddle value=absMiddle> Absmiddle </OPTION>
+<OPTION id=optBaseline value=baseline SELECTED> Baseline </OPTION>
+<OPTION id=optAbsBottom value=absBottom> Absbottom </OPTION>
+<OPTION id=optBottom value=bottom> Bottom </OPTION>
+<OPTION id=optMiddle value=middle> Middle </OPTION>
+<OPTION id=optTop value=top> Top </OPTION>
+</SELECT>
+
+<DIV id=divHoriz style="left: 19.88em; top: 9.126em; width: 4.76em; height: 1.2168em; ">Horizontal:</DIV>
+<INPUT ID=txtHorizontal style="left: 24.92em; top: 8.8218em; width: 4.2em; height: 2.1294em; ime-mode: disabled;" type=text size=3 maxlength=3 value="" tabIndex=25 onfocus="select()">
+
+<DIV id=divBorder style="left: 1.82em; top: 12.0159em; width: 8.12em; height: 1.2168em; ">Border Thickness:</DIV>
+<INPUT ID=txtBorder style="left: 10.36em; top: 11.5596em; width: 6.72em; height: 2.1294em; ime-mode: disabled;" type=text size=3 maxlength=3 value="" tabIndex=21 onfocus="select()">
+
+<DIV id=divVert style="left: 19.88em; top: 12.0159em; width: 3.64em; height: 1.2168em; ">Vertical:</DIV>
+<INPUT ID=txtVertical style="left: 24.92em; top: 11.5596em; width: 4.2em; height: 2.1294em; ime-mode: disabled;" type=text size=3 maxlength=3 value="" tabIndex=30 onfocus="select()">
+
+<BUTTON ID=btnOK style="left: 31.36em; top: 1.0647em; width: 7em; height: 2.2em; " type=submit tabIndex=40>OK</BUTTON>
+<BUTTON ID=btnCancel style="left: 31.36em; top: 3.6504em; width: 7em; height: 2.2em; " type=reset tabIndex=45 onClick="window.close();">Cancel</BUTTON>
+
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/popup.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/popup.js
new file mode 100644 (file)
index 0000000..ce4517b
--- /dev/null
@@ -0,0 +1,109 @@
+// htmlArea v3.0 - Copyright (c) 2002, 2003 interactivetools.com, inc.
+// This copyright notice MUST stay intact for use (see license.txt).
+//
+// Portions (c) dynarch.com, 2003
+//
+// A free WYSIWYG editor replacement for <textarea> fields.
+// For full source code and docs, visit http://www.interactivetools.com/
+//
+// Version 3.0 developed by Mihai Bazon.
+//   http://dynarch.com/mishoo
+//
+// $Id: popup.js 30938 2004-07-29 19:08:16Z vgritsenko $
+
+function getAbsolutePos(el) {
+       var r = { x: el.offsetLeft, y: el.offsetTop };
+       if (el.offsetParent) {
+               var tmp = getAbsolutePos(el.offsetParent);
+               r.x += tmp.x;
+               r.y += tmp.y;
+       }
+       return r;
+};
+
+function comboSelectValue(c, val) {
+       var ops = c.getElementsByTagName("option");
+       for (var i = ops.length; --i >= 0;) {
+               var op = ops[i];
+               op.selected = (op.value == val);
+       }
+       c.value = val;
+};
+
+function __dlg_onclose() {
+       opener.Dialog._return(null);
+};
+
+function __dlg_init(bottom) {
+       var body = document.body;
+       var body_height = 0;
+       if (typeof bottom == "undefined") {
+               var div = document.createElement("div");
+               body.appendChild(div);
+               var pos = getAbsolutePos(div);
+               body_height = pos.y;
+       } else {
+               var pos = getAbsolutePos(bottom);
+               body_height = pos.y + bottom.offsetHeight;
+       }
+       window.dialogArguments = opener.Dialog._arguments;
+       if (!document.all) {
+               window.sizeToContent();
+               window.sizeToContent(); // for reasons beyond understanding,
+                                       // only if we call it twice we get the
+                                       // correct size.
+               window.addEventListener("unload", __dlg_onclose, true);
+               // center on parent
+               var x = opener.screenX + (opener.outerWidth - window.outerWidth) / 2;
+               var y = opener.screenY + (opener.outerHeight - window.outerHeight) / 2;
+               window.moveTo(x, y);
+               window.innerWidth = body.offsetWidth + 5;
+               window.innerHeight = body_height + 2;
+       } else {
+               // window.dialogHeight = body.offsetHeight + 50 + "px";
+               // window.dialogWidth = body.offsetWidth + "px";
+               window.resizeTo(body.offsetWidth, body_height);
+               var ch = body.clientHeight;
+               var cw = body.clientWidth;
+               window.resizeBy(body.offsetWidth - cw, body_height - ch);
+               var W = body.offsetWidth;
+               var H = 2 * body_height - ch;
+               var x = (screen.availWidth - W) / 2;
+               var y = (screen.availHeight - H) / 2;
+               window.moveTo(x, y);
+       }
+       document.body.onkeypress = __dlg_close_on_esc;
+};
+
+function __dlg_translate(i18n) {
+       var types = ["span", "option", "td", "button", "div"];
+       for (var type in types) {
+               var spans = document.getElementsByTagName(types[type]);
+               for (var i = spans.length; --i >= 0;) {
+                       var span = spans[i];
+                       if (span.firstChild && span.firstChild.data) {
+                               var txt = i18n[span.firstChild.data];
+                               if (txt)
+                                       span.firstChild.data = txt;
+                       }
+               }
+       }
+       var txt = i18n[document.title];
+       if (txt)
+               document.title = txt;
+};
+
+// closes the dialog and passes the return info upper.
+function __dlg_close(val) {
+       opener.Dialog._return(val);
+       window.close();
+};
+
+function __dlg_close_on_esc(ev) {
+       ev || (ev = window.event);
+       if (ev.keyCode == 27) {
+               window.close();
+               return false;
+       }
+       return true;
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/select_color.html b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popups/select_color.html
new file mode 100644 (file)
index 0000000..bc3d779
--- /dev/null
@@ -0,0 +1,347 @@
+<!-- note: this version of the color picker is optimized for IE 5.5+ only -->
+
+<html><head><title>Select Color</title>
+
+<script type="text/javascript" src="popup.js"></script>
+
+<script type="text/javascript">
+
+window.resizeTo(240, 182);
+function _CloseOnEsc() {
+  if (event.keyCode == 27) { window.close(); return; }
+}
+
+function Init() {                                                       // run on page load
+  __dlg_init();    // <!-- this can be found in popup.js -->
+  document.body.onkeypress = _CloseOnEsc;
+
+  var color = window.dialogArguments;
+  color = ValidateColor(color) || '000000';
+  View(color);                                                          // set default color
+}
+
+function View(color) {                  // preview color
+  document.getElementById("ColorPreview").style.backgroundColor = '#' + color;
+  document.getElementById("ColorHex").value = '#' + color;
+}
+
+function Set(string) {                   // select color
+  var color = ValidateColor(string);
+  if (color == null) { alert("Invalid color code: " + string); }        // invalid color
+  else {                                                                // valid color
+    View(color);                          // show selected color
+    __dlg_close(color);
+  }
+}
+
+function ValidateColor(string) {                // return valid color code
+  string = string || '';
+  string = string + "";
+  string = string.toUpperCase();
+  var chars = '0123456789ABCDEF';
+  var out   = '';
+
+  for (var i=0; i<string.length; i++) {             // remove invalid color chars
+    var schar = string.charAt(i);
+    if (chars.indexOf(schar) != -1) { out += schar; }
+  }
+
+  if (out.length != 6) { return null; }            // check length
+  return out;
+}
+
+</script>
+</head>
+<body style="background:ButtonFace; margin:0px; padding:0px" onload="Init()">
+
+<form method="get" style="margin:0px; padding:0px" onSubmit="Set(document.getElementById('ColorHex').value); return false;">
+<table border="0px" cellspacing="0px" cellpadding="4" width="100%">
+ <tr>
+  <td style="background:buttonface" valign=center><div style="background-color: #000000; padding: 1; height: 21px; width: 50px"><div id="ColorPreview" style="height: 100%; width: 100%"></div></div></td>
+  <td style="background:buttonface" valign=center><input type="text" name="ColorHex"
+    id="ColorHex" value="" size=15 style="font-size: 12px"></td>
+  <td style="background:buttonface" width=100%></td>
+ </tr>
+</table>
+</form>
+
+<table border="0" cellspacing="1px" cellpadding="0px" width="100%" bgcolor="#000000" style="cursor: hand;">
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#003300 onMouseOver=View('003300') onClick=Set('003300') height="10px" width="10px"></td>
+<td bgcolor=#006600 onMouseOver=View('006600') onClick=Set('006600') height="10px" width="10px"></td>
+<td bgcolor=#009900 onMouseOver=View('009900') onClick=Set('009900') height="10px" width="10px"></td>
+<td bgcolor=#00CC00 onMouseOver=View('00CC00') onClick=Set('00CC00') height="10px" width="10px"></td>
+<td bgcolor=#00FF00 onMouseOver=View('00FF00') onClick=Set('00FF00') height="10px" width="10px"></td>
+<td bgcolor=#330000 onMouseOver=View('330000') onClick=Set('330000') height="10px" width="10px"></td>
+<td bgcolor=#333300 onMouseOver=View('333300') onClick=Set('333300') height="10px" width="10px"></td>
+<td bgcolor=#336600 onMouseOver=View('336600') onClick=Set('336600') height="10px" width="10px"></td>
+<td bgcolor=#339900 onMouseOver=View('339900') onClick=Set('339900') height="10px" width="10px"></td>
+<td bgcolor=#33CC00 onMouseOver=View('33CC00') onClick=Set('33CC00') height="10px" width="10px"></td>
+<td bgcolor=#33FF00 onMouseOver=View('33FF00') onClick=Set('33FF00') height="10px" width="10px"></td>
+<td bgcolor=#660000 onMouseOver=View('660000') onClick=Set('660000') height="10px" width="10px"></td>
+<td bgcolor=#663300 onMouseOver=View('663300') onClick=Set('663300') height="10px" width="10px"></td>
+<td bgcolor=#666600 onMouseOver=View('666600') onClick=Set('666600') height="10px" width="10px"></td>
+<td bgcolor=#669900 onMouseOver=View('669900') onClick=Set('669900') height="10px" width="10px"></td>
+<td bgcolor=#66CC00 onMouseOver=View('66CC00') onClick=Set('66CC00') height="10px" width="10px"></td>
+<td bgcolor=#66FF00 onMouseOver=View('66FF00') onClick=Set('66FF00') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#333333 onMouseOver=View('333333') onClick=Set('333333') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#000033 onMouseOver=View('000033') onClick=Set('000033') height="10px" width="10px"></td>
+<td bgcolor=#003333 onMouseOver=View('003333') onClick=Set('003333') height="10px" width="10px"></td>
+<td bgcolor=#006633 onMouseOver=View('006633') onClick=Set('006633') height="10px" width="10px"></td>
+<td bgcolor=#009933 onMouseOver=View('009933') onClick=Set('009933') height="10px" width="10px"></td>
+<td bgcolor=#00CC33 onMouseOver=View('00CC33') onClick=Set('00CC33') height="10px" width="10px"></td>
+<td bgcolor=#00FF33 onMouseOver=View('00FF33') onClick=Set('00FF33') height="10px" width="10px"></td>
+<td bgcolor=#330033 onMouseOver=View('330033') onClick=Set('330033') height="10px" width="10px"></td>
+<td bgcolor=#333333 onMouseOver=View('333333') onClick=Set('333333') height="10px" width="10px"></td>
+<td bgcolor=#336633 onMouseOver=View('336633') onClick=Set('336633') height="10px" width="10px"></td>
+<td bgcolor=#339933 onMouseOver=View('339933') onClick=Set('339933') height="10px" width="10px"></td>
+<td bgcolor=#33CC33 onMouseOver=View('33CC33') onClick=Set('33CC33') height="10px" width="10px"></td>
+<td bgcolor=#33FF33 onMouseOver=View('33FF33') onClick=Set('33FF33') height="10px" width="10px"></td>
+<td bgcolor=#660033 onMouseOver=View('660033') onClick=Set('660033') height="10px" width="10px"></td>
+<td bgcolor=#663333 onMouseOver=View('663333') onClick=Set('663333') height="10px" width="10px"></td>
+<td bgcolor=#666633 onMouseOver=View('666633') onClick=Set('666633') height="10px" width="10px"></td>
+<td bgcolor=#669933 onMouseOver=View('669933') onClick=Set('669933') height="10px" width="10px"></td>
+<td bgcolor=#66CC33 onMouseOver=View('66CC33') onClick=Set('66CC33') height="10px" width="10px"></td>
+<td bgcolor=#66FF33 onMouseOver=View('66FF33') onClick=Set('66FF33') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#666666 onMouseOver=View('666666') onClick=Set('666666') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#000066 onMouseOver=View('000066') onClick=Set('000066') height="10px" width="10px"></td>
+<td bgcolor=#003366 onMouseOver=View('003366') onClick=Set('003366') height="10px" width="10px"></td>
+<td bgcolor=#006666 onMouseOver=View('006666') onClick=Set('006666') height="10px" width="10px"></td>
+<td bgcolor=#009966 onMouseOver=View('009966') onClick=Set('009966') height="10px" width="10px"></td>
+<td bgcolor=#00CC66 onMouseOver=View('00CC66') onClick=Set('00CC66') height="10px" width="10px"></td>
+<td bgcolor=#00FF66 onMouseOver=View('00FF66') onClick=Set('00FF66') height="10px" width="10px"></td>
+<td bgcolor=#330066 onMouseOver=View('330066') onClick=Set('330066') height="10px" width="10px"></td>
+<td bgcolor=#333366 onMouseOver=View('333366') onClick=Set('333366') height="10px" width="10px"></td>
+<td bgcolor=#336666 onMouseOver=View('336666') onClick=Set('336666') height="10px" width="10px"></td>
+<td bgcolor=#339966 onMouseOver=View('339966') onClick=Set('339966') height="10px" width="10px"></td>
+<td bgcolor=#33CC66 onMouseOver=View('33CC66') onClick=Set('33CC66') height="10px" width="10px"></td>
+<td bgcolor=#33FF66 onMouseOver=View('33FF66') onClick=Set('33FF66') height="10px" width="10px"></td>
+<td bgcolor=#660066 onMouseOver=View('660066') onClick=Set('660066') height="10px" width="10px"></td>
+<td bgcolor=#663366 onMouseOver=View('663366') onClick=Set('663366') height="10px" width="10px"></td>
+<td bgcolor=#666666 onMouseOver=View('666666') onClick=Set('666666') height="10px" width="10px"></td>
+<td bgcolor=#669966 onMouseOver=View('669966') onClick=Set('669966') height="10px" width="10px"></td>
+<td bgcolor=#66CC66 onMouseOver=View('66CC66') onClick=Set('66CC66') height="10px" width="10px"></td>
+<td bgcolor=#66FF66 onMouseOver=View('66FF66') onClick=Set('66FF66') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#999999 onMouseOver=View('999999') onClick=Set('999999') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#000099 onMouseOver=View('000099') onClick=Set('000099') height="10px" width="10px"></td>
+<td bgcolor=#003399 onMouseOver=View('003399') onClick=Set('003399') height="10px" width="10px"></td>
+<td bgcolor=#006699 onMouseOver=View('006699') onClick=Set('006699') height="10px" width="10px"></td>
+<td bgcolor=#009999 onMouseOver=View('009999') onClick=Set('009999') height="10px" width="10px"></td>
+<td bgcolor=#00CC99 onMouseOver=View('00CC99') onClick=Set('00CC99') height="10px" width="10px"></td>
+<td bgcolor=#00FF99 onMouseOver=View('00FF99') onClick=Set('00FF99') height="10px" width="10px"></td>
+<td bgcolor=#330099 onMouseOver=View('330099') onClick=Set('330099') height="10px" width="10px"></td>
+<td bgcolor=#333399 onMouseOver=View('333399') onClick=Set('333399') height="10px" width="10px"></td>
+<td bgcolor=#336699 onMouseOver=View('336699') onClick=Set('336699') height="10px" width="10px"></td>
+<td bgcolor=#339999 onMouseOver=View('339999') onClick=Set('339999') height="10px" width="10px"></td>
+<td bgcolor=#33CC99 onMouseOver=View('33CC99') onClick=Set('33CC99') height="10px" width="10px"></td>
+<td bgcolor=#33FF99 onMouseOver=View('33FF99') onClick=Set('33FF99') height="10px" width="10px"></td>
+<td bgcolor=#660099 onMouseOver=View('660099') onClick=Set('660099') height="10px" width="10px"></td>
+<td bgcolor=#663399 onMouseOver=View('663399') onClick=Set('663399') height="10px" width="10px"></td>
+<td bgcolor=#666699 onMouseOver=View('666699') onClick=Set('666699') height="10px" width="10px"></td>
+<td bgcolor=#669999 onMouseOver=View('669999') onClick=Set('669999') height="10px" width="10px"></td>
+<td bgcolor=#66CC99 onMouseOver=View('66CC99') onClick=Set('66CC99') height="10px" width="10px"></td>
+<td bgcolor=#66FF99 onMouseOver=View('66FF99') onClick=Set('66FF99') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#CCCCCC onMouseOver=View('CCCCCC') onClick=Set('CCCCCC') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#0000CC onMouseOver=View('0000CC') onClick=Set('0000CC') height="10px" width="10px"></td>
+<td bgcolor=#0033CC onMouseOver=View('0033CC') onClick=Set('0033CC') height="10px" width="10px"></td>
+<td bgcolor=#0066CC onMouseOver=View('0066CC') onClick=Set('0066CC') height="10px" width="10px"></td>
+<td bgcolor=#0099CC onMouseOver=View('0099CC') onClick=Set('0099CC') height="10px" width="10px"></td>
+<td bgcolor=#00CCCC onMouseOver=View('00CCCC') onClick=Set('00CCCC') height="10px" width="10px"></td>
+<td bgcolor=#00FFCC onMouseOver=View('00FFCC') onClick=Set('00FFCC') height="10px" width="10px"></td>
+<td bgcolor=#3300CC onMouseOver=View('3300CC') onClick=Set('3300CC') height="10px" width="10px"></td>
+<td bgcolor=#3333CC onMouseOver=View('3333CC') onClick=Set('3333CC') height="10px" width="10px"></td>
+<td bgcolor=#3366CC onMouseOver=View('3366CC') onClick=Set('3366CC') height="10px" width="10px"></td>
+<td bgcolor=#3399CC onMouseOver=View('3399CC') onClick=Set('3399CC') height="10px" width="10px"></td>
+<td bgcolor=#33CCCC onMouseOver=View('33CCCC') onClick=Set('33CCCC') height="10px" width="10px"></td>
+<td bgcolor=#33FFCC onMouseOver=View('33FFCC') onClick=Set('33FFCC') height="10px" width="10px"></td>
+<td bgcolor=#6600CC onMouseOver=View('6600CC') onClick=Set('6600CC') height="10px" width="10px"></td>
+<td bgcolor=#6633CC onMouseOver=View('6633CC') onClick=Set('6633CC') height="10px" width="10px"></td>
+<td bgcolor=#6666CC onMouseOver=View('6666CC') onClick=Set('6666CC') height="10px" width="10px"></td>
+<td bgcolor=#6699CC onMouseOver=View('6699CC') onClick=Set('6699CC') height="10px" width="10px"></td>
+<td bgcolor=#66CCCC onMouseOver=View('66CCCC') onClick=Set('66CCCC') height="10px" width="10px"></td>
+<td bgcolor=#66FFCC onMouseOver=View('66FFCC') onClick=Set('66FFCC') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#FFFFFF onMouseOver=View('FFFFFF') onClick=Set('FFFFFF') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#0000FF onMouseOver=View('0000FF') onClick=Set('0000FF') height="10px" width="10px"></td>
+<td bgcolor=#0033FF onMouseOver=View('0033FF') onClick=Set('0033FF') height="10px" width="10px"></td>
+<td bgcolor=#0066FF onMouseOver=View('0066FF') onClick=Set('0066FF') height="10px" width="10px"></td>
+<td bgcolor=#0099FF onMouseOver=View('0099FF') onClick=Set('0099FF') height="10px" width="10px"></td>
+<td bgcolor=#00CCFF onMouseOver=View('00CCFF') onClick=Set('00CCFF') height="10px" width="10px"></td>
+<td bgcolor=#00FFFF onMouseOver=View('00FFFF') onClick=Set('00FFFF') height="10px" width="10px"></td>
+<td bgcolor=#3300FF onMouseOver=View('3300FF') onClick=Set('3300FF') height="10px" width="10px"></td>
+<td bgcolor=#3333FF onMouseOver=View('3333FF') onClick=Set('3333FF') height="10px" width="10px"></td>
+<td bgcolor=#3366FF onMouseOver=View('3366FF') onClick=Set('3366FF') height="10px" width="10px"></td>
+<td bgcolor=#3399FF onMouseOver=View('3399FF') onClick=Set('3399FF') height="10px" width="10px"></td>
+<td bgcolor=#33CCFF onMouseOver=View('33CCFF') onClick=Set('33CCFF') height="10px" width="10px"></td>
+<td bgcolor=#33FFFF onMouseOver=View('33FFFF') onClick=Set('33FFFF') height="10px" width="10px"></td>
+<td bgcolor=#6600FF onMouseOver=View('6600FF') onClick=Set('6600FF') height="10px" width="10px"></td>
+<td bgcolor=#6633FF onMouseOver=View('6633FF') onClick=Set('6633FF') height="10px" width="10px"></td>
+<td bgcolor=#6666FF onMouseOver=View('6666FF') onClick=Set('6666FF') height="10px" width="10px"></td>
+<td bgcolor=#6699FF onMouseOver=View('6699FF') onClick=Set('6699FF') height="10px" width="10px"></td>
+<td bgcolor=#66CCFF onMouseOver=View('66CCFF') onClick=Set('66CCFF') height="10px" width="10px"></td>
+<td bgcolor=#66FFFF onMouseOver=View('66FFFF') onClick=Set('66FFFF') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#FF0000 onMouseOver=View('FF0000') onClick=Set('FF0000') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#990000 onMouseOver=View('990000') onClick=Set('990000') height="10px" width="10px"></td>
+<td bgcolor=#993300 onMouseOver=View('993300') onClick=Set('993300') height="10px" width="10px"></td>
+<td bgcolor=#996600 onMouseOver=View('996600') onClick=Set('996600') height="10px" width="10px"></td>
+<td bgcolor=#999900 onMouseOver=View('999900') onClick=Set('999900') height="10px" width="10px"></td>
+<td bgcolor=#99CC00 onMouseOver=View('99CC00') onClick=Set('99CC00') height="10px" width="10px"></td>
+<td bgcolor=#99FF00 onMouseOver=View('99FF00') onClick=Set('99FF00') height="10px" width="10px"></td>
+<td bgcolor=#CC0000 onMouseOver=View('CC0000') onClick=Set('CC0000') height="10px" width="10px"></td>
+<td bgcolor=#CC3300 onMouseOver=View('CC3300') onClick=Set('CC3300') height="10px" width="10px"></td>
+<td bgcolor=#CC6600 onMouseOver=View('CC6600') onClick=Set('CC6600') height="10px" width="10px"></td>
+<td bgcolor=#CC9900 onMouseOver=View('CC9900') onClick=Set('CC9900') height="10px" width="10px"></td>
+<td bgcolor=#CCCC00 onMouseOver=View('CCCC00') onClick=Set('CCCC00') height="10px" width="10px"></td>
+<td bgcolor=#CCFF00 onMouseOver=View('CCFF00') onClick=Set('CCFF00') height="10px" width="10px"></td>
+<td bgcolor=#FF0000 onMouseOver=View('FF0000') onClick=Set('FF0000') height="10px" width="10px"></td>
+<td bgcolor=#FF3300 onMouseOver=View('FF3300') onClick=Set('FF3300') height="10px" width="10px"></td>
+<td bgcolor=#FF6600 onMouseOver=View('FF6600') onClick=Set('FF6600') height="10px" width="10px"></td>
+<td bgcolor=#FF9900 onMouseOver=View('FF9900') onClick=Set('FF9900') height="10px" width="10px"></td>
+<td bgcolor=#FFCC00 onMouseOver=View('FFCC00') onClick=Set('FFCC00') height="10px" width="10px"></td>
+<td bgcolor=#FFFF00 onMouseOver=View('FFFF00') onClick=Set('FFFF00') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#00FF00 onMouseOver=View('00FF00') onClick=Set('00FF00') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#990033 onMouseOver=View('990033') onClick=Set('990033') height="10px" width="10px"></td>
+<td bgcolor=#993333 onMouseOver=View('993333') onClick=Set('993333') height="10px" width="10px"></td>
+<td bgcolor=#996633 onMouseOver=View('996633') onClick=Set('996633') height="10px" width="10px"></td>
+<td bgcolor=#999933 onMouseOver=View('999933') onClick=Set('999933') height="10px" width="10px"></td>
+<td bgcolor=#99CC33 onMouseOver=View('99CC33') onClick=Set('99CC33') height="10px" width="10px"></td>
+<td bgcolor=#99FF33 onMouseOver=View('99FF33') onClick=Set('99FF33') height="10px" width="10px"></td>
+<td bgcolor=#CC0033 onMouseOver=View('CC0033') onClick=Set('CC0033') height="10px" width="10px"></td>
+<td bgcolor=#CC3333 onMouseOver=View('CC3333') onClick=Set('CC3333') height="10px" width="10px"></td>
+<td bgcolor=#CC6633 onMouseOver=View('CC6633') onClick=Set('CC6633') height="10px" width="10px"></td>
+<td bgcolor=#CC9933 onMouseOver=View('CC9933') onClick=Set('CC9933') height="10px" width="10px"></td>
+<td bgcolor=#CCCC33 onMouseOver=View('CCCC33') onClick=Set('CCCC33') height="10px" width="10px"></td>
+<td bgcolor=#CCFF33 onMouseOver=View('CCFF33') onClick=Set('CCFF33') height="10px" width="10px"></td>
+<td bgcolor=#FF0033 onMouseOver=View('FF0033') onClick=Set('FF0033') height="10px" width="10px"></td>
+<td bgcolor=#FF3333 onMouseOver=View('FF3333') onClick=Set('FF3333') height="10px" width="10px"></td>
+<td bgcolor=#FF6633 onMouseOver=View('FF6633') onClick=Set('FF6633') height="10px" width="10px"></td>
+<td bgcolor=#FF9933 onMouseOver=View('FF9933') onClick=Set('FF9933') height="10px" width="10px"></td>
+<td bgcolor=#FFCC33 onMouseOver=View('FFCC33') onClick=Set('FFCC33') height="10px" width="10px"></td>
+<td bgcolor=#FFFF33 onMouseOver=View('FFFF33') onClick=Set('FFFF33') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#0000FF onMouseOver=View('0000FF') onClick=Set('0000FF') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#990066 onMouseOver=View('990066') onClick=Set('990066') height="10px" width="10px"></td>
+<td bgcolor=#993366 onMouseOver=View('993366') onClick=Set('993366') height="10px" width="10px"></td>
+<td bgcolor=#996666 onMouseOver=View('996666') onClick=Set('996666') height="10px" width="10px"></td>
+<td bgcolor=#999966 onMouseOver=View('999966') onClick=Set('999966') height="10px" width="10px"></td>
+<td bgcolor=#99CC66 onMouseOver=View('99CC66') onClick=Set('99CC66') height="10px" width="10px"></td>
+<td bgcolor=#99FF66 onMouseOver=View('99FF66') onClick=Set('99FF66') height="10px" width="10px"></td>
+<td bgcolor=#CC0066 onMouseOver=View('CC0066') onClick=Set('CC0066') height="10px" width="10px"></td>
+<td bgcolor=#CC3366 onMouseOver=View('CC3366') onClick=Set('CC3366') height="10px" width="10px"></td>
+<td bgcolor=#CC6666 onMouseOver=View('CC6666') onClick=Set('CC6666') height="10px" width="10px"></td>
+<td bgcolor=#CC9966 onMouseOver=View('CC9966') onClick=Set('CC9966') height="10px" width="10px"></td>
+<td bgcolor=#CCCC66 onMouseOver=View('CCCC66') onClick=Set('CCCC66') height="10px" width="10px"></td>
+<td bgcolor=#CCFF66 onMouseOver=View('CCFF66') onClick=Set('CCFF66') height="10px" width="10px"></td>
+<td bgcolor=#FF0066 onMouseOver=View('FF0066') onClick=Set('FF0066') height="10px" width="10px"></td>
+<td bgcolor=#FF3366 onMouseOver=View('FF3366') onClick=Set('FF3366') height="10px" width="10px"></td>
+<td bgcolor=#FF6666 onMouseOver=View('FF6666') onClick=Set('FF6666') height="10px" width="10px"></td>
+<td bgcolor=#FF9966 onMouseOver=View('FF9966') onClick=Set('FF9966') height="10px" width="10px"></td>
+<td bgcolor=#FFCC66 onMouseOver=View('FFCC66') onClick=Set('FFCC66') height="10px" width="10px"></td>
+<td bgcolor=#FFFF66 onMouseOver=View('FFFF66') onClick=Set('FFFF66') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#FFFF00 onMouseOver=View('FFFF00') onClick=Set('FFFF00') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#990099 onMouseOver=View('990099') onClick=Set('990099') height="10px" width="10px"></td>
+<td bgcolor=#993399 onMouseOver=View('993399') onClick=Set('993399') height="10px" width="10px"></td>
+<td bgcolor=#996699 onMouseOver=View('996699') onClick=Set('996699') height="10px" width="10px"></td>
+<td bgcolor=#999999 onMouseOver=View('999999') onClick=Set('999999') height="10px" width="10px"></td>
+<td bgcolor=#99CC99 onMouseOver=View('99CC99') onClick=Set('99CC99') height="10px" width="10px"></td>
+<td bgcolor=#99FF99 onMouseOver=View('99FF99') onClick=Set('99FF99') height="10px" width="10px"></td>
+<td bgcolor=#CC0099 onMouseOver=View('CC0099') onClick=Set('CC0099') height="10px" width="10px"></td>
+<td bgcolor=#CC3399 onMouseOver=View('CC3399') onClick=Set('CC3399') height="10px" width="10px"></td>
+<td bgcolor=#CC6699 onMouseOver=View('CC6699') onClick=Set('CC6699') height="10px" width="10px"></td>
+<td bgcolor=#CC9999 onMouseOver=View('CC9999') onClick=Set('CC9999') height="10px" width="10px"></td>
+<td bgcolor=#CCCC99 onMouseOver=View('CCCC99') onClick=Set('CCCC99') height="10px" width="10px"></td>
+<td bgcolor=#CCFF99 onMouseOver=View('CCFF99') onClick=Set('CCFF99') height="10px" width="10px"></td>
+<td bgcolor=#FF0099 onMouseOver=View('FF0099') onClick=Set('FF0099') height="10px" width="10px"></td>
+<td bgcolor=#FF3399 onMouseOver=View('FF3399') onClick=Set('FF3399') height="10px" width="10px"></td>
+<td bgcolor=#FF6699 onMouseOver=View('FF6699') onClick=Set('FF6699') height="10px" width="10px"></td>
+<td bgcolor=#FF9999 onMouseOver=View('FF9999') onClick=Set('FF9999') height="10px" width="10px"></td>
+<td bgcolor=#FFCC99 onMouseOver=View('FFCC99') onClick=Set('FFCC99') height="10px" width="10px"></td>
+<td bgcolor=#FFFF99 onMouseOver=View('FFFF99') onClick=Set('FFFF99') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#00FFFF onMouseOver=View('00FFFF') onClick=Set('00FFFF') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#9900CC onMouseOver=View('9900CC') onClick=Set('9900CC') height="10px" width="10px"></td>
+<td bgcolor=#9933CC onMouseOver=View('9933CC') onClick=Set('9933CC') height="10px" width="10px"></td>
+<td bgcolor=#9966CC onMouseOver=View('9966CC') onClick=Set('9966CC') height="10px" width="10px"></td>
+<td bgcolor=#9999CC onMouseOver=View('9999CC') onClick=Set('9999CC') height="10px" width="10px"></td>
+<td bgcolor=#99CCCC onMouseOver=View('99CCCC') onClick=Set('99CCCC') height="10px" width="10px"></td>
+<td bgcolor=#99FFCC onMouseOver=View('99FFCC') onClick=Set('99FFCC') height="10px" width="10px"></td>
+<td bgcolor=#CC00CC onMouseOver=View('CC00CC') onClick=Set('CC00CC') height="10px" width="10px"></td>
+<td bgcolor=#CC33CC onMouseOver=View('CC33CC') onClick=Set('CC33CC') height="10px" width="10px"></td>
+<td bgcolor=#CC66CC onMouseOver=View('CC66CC') onClick=Set('CC66CC') height="10px" width="10px"></td>
+<td bgcolor=#CC99CC onMouseOver=View('CC99CC') onClick=Set('CC99CC') height="10px" width="10px"></td>
+<td bgcolor=#CCCCCC onMouseOver=View('CCCCCC') onClick=Set('CCCCCC') height="10px" width="10px"></td>
+<td bgcolor=#CCFFCC onMouseOver=View('CCFFCC') onClick=Set('CCFFCC') height="10px" width="10px"></td>
+<td bgcolor=#FF00CC onMouseOver=View('FF00CC') onClick=Set('FF00CC') height="10px" width="10px"></td>
+<td bgcolor=#FF33CC onMouseOver=View('FF33CC') onClick=Set('FF33CC') height="10px" width="10px"></td>
+<td bgcolor=#FF66CC onMouseOver=View('FF66CC') onClick=Set('FF66CC') height="10px" width="10px"></td>
+<td bgcolor=#FF99CC onMouseOver=View('FF99CC') onClick=Set('FF99CC') height="10px" width="10px"></td>
+<td bgcolor=#FFCCCC onMouseOver=View('FFCCCC') onClick=Set('FFCCCC') height="10px" width="10px"></td>
+<td bgcolor=#FFFFCC onMouseOver=View('FFFFCC') onClick=Set('FFFFCC') height="10px" width="10px"></td>
+</tr>
+<tr>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#FF00FF onMouseOver=View('FF00FF') onClick=Set('FF00FF') height="10px" width="10px"></td>
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>
+<td bgcolor=#9900FF onMouseOver=View('9900FF') onClick=Set('9900FF') height="10px" width="10px"></td>
+<td bgcolor=#9933FF onMouseOver=View('9933FF') onClick=Set('9933FF') height="10px" width="10px"></td>
+<td bgcolor=#9966FF onMouseOver=View('9966FF') onClick=Set('9966FF') height="10px" width="10px"></td>
+<td bgcolor=#9999FF onMouseOver=View('9999FF') onClick=Set('9999FF') height="10px" width="10px"></td>
+<td bgcolor=#99CCFF onMouseOver=View('99CCFF') onClick=Set('99CCFF') height="10px" width="10px"></td>
+<td bgcolor=#99FFFF onMouseOver=View('99FFFF') onClick=Set('99FFFF') height="10px" width="10px"></td>
+<td bgcolor=#CC00FF onMouseOver=View('CC00FF') onClick=Set('CC00FF') height="10px" width="10px"></td>
+<td bgcolor=#CC33FF onMouseOver=View('CC33FF') onClick=Set('CC33FF') height="10px" width="10px"></td>
+<td bgcolor=#CC66FF onMouseOver=View('CC66FF') onClick=Set('CC66FF') height="10px" width="10px"></td>
+<td bgcolor=#CC99FF onMouseOver=View('CC99FF') onClick=Set('CC99FF') height="10px" width="10px"></td>
+<td bgcolor=#CCCCFF onMouseOver=View('CCCCFF') onClick=Set('CCCCFF') height="10px" width="10px"></td>
+<td bgcolor=#CCFFFF onMouseOver=View('CCFFFF') onClick=Set('CCFFFF') height="10px" width="10px"></td>
+<td bgcolor=#FF00FF onMouseOver=View('FF00FF') onClick=Set('FF00FF') height="10px" width="10px"></td>
+<td bgcolor=#FF33FF onMouseOver=View('FF33FF') onClick=Set('FF33FF') height="10px" width="10px"></td>
+<td bgcolor=#FF66FF onMouseOver=View('FF66FF') onClick=Set('FF66FF') height="10px" width="10px"></td>
+<td bgcolor=#FF99FF onMouseOver=View('FF99FF') onClick=Set('FF99FF') height="10px" width="10px"></td>
+<td bgcolor=#FFCCFF onMouseOver=View('FFCCFF') onClick=Set('FFCCFF') height="10px" width="10px"></td>
+<td bgcolor=#FFFFFF onMouseOver=View('FFFFFF') onClick=Set('FFFFFF') height="10px" width="10px"></td>
+</tr>
+</table>
+
+</body></html>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popupwin.js b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/popupwin.js
new file mode 100644 (file)
index 0000000..0e0c426
--- /dev/null
@@ -0,0 +1,139 @@
+// (c) dynarch.com 2003-2004
+// Distributed under the same terms as HTMLArea itself.
+
+function PopupWin(editor, title, handler, initFunction) {
+       this.editor = editor;
+       this.handler = handler;
+       var dlg = window.open("", "__ha_dialog",
+                             "toolbar=no,menubar=no,personalbar=no,width=600,height=600,left=20,top=40" +
+                             "scrollbars=no,resizable=no");
+       this.window = dlg;
+       var doc = dlg.document;
+       this.doc = doc;
+       var self = this;
+
+       var base = document.baseURI || document.URL;
+       if (base && base.match(/(.*)\/([^\/]+)/)) {
+               base = RegExp.$1 + "/";
+       }
+       if (typeof _editor_url != "undefined" && !/^\//.test(_editor_url)) {
+               // _editor_url doesn't start with '/' which means it's relative
+               // FIXME: there's a problem here, it could be http:// which
+               // doesn't start with slash but it's not relative either.
+               base += _editor_url;
+       } else
+               base = _editor_url;
+       if (!/\/$/.test(base)) {
+               // base does not end in slash, add it now
+               base += '/';
+       }
+       this.baseURL = base;
+
+       doc.open();
+       var html = "<html><head><title>" + title + "</title>\n";
+       // html += "<base href='" + base + "htmlarea.js' />\n";
+       html += "<style type='text/css'>@import url(" + base + "htmlarea.css);</style></head>\n";
+       html += "<body class='dialog popupwin' id='--HA-body'></body></html>";
+       doc.write(html);
+       doc.close();
+
+       // sometimes I Hate Mozilla... ;-(
+       function init2() {
+               var body = doc.body;
+               if (!body) {
+                       setTimeout(init2, 25);
+                       return false;
+               }
+               dlg.title = title;
+               doc.documentElement.style.padding = "0px";
+               doc.documentElement.style.margin = "0px";
+               var content = doc.createElement("div");
+               content.className = "content";
+               self.content = content;
+               body.appendChild(content);
+               self.element = body;
+               initFunction(self);
+               dlg.focus();
+       };
+       init2();
+};
+
+PopupWin.prototype.callHandler = function() {
+       var tags = ["input", "textarea", "select"];
+       var params = new Object();
+       for (var ti in tags) {
+               var tag = tags[ti];
+               var els = this.content.getElementsByTagName(tag);
+               for (var j = 0; j < els.length; ++j) {
+                       var el = els[j];
+                       var val = el.value;
+                       if (el.tagName.toLowerCase() == "input") {
+                               if (el.type == "checkbox") {
+                                       val = el.checked;
+                               }
+                       }
+                       params[el.name] = val;
+               }
+       }
+       this.handler(this, params);
+       return false;
+};
+
+PopupWin.prototype.close = function() {
+       this.window.close();
+};
+
+PopupWin.prototype.addButtons = function() {
+       var self = this;
+       var div = this.doc.createElement("div");
+       this.content.appendChild(div);
+       div.className = "buttons";
+       for (var i = 0; i < arguments.length; ++i) {
+               var btn = arguments[i];
+               var button = this.doc.createElement("button");
+               div.appendChild(button);
+               button.innerHTML = HTMLArea.I18N.buttons[btn];
+               switch (btn) {
+                   case "ok":
+                       button.onclick = function() {
+                               self.callHandler();
+                               self.close();
+                               return false;
+                       };
+                       break;
+                   case "cancel":
+                       button.onclick = function() {
+                               self.close();
+                               return false;
+                       };
+                       break;
+               }
+       }
+};
+
+PopupWin.prototype.showAtElement = function() {
+       var self = this;
+       // Mozilla needs some time to realize what's goin' on..
+       setTimeout(function() {
+               var w = self.content.offsetWidth + 4;
+               var h = self.content.offsetHeight + 4;
+               // size to content -- that's fuckin' buggy in all fuckin' browsers!!!
+               // so that we set a larger size for the dialog window and then center
+               // the element inside... phuck!
+
+               // center...
+               var el = self.content;
+               var s = el.style;
+               // s.width = el.offsetWidth + "px";
+               // s.height = el.offsetHeight + "px";
+               s.position = "absolute";
+               s.left = (w - el.offsetWidth) / 2 + "px";
+               s.top = (h - el.offsetHeight) / 2 + "px";
+               if (HTMLArea.is_gecko) {
+                       self.window.innerWidth = w;
+                       self.window.innerHeight = h;
+               } else {
+                       self.window.resizeTo(w + 8, h + 35);
+               }
+       }, 25);
+};
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/project-config.xml b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/project-config.xml
new file mode 100644 (file)
index 0000000..7202071
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<project title="HTMLArea">
+  <version>3.0</version>
+  <release>rc1</release>
+</project>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/reference.html b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/reference.html
new file mode 100644 (file)
index 0000000..0760a73
--- /dev/null
@@ -0,0 +1,523 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN">
+<html> <head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>HTMLArea-3.0 Reference</title>
+
+<style type="text/css">
+  @import url(htmlarea.css);
+  body { font: 14px verdana,sans-serif; background: #fff; color: #000; }
+  h1, h2 { font-family:tahoma,sans-serif; }
+  h1 { border-bottom: 2px solid #000; }
+  h2 { border-bottom: 1px solid #aaa; }
+  h3, h4 { margin-bottom: 0px; font-family: Georgia,serif; font-style: italic; }
+  h4 { font-size: 90%; margin-left: 1em; }
+  acronym { border-bottom: 1px dotted #063; color: #063; }
+  p { margin-left: 2em; margin-top: 0.3em; }
+  li p { margin-left: 0px; }
+  .abstract { padding: 5px; margin: 0px 10em; font-size: 90%; border: 1px dashed #aaa; background: #eee;}
+  li { margin-left: 2em; }
+  em { color: #042; }
+  a { color: #00f; }
+  a:hover { color: #f00; }
+  a:active { color: #f80; }
+  span.browser { font-weight: bold; color: #864; }
+  .fixme { font-size: 20px; font-weight: bold; color: red; background: #fab;
+padding: 5px; text-align: center; }
+  .code {
+   background: #e4efff; padding: 5px; border: 1px dashed #abc; margin-left: 2em; margin-right: 2em;
+   font-family: fixed,"lucidux mono","andale mono","courier new",monospace;
+  }
+  .note, .warning { font-weight: bold; color: #0a0; font-variant: small-caps; }
+  .warning { color: #a00; }
+
+.string {
+  color: #06c;
+} /* font-lock-string-face */
+.comment {
+  color: #840;
+} /* font-lock-comment-face */
+.variable-name {
+  color: #000;
+} /* font-lock-variable-name-face */
+.type {
+  color: #008;
+  font-weight: bold;
+} /* font-lock-type-face */
+.reference {
+  color: #048;
+} /* font-lock-reference-face */
+.preprocessor {
+  color: #808;
+} /* font-lock-preprocessor-face */
+.keyword {
+  color: #00f;
+  font-weight: bold;
+} /* font-lock-keyword-face */
+.function-name {
+  color: #044;
+} /* font-lock-function-name-face */
+.html-tag {
+  font-weight: bold;
+} /* html-tag-face */
+.html-helper-italic {
+  font-style: italic;
+} /* html-helper-italic-face */
+.html-helper-bold {
+  font-weight: bold;
+} /* html-helper-bold-face */
+
+</style>
+
+<script type="text/javascript">
+  _editor_url = './';
+  _editor_lang = 'en';
+</script>
+<script type="text/javascript" src="htmlarea.js"></script>
+<script type="text/javascript" src="dialog.js"></script>
+<script tyle="text/javascript" src="lang/en.js"></script>
+
+</head>
+
+<body onload="HTMLArea.replace('TA')">
+
+
+<h1>HTMLArea-3.0 Documentation</h1>
+
+<div class="abstract" style="color: red; font-weight: bold">
+
+      This documentation contains valid information, but is outdated in the
+      terms that it does not covers all the features of HTMLArea.  A new
+      documentation project will be started, based on LaTeX.
+
+</div>
+
+
+<h2>Introduction</h2>
+
+<h3>What is HTMLArea?</h3>
+
+<p>HTMLArea is a free <acronym title="What You See Is What You Get"
+>WYSIWYG</acronym> editor replacement for <code>&lt;textarea&gt;</code>
+fields.  By adding a few simple lines of JavaScript code to your web page
+you can replace a regular textarea with a rich text editor that lets your
+users do the following:</p>
+
+<ul>
+  <li>Format text to be bold, italicized, or underlined.</li>
+  <li>Change the face, size, style and color.</li>
+  <li>Left, center, or right-justify paragraphs.</li>
+  <li>Make bulleted or numbered lists.</li>
+  <li>Indent or un-indent paragraphs.</li>
+  <li>Insert a horizontal line.</li>
+  <li>Insert hyperlinks and images.</li>
+  <li>View the raw HTML source of what they're editing.</li>
+  <li>and much more...</li>
+</ul>
+
+<p>Some of the interesting features of HTMLArea that set's it apart from
+other web based WYSIWYG editors are as follows:</p>
+
+<ul>
+  <li>It's lightweight, fast loading and can transform a regular textarea
+  into a rich-text editor with a single line of JavaScript.</li>
+  <li>Generates clean, valid HTML.</li>
+  <li>It degrades gracefully to older or non-supported browsers
+  (they get the original textarea field).</li>
+  <li>It's free and can be incorporated into any free or commercial
+  program.</li>
+  <li>It works with any server-side languages (ASP, PHP, Perl, Java,
+  etc).</li>
+  <li>It's written in JavaScript and can be easily viewed, modified or
+  extended.</li>
+  <li>It remembers entered content when a user navigates away and then hits
+  "back" in their browser.</li>
+  <li>Since it replaces existing textareas it doesn't require a lot of code
+  to add it to your pages (just one line).</li>
+  <li>Did we mention it was free? ;-)</li>
+</ul>
+
+<h3>Is it really free?  What's the catch?</h3>
+
+<p>Yes! It's really free. You can use it, modify it, distribute it with your
+software, or do just about anything you like with it.</p>
+
+<h3>What are the browser requirements?</h3>
+
+<p>HTMLArea requires <span class="browser"><a
+href="http://www.microsoft.com/ie">Internet Explorer</a> &gt;= 5.5</span>
+(Windows only), or <span class="browser"><a
+href="http://mozilla.org">Mozilla</a> &gt;= 1.3-Beta</span> on any platform.
+Any browser based on <a href="http://mozilla.org/newlayout">Gecko</a> will
+also work, provided that Gecko version is at least the one included in
+Mozilla-1.3-Beta (for example, <a
+href="http://galeon.sf.net">Galeon-1.2.8</a>).  However, it degrades
+gracefully to other browsers. They will get a regular textarea field
+instead of a WYSIWYG editor.</p>
+
+<h3>Can I see an example of what it looks like?</h3>
+
+<p>Just make sure you're using one of the browsers mentioned above and see
+below.</p>
+
+<form onsubmit="return false;">
+<textarea id="TA" style="width: 100%; height: 15em;">
+<p>Here is some sample text in textarea that's been transformed with <font
+color="#0000CC"><b>HTMLArea</b></font>.<br />
+You can make things <b>bold</b>, <i>italic</i>, <u>underline</u>.  You can change the
+<font size="3">size</font> and <b><font color="#0000CC">c</font><font color="#00CC00">o</font><font color="#00CCCC">l</font><font color="#CC0000">o</font><font color="#CC00CC">r</font><font color="#CCCC00">s</font><font color="#CCCCCC">!</font></b>
+And lots more...</p>
+
+<p align="center"><font size="4" color="#ff0000"><b><u>Try HTMLArea
+today!</u></b></font><br /></p>
+</textarea>
+</form>
+
+<h3>Where can I find out more info, download the latest version and talk to
+other HTMLArea users?</h3>
+
+<p>You can find out more about HTMLArea and download the latest version on
+the <a href="http://dynarch.com/htmlarea/">HTMLArea
+homepage</a> and you can talk to other HTMLArea users and post any comments
+or suggestions you have in the <a
+href="http://www.interactivetools.com/iforum/Open_Source_C3/htmlArea_v3.0_-_Alpha_Release_F14/"
+>HTMLArea forum</a>.</p>
+
+<h2>Keyboard shortcuts</h2>
+
+<p>The editor provides the following key combinations:</p>
+
+<ul>
+  <li>CTRL-A -- select all</li>
+  <li>CTRL-B -- bold</li>
+  <li>CTRL-I -- italic</li>
+  <li>CTRL-U -- underline</li>
+  <li>CTRL-S -- strikethrough</li>
+  <li>CTRL-L -- justify left</li>
+  <li>CTRL-E -- justify center</li>
+  <li>CTRL-R -- justify right</li>
+  <li>CTRL-J -- justify full</li>
+  <li>CTRL-1 .. CTRL-6 -- headings (&lt;h1&gt; .. &lt;h6&gt;)</li>
+  <li>CTRL-0 (zero) -- clean content pasted from Word</li>
+</ul>
+
+<h2>Installation</h2>
+
+<h3>How do I add HTMLArea to my web page?</h3>
+
+<p>It's easy.  First you need to upload HTMLArea files to your website.
+Just follow these steps.</p>
+
+<ol>
+  <li>Download the latest version from the <a
+  href="http://www.interactivetools.com/products/htmlarea/">htmlArea
+  homepage</a>.</li>
+  <li>Unzip the files onto your local computer (making sure to maintain the
+  directory structure contained in the zip).</li>
+  <li>Create a new folder on your website called /htmlarea/ (make sure it's
+  NOT inside the cgi-bin).</li>
+  <li>Transfer all the HTMLArea files from your local computer into the
+  /htmlarea/ folder on your website.</li>
+  <li>Open the example page /htmlarea/examples/core.html with your browser to make
+  sure everything works.</li>
+</ol>
+
+<p>Once htmlArea is on your website all you need to do is add some
+JavaScript to any pages that you want to add WYSIWYG editors to.  Here's how
+to do that.</p>
+
+<ol>
+
+  <li>Define some global variables.  "_editor_url" has to be the absolute
+  URL where HTMLArea resides within your
+  website; as we discussed, this would be “/htmlarea/”.  "_editor_lang" must
+  be the language code in which you want HTMLArea to appear.  This defaults
+  to "en" (English); for a list of supported languages, please look into
+  the "lang" subdirectory in the distribution.
+  <pre class="code"
+  ><span class="function-name">&lt;</span><span class="html-tag">script</span> <span class="variable-name">type=</span><span class="string">&quot;text/javascript&quot;</span><span class="function-name">&gt;</span>
+   _editor_url = <span class="string">&quot;/htmlarea/&quot;</span>;
+   _editor_lang = <span class="string">&quot;en&quot;</span>;
+<span class="function-name">&lt;</span><span class="html-tag">/script</span><span class="function-name">&gt;</span></pre>
+
+  <li>Include the "htmlarea.js" script:
+  <pre class="code"
+  ><span class="function-name">&lt;</span><span class="html-tag">script</span> <span class="variable-name">type=</span><span class="string">&quot;text/javascript&quot;</span> <span class="variable-name">src=</span><span class="string">&quot;/htmlarea/htmlarea.js&quot;</span><span class="function-name">&gt;</span><span class="paren-face-match">&lt;</span><span class="html-tag">/script</span><span class="paren-face-match">&gt;</span></pre>
+  </li>
+
+  <li><p>If you want to change all your &lt;textarea&gt;-s into
+  HTMLArea-s then you can use the simplest way to create HTMLArea:</p>
+  <pre class="code"
+  ><span class="function-name">&lt;</span><span class="html-tag">script</span> <span class="variable-name">type=</span><span class="string">&quot;text/javascript&quot;</span> <span class="variable-name">defer=</span><span class="string">&quot;1&quot;</span><span class="function-name">&gt;</span>
+    HTMLArea.replaceAll<span class="function-name">()</span>;
+<span class="paren-face-match">&lt;</span><span class="html-tag">/script</span><span class="paren-face-match">&gt;</span></pre>
+  <p><span class="note">Note:</span> you can also add the
+  <code>HTMLArea.replaceAll()</code> code to the <code>onload</code>
+  event handler for the <code>body</code> element, if you find it more appropriate.</p>
+
+  <p>A different approach, if you have more than one textarea and only want
+  to change one of them, is to use <code>HTMLArea.replace("id")</code> --
+  pass the <code>id</code> of your textarea.  Do not use the
+  <code>name</code> attribute anymore, it's not a standard solution!</p>
+
+</ol>
+
+<p>This section applies to HTMLArea-3.0 release candidate 1 or later; prior
+to this version, one needed to include more files; however, now HTMLArea is
+able to include other files too (such as stylesheet, language definition
+file, etc.) so you only need to define the editor path and load
+"htmlarea.js".  Nice, eh? ;-)</p>
+
+<h3>I want to change the editor settings, how do I do that?</h3>
+
+<p>While it's true that all you need is one line of JavaScript to create an
+htmlArea WYSIWYG editor, you can also specify more config settings in the
+code to control how the editor works and looks.  Here's an example of some of
+the available settings:</p>
+
+<pre class="code"
+><span class="keyword">var</span> <span class="variable-name">config</span> = <span class="keyword">new</span> HTMLArea.Config(); <span class="comment">// create a new configuration object
+</span>                                    <span class="comment">// having all the default values
+</span>config.width = '<span class="string">90%</span>';
+config.height = '<span class="string">200px</span>';
+
+<span class="comment">// the following sets a style for the page body (black text on yellow page)
+// and makes all paragraphs be bold by default
+</span>config.pageStyle =
+  '<span class="string">body { background-color: yellow; color: black; font-family: verdana,sans-serif } </span>' +
+  '<span class="string">p { font-width: bold; } </span>';
+
+<span class="comment">// the following replaces the textarea with the given id with a new
+// HTMLArea object having the specified configuration
+</span>HTMLArea.replace('<span class="string">id</span>', config);</pre>
+
+<p><span class="warning">Important:</span> It's recommended that you add
+custom features and configuration to a separate file.  This will ensure you
+that when we release a new official version of HTMLArea you'll have less
+trouble upgrading it.</p>
+
+<h3>How do I customize the toolbar?</h3>
+
+<p>Using the configuration object introduced above allows you to completely
+control what the toolbar contains.  Following is an example of a one-line,
+customized toolbar, much simpler than the default one:</p>
+
+<pre class="code"
+><span class="keyword">var</span> <span class="variable-name">config</span> = <span class="keyword">new</span> HTMLArea.Config();
+config.toolbar = [
+  ['<span class="string">fontname</span>', '<span class="string">space</span>',
+   '<span class="string">fontsize</span>', '<span class="string">space</span>',
+   '<span class="string">formatblock</span>', '<span class="string">space</span>',
+   '<span class="string">bold</span>', '<span class="string">italic</span>', '<span class="string">underline</span>']
+];
+HTMLArea.replace('<span class="string">id</span>', config);</pre>
+
+<p>The toolbar is an Array of Array objects.  Each array in the toolbar
+defines a new line.  The default toolbar looks like this:</p>
+
+<pre class="code"
+>config.toolbar = [
+[ &quot;<span class="string">fontname</span>&quot;, &quot;<span class="string">space</span>&quot;,
+  &quot;<span class="string">fontsize</span>&quot;, &quot;<span class="string">space</span>&quot;,
+  &quot;<span class="string">formatblock</span>&quot;, &quot;<span class="string">space</span>&quot;,
+  &quot;<span class="string">bold</span>&quot;, &quot;<span class="string">italic</span>&quot;, &quot;<span class="string">underline</span>&quot;, &quot;<span class="string">separator</span>&quot;,
+  &quot;<span class="string">strikethrough</span>&quot;, &quot;<span class="string">subscript</span>&quot;, &quot;<span class="string">superscript</span>&quot;, &quot;<span class="string">separator</span>&quot;,
+  &quot;<span class="string">copy</span>&quot;, &quot;<span class="string">cut</span>&quot;, &quot;<span class="string">paste</span>&quot;, &quot;<span class="string">space</span>&quot;, &quot;<span class="string">undo</span>&quot;, &quot;<span class="string">redo</span>&quot; ],
+               
+[ &quot;<span class="string">justifyleft</span>&quot;, &quot;<span class="string">justifycenter</span>&quot;, &quot;<span class="string">justifyright</span>&quot;, &quot;<span class="string">justifyfull</span>&quot;, &quot;<span class="string">separator</span>&quot;,
+  &quot;<span class="string">insertorderedlist</span>&quot;, &quot;<span class="string">insertunorderedlist</span>&quot;, &quot;<span class="string">outdent</span>&quot;, &quot;<span class="string">indent</span>&quot;, &quot;<span class="string">separator</span>&quot;,
+  &quot;<span class="string">forecolor</span>&quot;, &quot;<span class="string">hilitecolor</span>&quot;, &quot;<span class="string">textindicator</span>&quot;, &quot;<span class="string">separator</span>&quot;,
+  &quot;<span class="string">inserthorizontalrule</span>&quot;, &quot;<span class="string">createlink</span>&quot;, &quot;<span class="string">insertimage</span>&quot;, &quot;<span class="string">inserttable</span>&quot;, &quot;<span class="string">htmlmode</span>&quot;, &quot;<span class="string">separator</span>&quot;,
+  &quot;<span class="string">popupeditor</span>&quot;, &quot;<span class="string">separator</span>&quot;, &quot;<span class="string">showhelp</span>&quot;, &quot;<span class="string">about</span>&quot; ]
+];</pre>
+
+<p>Except three strings, all others in the examples above need to be defined
+in the <code>config.btnList</code> object (detailed a bit later in this
+document).  The three exceptions are: 'space', 'separator' and 'linebreak'.
+These three have the following meaning, and need not be present in
+<code>btnList</code>:</p>
+
+<ul>
+  <li>'space' -- Inserts a space of 5 pixels (the width is configurable by external
+  <acronym title="Cascading Style Sheets">CSS</acronym>) at the current
+  position in the toolbar.</li>
+  <li>'separator' -- Inserts a small vertical separator, for visually grouping related
+  buttons.</li>
+  <li>'linebreak' -- Starts a new line in the toolbar.  Subsequent controls will be
+  inserted on the new line.</li>
+</ul>
+
+<p><span class="warning">Important:</span> It's recommended that you add
+custom features and configuration to a separate file.  This will ensure you
+that when we release a new official version of HTMLArea you'll have less
+trouble upgrading it.</p>
+
+<h3>How do I create custom buttons?</h3>
+
+<p>By design, the toolbar is easily extensible.  For adding a custom button
+one needs to follow two steps.</p>
+
+<h4 id="regbtn">1. Register the button in <code>config.btnList</code>.</h4>
+
+<p>For each button in the toolbar, HTMLArea needs to know the following
+information:</p>
+<ul>
+  <li>a name for it (we call it the ID of the button);</li>
+  <li>the path to an image to be displayed in the toolbar;</li>
+  <li>a tooltip for it;</li>
+  <li>whether the button is enabled or not in text mode;</li>
+  <li>what to do when the button is clicked;</li>
+</ul>
+<p>You need to provide all this information for registering a new button
+too.  The button ID can be any string identifier and it's used when
+defining the toolbar, as you saw above.  We recommend starting
+it with "my-" so that it won't clash with the standard ID-s (those from
+the default toolbar).</p>
+
+<p class="note">Register button example #1</p>
+
+<pre class="code"
+><span class="comment">// get a default configuration
+</span><span class="keyword">var</span> <span class="variable-name">config</span> = <span class="keyword">new</span> HTMLArea.Config();
+<span class="comment">// register the new button using Config.registerButton.
+// parameters:        button ID,   tooltip,          image,           textMode,
+</span>config.registerButton(&quot;<span class="string">my-hilite</span>&quot;, &quot;<span class="string">Highlight text</span>&quot;, &quot;<span class="string">my-hilite.gif</span>&quot;, <span class="keyword">false</span>,
+<span class="comment">// function that gets called when the button is clicked
+</span>  <span class="keyword">function</span>(editor, id) {
+    editor.surroundHTML('<span class="string">&lt;span class=&quot;hilite&quot;&gt;</span>', '<span class="string">&lt;/span&gt;</span>');
+  }
+);</pre>
+
+<p>An alternate way of calling registerButton is exemplified above.  Though
+the code might be a little bit larger, using this form makes your code more
+maintainable.  It doesn't even needs comments as it's pretty clear.</p>
+
+<p class="note">Register button example #2</p>
+
+<pre class="code"
+><span class="keyword">var</span> <span class="variable-name">config</span> = <span class="keyword">new</span> HTMLArea.Config();
+config.registerButton({
+  id        : &quot;<span class="string">my-hilite</span>&quot;,
+  tooltip   : &quot;<span class="string">Highlight text</span>&quot;,
+  image     : &quot;<span class="string">my-hilite.gif</span>&quot;,
+  textMode  : <span class="keyword">false</span>,
+  action    : <span class="keyword">function</span>(editor, id) {
+                editor.surroundHTML('<span class="string">&lt;span class=&quot;hilite&quot;&gt;</span>', '<span class="string">&lt;/span&gt;</span>');
+              }
+});</pre>
+
+<p>You might notice that the "action" function receives two parameters:
+<b>editor</b> and <b>id</b>.  In the examples above we only used the
+<b>editor</b> parameter.  But it could be helpful for you to understand
+both:</p>
+
+<ul>
+  <li><b>editor</b> is a reference to the HTMLArea object.  Since our entire
+  code now has an <acronym title="Object Oriented Programming">OOP</acronym>-like
+  design, you need to have a reference to
+  the editor object in order to do things with it.  In previous versions of
+  HTMLArea, in order to identify the object an ID was used -- the ID of the
+  HTML element.  In this version ID-s are no longer necessary.</li>
+
+  <li><b>id</b> is the button ID.  Wondering why is this useful?  Well, you
+  could use the same handler function (presuming that it's not an anonymous
+  function like in the examples above) for more buttons.  You can <a
+  href="#btnex">see an example</a> a bit later in this document.</li>
+</ul>
+
+<h4>2. Inserting it into the toolbar</h4>
+
+<p>At this step you need to specify where in the toolbar to insert the
+button, or just create the whole toolbar again as you saw in the previous
+section.  You use the button ID, as shown in the examples of customizing the
+toolbar in the previous section.</p>
+
+<p>For the sake of completion, following there are another examples.</p>
+
+<p class="note">Append your button to the default toolbar</p>
+
+<pre class="code"
+>config.toolbar.push([ &quot;<span class="string">my-hilite</span>&quot; ]);</pre>
+
+<p class="note">Customized toolbar</p>
+
+<pre class="code"
+>config.toolbar = [
+  ['<span class="string">fontname</span>', '<span class="string">space</span>',
+   '<span class="string">fontsize</span>', '<span class="string">space</span>',
+   '<span class="string">formatblock</span>', '<span class="string">space</span>',
+   '<span class="string">separator</span>', '<span class="string">my-hilite</span>', '<span class="string">separator</span>', '<span class="string">space</span>', <span class="comment">// here's your button
+</span>   '<span class="string">bold</span>', '<span class="string">italic</span>', '<span class="string">underline</span>', '<span class="string">space</span>']
+];</pre>
+
+<p><span class="note">Note:</span> in the example above our new button is
+between two vertical separators.  But this is by no means required.  You can
+put it wherever you like.  Once registered in the btnList (<a
+href="#regbtn">step 1</a>) your custom button behaves just like a default
+button.</p>
+
+<p><span class="warning">Important:</span> It's recommended that you add
+custom features and configuration to a separate file.  This will ensure you
+that when we release a new official version of HTMLArea you'll have less
+trouble upgrading it.</p>
+
+<h4 id="btnex">A complete example</h4>
+
+<p>Please note that it is by no means necessary to include the following
+code into the htmlarea.js file.  On the contrary, it might not work there.
+The configuration system is designed such that you can always customize the
+editor <em>from outside files</em>, thus keeping the htmlarea.js file
+intact.  This will make it easy for you to upgrade your HTMLArea when we
+release a new official version.  OK, I promise it's the last time I said
+this. ;)</p>
+
+<pre class="code"
+><span class="comment">// All our custom buttons will call this function when clicked.
+// We use the <b>buttonId</b> parameter to determine what button
+// triggered the call.
+</span><span class="keyword">function</span> <span class="function-name">clickHandler</span>(editor, buttonId) {
+  <span class="keyword">switch</span> (buttonId) {
+    <span class="keyword">case</span> &quot;<span class="string">my-toc</span>&quot;:
+      editor.insertHTML(&quot;<span class="string">&lt;h1&gt;Table Of Contents&lt;/h1&gt;</span>&quot;);
+      <span class="keyword">break</span>;
+    <span class="keyword">case</span> &quot;<span class="string">my-date</span>&quot;:
+      editor.insertHTML((<span class="keyword">new</span> Date()).toString());
+      <span class="keyword">break</span>;
+    <span class="keyword">case</span> &quot;<span class="string">my-bold</span>&quot;:
+      editor.execCommand(&quot;<span class="string">bold</span>&quot;);
+      editor.execCommand(&quot;<span class="string">italic</span>&quot;);
+      <span class="keyword">break</span>;
+    <span class="keyword">case</span> &quot;<span class="string">my-hilite</span>&quot;:
+      editor.surroundHTML(&quot;<span class="string">&lt;span class=\&quot;hilite\&quot;&gt;</span>&quot;, &quot;<span class="string">&lt;/span&gt;</span>&quot;);
+      <span class="keyword">break</span>;
+  }
+};
+
+<span class="comment">// Create a new configuration object
+</span><span class="keyword">var</span> <span class="variable-name">config</span> = <span class="keyword">new</span> HTMLArea.Config();
+
+<span class="comment">// Register our custom buttons
+</span>config.registerButton(&quot;<span class="string">my-toc</span>&quot;,  &quot;<span class="string">Insert TOC</span>&quot;, &quot;<span class="string">my-toc.gif</span>&quot;, <span class="keyword">false</span>, clickHandler);
+config.registerButton(&quot;<span class="string">my-date</span>&quot;, &quot;<span class="string">Insert date/time</span>&quot;, &quot;<span class="string">my-date.gif</span>&quot;, <span class="keyword">false</span>, clickHandler);
+config.registerButton(&quot;<span class="string">my-bold</span>&quot;, &quot;<span class="string">Toggle bold/italic</span>&quot;, &quot;<span class="string">my-bold.gif</span>&quot;, <span class="keyword">false</span>, clickHandler);
+config.registerButton(&quot;<span class="string">my-hilite</span>&quot;, &quot;<span class="string">Hilite selection</span>&quot;, &quot;<span class="string">my-hilite.gif</span>&quot;, <span class="keyword">false</span>, clickHandler);
+
+<span class="comment">// Append the buttons to the default toolbar
+</span>config.toolbar.push([&quot;<span class="string">linebreak</span>&quot;, &quot;<span class="string">my-toc</span>&quot;, &quot;<span class="string">my-date</span>&quot;, &quot;<span class="string">my-bold</span>&quot;, &quot;<span class="string">my-hilite</span>&quot;]);
+
+<span class="comment">// Replace an existing textarea with an HTMLArea object having the above config.
+</span>HTMLArea.replace(&quot;<span class="string">textAreaID</span>&quot;, config);</pre>
+
+
+<hr />
+<address>&copy; <a href="http://interactivetools.com" title="Visit our website"
+>InteractiveTools.com</a> 2002-2004.
+<br />
+© <a href="http://dynarch.com">dynarch.com</a> 2003-2004<br />
+HTMLArea v3.0 developed by <a
+href="http://dynarch.com/mishoo/">Mihai Bazon</a>.
+<br />
+Documentation written by Mihai Bazon.
+</address>
+<!-- hhmts start --> Last modified: Wed Jan 28 12:18:23 EET 2004 <!-- hhmts end -->
+<!-- doc-lang: English -->
+</body> </html>
diff --git a/Open-ILS/src/extras/authcon/auth/resources/htmlarea/release-notes.html b/Open-ILS/src/extras/authcon/auth/resources/htmlarea/release-notes.html
new file mode 100644 (file)
index 0000000..f2200d5
--- /dev/null
@@ -0,0 +1,165 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>HTMLArea-3.0-rc1 release notes</title>
+    <style>
+      .fixme { color: red; }
+    </style>
+  </head>
+
+  <body>
+
+    <h1>HTMLArea-3.0-rc1 release notes</h1>
+
+    <p>This release was compiled on Mar  1, 2004 [19:37] GMT.</p>
+
+    <h2>3.0-rc1</h2>
+
+    <p>Changes since 3.0-Beta:</p>
+
+    <ul>
+      <li>
+        <b>New plugins</b>
+        <ul>
+          <li>
+            ContextMenu plugin (provides a nice context menu with common
+            operations, including table ops, link ops, etc.)
+          </li>
+          <li>
+            CSS plugin (provides an easy way to insert/change CSS classes)
+          </li>
+          <li>
+            FullPage plugin (allows HTMLArea to edit a whole HTML file,
+            not only the content within &lt;body&gt;.)
+          </li>
+        </ul>
+      </li>
+      <li>
+        <b>Changes in the SpellChecker plugin</b>
+        <ul>
+          <li>
+            Many bugfixes: now it works ;-)  Fully Unicode-safe.
+          </li>
+          <li>
+            Speed and bandwidth optimization: reports the list of
+            suggestions only once for each mispelled word; this helps
+            in cases where you have, for instance, the word “HTMLArea”
+            in 10 places all over the document; the list of
+            suggestions for it--which is kind of huge--will only be
+            included <em>once</em>.
+          </li>
+          <li>
+            User interface improvements: the highlighted word will
+            remain in view; in cases where it's normally outside, the
+            window will be scrolled to it.
+          </li>
+          <li>
+            Added a "Revert" button for those that change their minds ;-)
+          </li>
+          <li>
+            Added a "Info" button which reports information about the
+            document, retrieved by the server-side spell checker:
+            total number of words, total number of mispelled words,
+            number of suggestions made, spell check time, etc.  More
+            can be easily added.  <span class="fixme">FIXME: this part
+            is not yet internationalized.</span>
+          </li>
+          <li>
+            The server-side spell checker now uses XML::DOM instead of
+            HTML::Parser, which means that it will be unable to parse
+            “tag-soup” HTML.  It needs valid code.  Usually HTMLArea
+            generates valid code, but on rare occasions it might fail
+            and the spell checker will report a gross error message.
+            This gonna have to be fixed, but instead of making the
+            spell checker accept invalid HTML I prefer to make
+            HTMLArea generate valid code, so changes are to be done in
+            other places ;-)
+          </li>
+        </ul>
+      </li>
+      <li>
+        <b>Changes in the core editor</b>
+        <ul>
+          <li>
+            Easier to setup: you only need to load
+            <tt>htmlarea.js</tt>; other scripts will be loaded
+            automatically.  <a href="reference.html">Documentation</a>
+            and <a href="examples/">examples</a> updated.
+          </li>
+          <li>
+            Better plugin support (they register information about
+            themselves with the editor; can register event handlers for
+            the editor, etc.)
+          </li>
+          <li>
+            New about box; check it out, it's cool ;-)
+          </li>
+          <li>
+            Word cleaner (can be enabled to automatically kill Word crap
+            on paste (see Config.killWordOnPaste); otherwise accessible by
+            pressing CTRL-0 in the editor; a toolbar button will come up
+            soon)
+          </li>
+          <li>
+            Image preview in "insert image" dialog.  Also allows
+            modification of current image, if selected.
+          </li>
+          <li>
+            New "insert link" dialog, allows target and title
+            specification, allows editing links.
+          </li>
+          <li>
+            Implemented support for text direction (left-to-right or
+            right-to-left).
+          </li>
+          <li>
+            Lots of bug fixes!  ... and more, I guess ;-) an
+            automatically generated <a href="ChangeLog">change log</a>
+            is now available.
+          </li>
+        </ul>
+      </li>
+    </ul>
+
+    <p>I don't have the power to go through the <a
+href="http://sourceforge.net/tracker/?atid=525656&group_id=69750&func=browse">bug
+system</a> at SourceForge
+    now.  Some of the bugs reported there may be fixed; I'll update
+    their status, some other time.  If you reported bugs there and now
+    find them to be fixed, please let me know.</p>
+
+    <h2>3.0-Beta</h2>
+
+    <p>Changes since 3.0-Alpha:</p>
+
+    <ul>
+
+      <li>Performance improvements.</li>
+
+      <li>Many bugs fixed.</li>
+
+      <li>Plugin infrastructure.</li>
+
+      <li>TableOperations plugin.</li>
+
+      <li>SpellChecker plugin.</li>
+
+      <li>Status bar.</li>
+
+      <li>API for registering custom buttons and drop-down boxes in the
+        toolbar.</li>
+
+      <li>Toolbar can contain text labels.</li>
+
+      <li>Cut, copy, paste, undo, redo buttons.</li>
+
+    </ul>
+    <hr />
+    <address><a href="http://dynarch.com/mishoo/">Mihai Bazon</a></address>
+<!-- Created: Sun Aug  3 16:55:08 EEST 2003 -->
+<!-- hhmts start --> Last modified: Sun Feb  1 13:16:10 EET 2004 <!-- hhmts end -->
+<!-- doc-lang: English -->
+  </body>
+</html>
+
+
diff --git a/Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib.js b/Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib.js
new file mode 100644 (file)
index 0000000..c7230c1
--- /dev/null
@@ -0,0 +1,124 @@
+// ===================================================================
+// Author: Matt Kruse <matt@mattkruse.com>
+// WWW: http://www.mattkruse.com/
+//
+// NOTICE: You may use this code for any purpose, commercial or
+// private, without any further permission from the author. You may
+// remove this notice from your final code if you wish, however it is
+// appreciated by the author if at least my web site address is kept.
+//
+// You may *NOT* re-distribute this code in any way except through its
+// use. That means, you can include it in your product, or your web
+// site, or any other form where the code is actually being used. You
+// may not put the plain javascript up on your site for download or
+// include it in your javascript libraries for download. 
+// If you wish to share this code with others, please just point them
+// to the URL instead.
+// Please DO NOT link directly to my .js files from your site. Copy
+// the files to your server and use them there. Thank you.
+// ===================================================================
+
+/* SOURCE FILE: selectbox.js */
+function selectUnselectMatchingOptions(obj,regex,which,only){if(window.RegExp){if(which == "select"){var selected1=true;var selected2=false;}else if(which == "unselect"){var selected1=false;var selected2=true;}else{return;}var re = new RegExp(regex);for(var i=0;i<obj.options.length;i++){if(re.test(obj.options[i].text)){obj.options[i].selected = selected1;}else{if(only == true){obj.options[i].selected = selected2;}}}}}
+function selectMatchingOptions(obj,regex){selectUnselectMatchingOptions(obj,regex,"select",false);}
+function selectOnlyMatchingOptions(obj,regex){selectUnselectMatchingOptions(obj,regex,"select",true);}
+function unSelectMatchingOptions(obj,regex){selectUnselectMatchingOptions(obj,regex,"unselect",false);}
+function sortSelect(obj){var o = new Array();if(obj.options==null){return;}for(var i=0;i<obj.options.length;i++){o[o.length] = new Option( obj.options[i].text, obj.options[i].value, obj.options[i].defaultSelected, obj.options[i].selected) ;}if(o.length==0){return;}o = o.sort(
+function(a,b){if((a.text+"") <(b.text+"")){return -1;}if((a.text+"") >(b.text+"")){return 1;}return 0;});for(var i=0;i<o.length;i++){obj.options[i] = new Option(o[i].text, o[i].value, o[i].defaultSelected, o[i].selected);}}
+function selectAllOptions(obj){for(var i=0;i<obj.options.length;i++){obj.options[i].selected = true;}}
+function moveSelectedOptions(from,to){if(arguments.length>3){var regex = arguments[3];if(regex != ""){unSelectMatchingOptions(from,regex);}}for(var i=0;i<from.options.length;i++){var o = from.options[i];if(o.selected){to.options[to.options.length] = new Option( o.text, o.value, false, false);}}for(var i=(from.options.length-1);i>=0;i--){var o = from.options[i];if(o.selected){from.options[i] = null;}}if((arguments.length<3) ||(arguments[2]==true)){sortSelect(from);sortSelect(to);}from.selectedIndex = -1;to.selectedIndex = -1;}
+function copySelectedOptions(from,to){var options = new Object();for(var i=0;i<to.options.length;i++){options[to.options[i].text] = true;}for(var i=0;i<from.options.length;i++){var o = from.options[i];if(o.selected){if(options[o.text] == null || options[o.text] == "undefined"){to.options[to.options.length] = new Option( o.text, o.value, false, false);}}}if((arguments.length<3) ||(arguments[2]==true)){sortSelect(to);}from.selectedIndex = -1;to.selectedIndex = -1;}
+function moveAllOptions(from,to){selectAllOptions(from);if(arguments.length==2){moveSelectedOptions(from,to);}else if(arguments.length==3){moveSelectedOptions(from,to,arguments[2]);}else if(arguments.length==4){moveSelectedOptions(from,to,arguments[2],arguments[3]);}}
+function copyAllOptions(from,to){selectAllOptions(from);if(arguments.length==2){copySelectedOptions(from,to);}else if(arguments.length==3){copySelectedOptions(from,to,arguments[2]);}}
+function swapOptions(obj,i,j){var o = obj.options;var i_selected = o[i].selected;var j_selected = o[j].selected;var temp = new Option(o[i].text, o[i].value, o[i].defaultSelected, o[i].selected);var temp2= new Option(o[j].text, o[j].value, o[j].defaultSelected, o[j].selected);o[i] = temp2;o[j] = temp;o[i].selected = j_selected;o[j].selected = i_selected;}
+function moveOptionUp(obj){var selectedCount=0;for(i=0;i<obj.options.length;i++){if(obj.options[i].selected){selectedCount++;}}if(selectedCount!=1){return;}var i = obj.selectedIndex;if(i == 0){return;}swapOptions(obj,i,i-1);obj.options[i-1].selected = true;}
+function moveOptionDown(obj){var selectedCount=0;for(i=0;i<obj.options.length;i++){if(obj.options[i].selected){selectedCount++;}}if(selectedCount != 1){return;}var i = obj.selectedIndex;if(i ==(obj.options.length-1)){return;}swapOptions(obj,i,i+1);obj.options[i+1].selected = true;}
+function removeSelectedOptions(from){for(var i=(from.options.length-1);i>=0;i--){var o=from.options[i];if(o.selected){from.options[i] = null;}}from.selectedIndex = -1;}
+
+
+/* SOURCE FILE: OptionTransfer.js */
+
+function OT_transferLeft(){moveSelectedOptions(this.right,this.left,this.autoSort);this.update();}
+function OT_transferRight(){moveSelectedOptions(this.left,this.right,this.autoSort);this.update();}
+function OT_transferAllLeft(){moveAllOptions(this.right,this.left,this.autoSort);this.update();}
+function OT_transferAllRight(){moveAllOptions(this.left,this.right,this.autoSort);this.update();}
+function OT_saveRemovedLeftOptions(f){this.removedLeftField = f;}
+function OT_saveRemovedRightOptions(f){this.removedRightField = f;}
+function OT_saveAddedLeftOptions(f){this.addedLeftField = f;}
+function OT_saveAddedRightOptions(f){this.addedRightField = f;}
+function OT_saveNewLeftOptions(f){this.newLeftField = f;}
+function OT_saveNewRightOptions(f){this.newRightField = f;}
+function OT_update(){var removedLeft = new Object();var removedRight = new Object();var addedLeft = new Object();var addedRight = new Object();var newLeft = new Object();var newRight = new Object();for(var i=0;i<this.left.options.length;i++){var o=this.left.options[i];newLeft[o.value]=1;if(typeof(this.originalLeftValues[o.value])=="undefined"){addedLeft[o.value]=1;removedRight[o.value]=1;}}for(var i=0;i<this.right.options.length;i++){var o=this.right.options[i];newRight[o.value]=1;if(typeof(this.originalRightValues[o.value])=="undefined"){addedRight[o.value]=1;removedLeft[o.value]=1;}}if(this.removedLeftField!=null){this.removedLeftField.value = OT_join(removedLeft,this.delimiter);}if(this.removedRightField!=null){this.removedRightField.value = OT_join(removedRight,this.delimiter);}if(this.addedLeftField!=null){this.addedLeftField.value = OT_join(addedLeft,this.delimiter);}if(this.addedRightField!=null){this.addedRightField.value = OT_join(addedRight,this.delimiter);}if(this.newLeftField!=null){this.newLeftField.value = OT_join(newLeft,this.delimiter);}if(this.newRightField!=null){this.newRightField.value = OT_join(newRight,this.delimiter);}}
+function OT_join(o,delimiter){var val;var str="";for(val in o){if(str.length>0){str=str+delimiter;}str=str+val;}return str;}
+function OT_setDelimiter(val){this.delimiter=val;}
+function OT_setAutoSort(val){this.autoSort=val;}
+function OT_init(theform){this.form = theform;if(!theform[this.left]){alert("OptionTransfer init(): Left select list does not exist in form!");return false;}if(!theform[this.right]){alert("OptionTransfer init(): Right select list does not exist in form!");return false;}this.left=theform[this.left];this.right=theform[this.right];for(var i=0;i<this.left.options.length;i++){this.originalLeftValues[this.left.options[i].value]=1;}for(var i=0;i<this.right.options.length;i++){this.originalRightValues[this.right.options[i].value]=1;}if(this.removedLeftField!=null){this.removedLeftField=theform[this.removedLeftField];}if(this.removedRightField!=null){this.removedRightField=theform[this.removedRightField];}if(this.addedLeftField!=null){this.addedLeftField=theform[this.addedLeftField];}if(this.addedRightField!=null){this.addedRightField=theform[this.addedRightField];}if(this.newLeftField!=null){this.newLeftField=theform[this.newLeftField];}if(this.newRightField!=null){this.newRightField=theform[this.newRightField];}this.update();}
+function OptionTransfer(l,r){this.form = null;this.left=l;this.right=r;this.autoSort=true;this.delimiter=",";this.originalLeftValues = new Object();this.originalRightValues = new Object();this.removedLeftField = null;this.removedRightField = null;this.addedLeftField = null;this.addedRightField = null;this.newLeftField = null;this.newRightField = null;this.transferLeft=OT_transferLeft;this.transferRight=OT_transferRight;this.transferAllLeft=OT_transferAllLeft;this.transferAllRight=OT_transferAllRight;this.saveRemovedLeftOptions=OT_saveRemovedLeftOptions;this.saveRemovedRightOptions=OT_saveRemovedRightOptions;this.saveAddedLeftOptions=OT_saveAddedLeftOptions;this.saveAddedRightOptions=OT_saveAddedRightOptions;this.saveNewLeftOptions=OT_saveNewLeftOptions;this.saveNewRightOptions=OT_saveNewRightOptions;this.setDelimiter=OT_setDelimiter;this.setAutoSort=OT_setAutoSort;this.init=OT_init;this.update=OT_update;}
+
+/* SOURCE FILE: date.js */
+var MONTH_NAMES=new Array('January','February','March','April','May','June','July','August','September','October','November','December','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');var DAY_NAMES=new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sun','Mon','Tue','Wed','Thu','Fri','Sat');
+function LZ(x){return(x<0||x>9?"":"0")+x}
+function isDate(val,format){var date=getDateFromFormat(val,format);if(date==0){return false;}return true;}
+function compareDates(date1,dateformat1,date2,dateformat2){var d1=getDateFromFormat(date1,dateformat1);var d2=getDateFromFormat(date2,dateformat2);if(d1==0 || d2==0){return -1;}else if(d1 > d2){return 1;}return 0;}
+function formatDate(date,format){format=format+"";var result="";var i_format=0;var c="";var token="";var y=date.getYear()+"";var M=date.getMonth()+1;var d=date.getDate();var E=date.getDay();var H=date.getHours();var m=date.getMinutes();var s=date.getSeconds();var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,H,KK,K,kk,k;var value=new Object();if(y.length < 4){y=""+(y-0+1900);}value["y"]=""+y;value["yyyy"]=y;value["yy"]=y.substring(2,4);value["M"]=M;value["MM"]=LZ(M);value["MMM"]=MONTH_NAMES[M-1];value["NNN"]=MONTH_NAMES[M+11];value["d"]=d;value["dd"]=LZ(d);value["E"]=DAY_NAMES[E+7];value["EE"]=DAY_NAMES[E];value["H"]=H;value["HH"]=LZ(H);if(H==0){value["h"]=12;}else if(H>12){value["h"]=H-12;}else{value["h"]=H;}value["hh"]=LZ(value["h"]);if(H>11){value["K"]=H-12;}else{value["K"]=H;}value["k"]=H+1;value["KK"]=LZ(value["K"]);value["kk"]=LZ(value["k"]);if(H > 11){value["a"]="PM";}else{value["a"]="AM";}value["m"]=m;value["mm"]=LZ(m);value["s"]=s;value["ss"]=LZ(s);while(i_format < format.length){c=format.charAt(i_format);token="";while((format.charAt(i_format)==c) &&(i_format < format.length)){token += format.charAt(i_format++);}if(value[token] != null){result=result + value[token];}else{result=result + token;}}return result;}
+function _isInteger(val){var digits="1234567890";for(var i=0;i < val.length;i++){if(digits.indexOf(val.charAt(i))==-1){return false;}}return true;}
+function _getInt(str,i,minlength,maxlength){for(var x=maxlength;x>=minlength;x--){var token=str.substring(i,i+x);if(token.length < minlength){return null;}if(_isInteger(token)){return token;}}return null;}
+function getDateFromFormat(val,format){val=val+"";format=format+"";var i_val=0;var i_format=0;var c="";var token="";var token2="";var x,y;var now=new Date();var year=now.getYear();var month=now.getMonth()+1;var date=1;var hh=now.getHours();var mm=now.getMinutes();var ss=now.getSeconds();var ampm="";while(i_format < format.length){c=format.charAt(i_format);token="";while((format.charAt(i_format)==c) &&(i_format < format.length)){token += format.charAt(i_format++);}if(token=="yyyy" || token=="yy" || token=="y"){if(token=="yyyy"){x=4;y=4;}if(token=="yy"){x=2;y=2;}if(token=="y"){x=2;y=4;}year=_getInt(val,i_val,x,y);if(year==null){return 0;}i_val += year.length;if(year.length==2){if(year > 70){year=1900+(year-0);}else{year=2000+(year-0);}}}else if(token=="MMM"||token=="NNN"){month=0;for(var i=0;i<MONTH_NAMES.length;i++){var month_name=MONTH_NAMES[i];if(val.substring(i_val,i_val+month_name.length).toLowerCase()==month_name.toLowerCase()){if(token=="MMM"||(token=="NNN"&&i>11)){month=i+1;if(month>12){month -= 12;}i_val += month_name.length;break;}}}if((month < 1)||(month>12)){return 0;}}else if(token=="EE"||token=="E"){for(var i=0;i<DAY_NAMES.length;i++){var day_name=DAY_NAMES[i];if(val.substring(i_val,i_val+day_name.length).toLowerCase()==day_name.toLowerCase()){i_val += day_name.length;break;}}}else if(token=="MM"||token=="M"){month=_getInt(val,i_val,token.length,2);if(month==null||(month<1)||(month>12)){return 0;}i_val+=month.length;}else if(token=="dd"||token=="d"){date=_getInt(val,i_val,token.length,2);if(date==null||(date<1)||(date>31)){return 0;}i_val+=date.length;}else if(token=="hh"||token=="h"){hh=_getInt(val,i_val,token.length,2);if(hh==null||(hh<1)||(hh>12)){return 0;}i_val+=hh.length;}else if(token=="HH"||token=="H"){hh=_getInt(val,i_val,token.length,2);if(hh==null||(hh<0)||(hh>23)){return 0;}i_val+=hh.length;}else if(token=="KK"||token=="K"){hh=_getInt(val,i_val,token.length,2);if(hh==null||(hh<0)||(hh>11)){return 0;}i_val+=hh.length;}else if(token=="kk"||token=="k"){hh=_getInt(val,i_val,token.length,2);if(hh==null||(hh<1)||(hh>24)){return 0;}i_val+=hh.length;hh--;}else if(token=="mm"||token=="m"){mm=_getInt(val,i_val,token.length,2);if(mm==null||(mm<0)||(mm>59)){return 0;}i_val+=mm.length;}else if(token=="ss"||token=="s"){ss=_getInt(val,i_val,token.length,2);if(ss==null||(ss<0)||(ss>59)){return 0;}i_val+=ss.length;}else if(token=="a"){if(val.substring(i_val,i_val+2).toLowerCase()=="am"){ampm="AM";}else if(val.substring(i_val,i_val+2).toLowerCase()=="pm"){ampm="PM";}else{return 0;}i_val+=2;}else{if(val.substring(i_val,i_val+token.length)!=token){return 0;}else{i_val+=token.length;}}}if(i_val != val.length){return 0;}if(month==2){if( ((year%4==0)&&(year%100 != 0) ) ||(year%400==0) ){if(date > 29){return 0;}}else{if(date > 28){return 0;}}}if((month==4)||(month==6)||(month==9)||(month==11)){if(date > 30){return 0;}}if(hh<12 && ampm=="PM"){hh=hh-0+12;}else if(hh>11 && ampm=="AM"){hh-=12;}var newdate=new Date(year,month-1,date,hh,mm,ss);return newdate.getTime();}
+function parseDate(val){var preferEuro=(arguments.length==2)?arguments[1]:false;generalFormats=new Array('y-M-d','MMM d, y','MMM d,y','y-MMM-d','d-MMM-y','MMM d');monthFirst=new Array('M/d/y','M-d-y','M.d.y','MMM-d','M/d','M-d');dateFirst =new Array('d/M/y','d-M-y','d.M.y','d-MMM','d/M','d-M');var checkList=new Array('generalFormats',preferEuro?'dateFirst':'monthFirst',preferEuro?'monthFirst':'dateFirst');var d=null;for(var i=0;i<checkList.length;i++){var l=window[checkList[i]];for(var j=0;j<l.length;j++){d=getDateFromFormat(val,l[j]);if(d!=0){return new Date(d);}}}return null;}
+
+/* SOURCE FILE: AnchorPosition.js */
+function getAnchorPosition(anchorname){var useWindow=false;var coordinates=new Object();var x=0,y=0;var use_gebi=false, use_css=false, use_layers=false;if(document.getElementById){use_gebi=true;}else if(document.all){use_css=true;}else if(document.layers){use_layers=true;}if(use_gebi && document.all){x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]);y=AnchorPosition_getPageOffsetTop(document.all[anchorname]);}else if(use_gebi){var o=document.getElementById(anchorname);x=AnchorPosition_getPageOffsetLeft(o);y=AnchorPosition_getPageOffsetTop(o);}else if(use_css){x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]);y=AnchorPosition_getPageOffsetTop(document.all[anchorname]);}else if(use_layers){var found=0;for(var i=0;i<document.anchors.length;i++){if(document.anchors[i].name==anchorname){found=1;break;}}if(found==0){coordinates.x=0;coordinates.y=0;return coordinates;}x=document.anchors[i].x;y=document.anchors[i].y;}else{coordinates.x=0;coordinates.y=0;return coordinates;}coordinates.x=x;coordinates.y=y;return coordinates;}
+function getAnchorWindowPosition(anchorname){var coordinates=getAnchorPosition(anchorname);var x=0;var y=0;if(document.getElementById){if(isNaN(window.screenX)){x=coordinates.x-document.body.scrollLeft+window.screenLeft;y=coordinates.y-document.body.scrollTop+window.screenTop;}else{x=coordinates.x+window.screenX+(window.outerWidth-window.innerWidth)-window.pageXOffset;y=coordinates.y+window.screenY+(window.outerHeight-24-window.innerHeight)-window.pageYOffset;}}else if(document.all){x=coordinates.x-document.body.scrollLeft+window.screenLeft;y=coordinates.y-document.body.scrollTop+window.screenTop;}else if(document.layers){x=coordinates.x+window.screenX+(window.outerWidth-window.innerWidth)-window.pageXOffset;y=coordinates.y+window.screenY+(window.outerHeight-24-window.innerHeight)-window.pageYOffset;}coordinates.x=x;coordinates.y=y;return coordinates;}
+function AnchorPosition_getPageOffsetLeft(el){var ol=el.offsetLeft;while((el=el.offsetParent) != null){ol += el.offsetLeft;}return ol;}
+function AnchorPosition_getWindowOffsetLeft(el){return AnchorPosition_getPageOffsetLeft(el)-document.body.scrollLeft;}
+function AnchorPosition_getPageOffsetTop(el){var ot=el.offsetTop;while((el=el.offsetParent) != null){ot += el.offsetTop;}return ot;}
+function AnchorPosition_getWindowOffsetTop(el){return AnchorPosition_getPageOffsetTop(el)-document.body.scrollTop;}
+
+/* SOURCE FILE: PopupWindow.js */
+function PopupWindow_getXYPosition(anchorname){var coordinates;if(this.type == "WINDOW"){coordinates = getAnchorWindowPosition(anchorname);}else{coordinates = getAnchorPosition(anchorname);}this.x = coordinates.x;this.y = coordinates.y;}
+function PopupWindow_setSize(width,height){this.width = width;this.height = height;}
+function PopupWindow_populate(contents){this.contents = contents;this.populated = false;}
+function PopupWindow_setUrl(url){this.url = url;}
+function PopupWindow_setWindowProperties(props){this.windowProperties = props;}
+function PopupWindow_refresh(){if(this.divName != null){if(this.use_gebi){document.getElementById(this.divName).innerHTML = this.contents;}else if(this.use_css){document.all[this.divName].innerHTML = this.contents;}else if(this.use_layers){var d = document.layers[this.divName];d.document.open();d.document.writeln(this.contents);d.document.close();}}else{if(this.popupWindow != null && !this.popupWindow.closed){if(this.url!=""){this.popupWindow.location.href=this.url;}else{this.popupWindow.document.open();this.popupWindow.document.writeln(this.contents);this.popupWindow.document.close();}this.popupWindow.focus();}}}
+function PopupWindow_showPopup(anchorname){this.getXYPosition(anchorname);this.x += this.offsetX;this.y += this.offsetY;if(!this.populated &&(this.contents != "")){this.populated = true;this.refresh();}if(this.divName != null){if(this.use_gebi){document.getElementById(this.divName).style.left = this.x;document.getElementById(this.divName).style.top = this.y;document.getElementById(this.divName).style.visibility = "visible";}else if(this.use_css){document.all[this.divName].style.left = this.x;document.all[this.divName].style.top = this.y;document.all[this.divName].style.visibility = "visible";}else if(this.use_layers){document.layers[this.divName].left = this.x;document.layers[this.divName].top = this.y;document.layers[this.divName].visibility = "visible";}}else{if(this.popupWindow == null || this.popupWindow.closed){if(this.x<0){this.x=0;}if(this.y<0){this.y=0;}if(screen && screen.availHeight){if((this.y + this.height) > screen.availHeight){this.y = screen.availHeight - this.height;}}if(screen && screen.availWidth){if((this.x + this.width) > screen.availWidth){this.x = screen.availWidth - this.width;}}var avoidAboutBlank = window.opera ||( document.layers && !navigator.mimeTypes['*']) || navigator.vendor == 'KDE' ||( document.childNodes && !document.all && !navigator.taintEnabled);this.popupWindow = window.open(avoidAboutBlank?"":"about:blank","window_"+anchorname,this.windowProperties+",width="+this.width+",height="+this.height+",screenX="+this.x+",left="+this.x+",screenY="+this.y+",top="+this.y+"");}this.refresh();}}
+function PopupWindow_hidePopup(){if(this.divName != null){if(this.use_gebi){document.getElementById(this.divName).style.visibility = "hidden";}else if(this.use_css){document.all[this.divName].style.visibility = "hidden";}else if(this.use_layers){document.layers[this.divName].visibility = "hidden";}}else{if(this.popupWindow && !this.popupWindow.closed){this.popupWindow.close();this.popupWindow = null;}}}
+function PopupWindow_isClicked(e){if(this.divName != null){if(this.use_layers){var clickX = e.pageX;var clickY = e.pageY;var t = document.layers[this.divName];if((clickX > t.left) &&(clickX < t.left+t.clip.width) &&(clickY > t.top) &&(clickY < t.top+t.clip.height)){return true;}else{return false;}}else if(document.all){var t = window.event.srcElement;while(t.parentElement != null){if(t.id==this.divName){return true;}t = t.parentElement;}return false;}else if(this.use_gebi){var t = e.originalTarget;while(t.parentNode != null){if(t.id==this.divName){return true;}t = t.parentNode;}return false;}return false;}return false;}
+function PopupWindow_hideIfNotClicked(e){if(this.autoHideEnabled && !this.isClicked(e)){this.hidePopup();}}
+function PopupWindow_autoHide(){this.autoHideEnabled = true;}
+function PopupWindow_hidePopupWindows(e){for(var i=0;i<popupWindowObjects.length;i++){if(popupWindowObjects[i] != null){var p = popupWindowObjects[i];p.hideIfNotClicked(e);}}}
+function PopupWindow_attachListener(){if(document.layers){document.captureEvents(Event.MOUSEUP);}window.popupWindowOldEventListener = document.onmouseup;if(window.popupWindowOldEventListener != null){document.onmouseup = new Function("window.popupWindowOldEventListener();PopupWindow_hidePopupWindows();");}else{document.onmouseup = PopupWindow_hidePopupWindows;}}
+function PopupWindow(){if(!window.popupWindowIndex){window.popupWindowIndex = 0;}if(!window.popupWindowObjects){window.popupWindowObjects = new Array();}if(!window.listenerAttached){window.listenerAttached = true;PopupWindow_attachListener();}this.index = popupWindowIndex++;popupWindowObjects[this.index] = this;this.divName = null;this.popupWindow = null;this.width=0;this.height=0;this.populated = false;this.visible = false;this.autoHideEnabled = false;this.contents = "";this.url="";this.windowProperties="toolbar=no,location=no,status=no,menubar=no,scrollbars=auto,resizable,alwaysRaised,dependent,titlebar=no";if(arguments.length>0){this.type="DIV";this.divName = arguments[0];}else{this.type="WINDOW";}this.use_gebi = false;this.use_css = false;this.use_layers = false;if(document.getElementById){this.use_gebi = true;}else if(document.all){this.use_css = true;}else if(document.layers){this.use_layers = true;}else{this.type = "WINDOW";}this.offsetX = 0;this.offsetY = 0;this.getXYPosition = PopupWindow_getXYPosition;this.populate = PopupWindow_populate;this.setUrl = PopupWindow_setUrl;this.setWindowProperties = PopupWindow_setWindowProperties;this.refresh = PopupWindow_refresh;this.showPopup = PopupWindow_showPopup;this.hidePopup = PopupWindow_hidePopup;this.setSize = PopupWindow_setSize;this.isClicked = PopupWindow_isClicked;this.autoHide = PopupWindow_autoHide;this.hideIfNotClicked = PopupWindow_hideIfNotClicked;}
+
+
+/* SOURCE FILE: CalendarPopup.js */
+
+function CalendarPopup(){var c;if(arguments.length>0){c = new PopupWindow(arguments[0]);}else{c = new PopupWindow();c.setSize(150,175);}c.offsetX = -152;c.offsetY = 25;c.autoHide();c.monthNames = new Array("January","February","March","April","May","June","July","August","September","October","November","December");c.monthAbbreviations = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");c.dayHeaders = new Array("S","M","T","W","T","F","S");c.returnFunction = "CP_tmpReturnFunction";c.returnMonthFunction = "CP_tmpReturnMonthFunction";c.returnQuarterFunction = "CP_tmpReturnQuarterFunction";c.returnYearFunction = "CP_tmpReturnYearFunction";c.weekStartDay = 0;c.isShowYearNavigation = false;c.displayType = "date";c.disabledWeekDays = new Object();c.disabledDatesExpression = "";c.yearSelectStartOffset = 2;c.currentDate = null;c.todayText="Today";c.cssPrefix="";c.isShowYearNavigationInput=false;window.CP_targetInput = null;window.CP_dateFormat = "MM/dd/yyyy";c.setReturnFunction = CP_setReturnFunction;c.setReturnMonthFunction = CP_setReturnMonthFunction;c.setReturnQuarterFunction = CP_setReturnQuarterFunction;c.setReturnYearFunction = CP_setReturnYearFunction;c.setMonthNames = CP_setMonthNames;c.setMonthAbbreviations = CP_setMonthAbbreviations;c.setDayHeaders = CP_setDayHeaders;c.setWeekStartDay = CP_setWeekStartDay;c.setDisplayType = CP_setDisplayType;c.setDisabledWeekDays = CP_setDisabledWeekDays;c.addDisabledDates = CP_addDisabledDates;c.setYearSelectStartOffset = CP_setYearSelectStartOffset;c.setTodayText = CP_setTodayText;c.showYearNavigation = CP_showYearNavigation;c.showCalendar = CP_showCalendar;c.hideCalendar = CP_hideCalendar;c.getStyles = getCalendarStyles;c.refreshCalendar = CP_refreshCalendar;c.getCalendar = CP_getCalendar;c.select = CP_select;c.setCssPrefix = CP_setCssPrefix;c.showYearNavigationInput = CP_showYearNavigationInput
+return c;}
+function CP_tmpReturnFunction(y,m,d){if(window.CP_targetInput!=null){var dt = new Date(y,m-1,d,0,0,0);window.CP_targetInput.value = formatDate(dt,window.CP_dateFormat);}else{alert('Use setReturnFunction() to define which function will get the clicked results!');}}
+function CP_tmpReturnMonthFunction(y,m){alert('Use setReturnMonthFunction() to define which function will get the clicked results!\nYou clicked: year='+y+' , month='+m);}
+function CP_tmpReturnQuarterFunction(y,q){alert('Use setReturnQuarterFunction() to define which function will get the clicked results!\nYou clicked: year='+y+' , quarter='+q);}
+function CP_tmpReturnYearFunction(y){alert('Use setReturnYearFunction() to define which function will get the clicked results!\nYou clicked: year='+y);}
+function CP_setReturnFunction(name){this.returnFunction = name;}
+function CP_setReturnMonthFunction(name){this.returnMonthFunction = name;}
+function CP_setReturnQuarterFunction(name){this.returnQuarterFunction = name;}
+function CP_setReturnYearFunction(name){this.returnYearFunction = name;}
+function CP_setMonthNames(){for(var i=0;i<arguments.length;i++){this.monthNames[i] = arguments[i];}}
+function CP_setMonthAbbreviations(){for(var i=0;i<arguments.length;i++){this.monthAbbreviations[i] = arguments[i];}}
+function CP_setDayHeaders(){for(var i=0;i<arguments.length;i++){this.dayHeaders[i] = arguments[i];}}
+function CP_setWeekStartDay(day){this.weekStartDay = day;}
+function CP_showYearNavigation(){this.isShowYearNavigation =(arguments.length>0)?arguments[0]:true;}
+function CP_setDisplayType(type){if(type!="date"&&type!="week-end"&&type!="month"&&type!="quarter"&&type!="year"){alert("Invalid display type! Must be one of: date,week-end,month,quarter,year");return false;}this.displayType=type;}
+function CP_setYearSelectStartOffset(num){this.yearSelectStartOffset=num;}
+function CP_setDisabledWeekDays(){this.disabledWeekDays = new Object();for(var i=0;i<arguments.length;i++){this.disabledWeekDays[arguments[i]] = true;}}
+function CP_addDisabledDates(start, end){if(arguments.length==1){end=start;}if(start==null && end==null){return;}if(this.disabledDatesExpression!=""){this.disabledDatesExpression+= "||";}if(start!=null){start = parseDate(start);start=""+start.getFullYear()+LZ(start.getMonth()+1)+LZ(start.getDate());}if(end!=null){end=parseDate(end);end=""+end.getFullYear()+LZ(end.getMonth()+1)+LZ(end.getDate());}if(start==null){this.disabledDatesExpression+="(ds<="+end+")";}else if(end  ==null){this.disabledDatesExpression+="(ds>="+start+")";}else{this.disabledDatesExpression+="(ds>="+start+"&&ds<="+end+")";}}
+function CP_setTodayText(text){this.todayText = text;}
+function CP_setCssPrefix(val){this.cssPrefix = val;}
+function CP_showYearNavigationInput(){this.isShowYearNavigationInput =(arguments.length>0)?arguments[0]:true;}
+function CP_hideCalendar(){if(arguments.length > 0){window.popupWindowObjects[arguments[0]].hidePopup();}else{this.hidePopup();}}
+function CP_refreshCalendar(index){var calObject = window.popupWindowObjects[index];if(arguments.length>1){calObject.populate(calObject.getCalendar(arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]));}else{calObject.populate(calObject.getCalendar());}calObject.refresh();}
+function CP_showCalendar(anchorname){if(arguments.length>1){if(arguments[1]==null||arguments[1]==""){this.currentDate=new Date();}else{this.currentDate=new Date(parseDate(arguments[1]));}}this.populate(this.getCalendar());this.showPopup(anchorname);}
+function CP_select(inputobj, linkname, format){var selectedDate=(arguments.length>3)?arguments[3]:null;if(!window.getDateFromFormat){alert("calendar.select: To use this method you must also include 'date.js' for date formatting");return;}if(this.displayType!="date"&&this.displayType!="week-end"){alert("calendar.select: This function can only be used with displayType 'date' or 'week-end'");return;}if(inputobj.type!="text" && inputobj.type!="hidden" && inputobj.type!="textarea"){alert("calendar.select: Input object passed is not a valid form input object");window.CP_targetInput=null;return;}window.CP_targetInput = inputobj;this.currentDate=null;var time=0;if(selectedDate!=null){time = getDateFromFormat(selectedDate,format)}else if(inputobj.value!=""){time = getDateFromFormat(inputobj.value,format);}if(selectedDate!=null || inputobj.value!=""){if(time==0){this.currentDate=null;}else{this.currentDate=new Date(time);}}window.CP_dateFormat = format;this.showCalendar(linkname);}
+function getCalendarStyles(){var result = "";var p = "";if(this!=null && typeof(this.cssPrefix)!="undefined" && this.cssPrefix!=null && this.cssPrefix!=""){p=this.cssPrefix;}result += "<STYLE>\n";result += "."+p+"cpYearNavigation,."+p+"cpMonthNavigation{background-color:#C0C0C0;text-align:center;vertical-align:center;text-decoration:none;color:#000000;font-weight:bold;}\n";result += "."+p+"cpDayColumnHeader, ."+p+"cpYearNavigation,."+p+"cpMonthNavigation,."+p+"cpCurrentMonthDate,."+p+"cpCurrentMonthDateDisabled,."+p+"cpOtherMonthDate,."+p+"cpOtherMonthDateDisabled,."+p+"cpCurrentDate,."+p+"cpCurrentDateDisabled,."+p+"cpTodayText,."+p+"cpTodayTextDisabled,."+p+"cpText{font-family:arial;font-size:8pt;}\n";result += "TD."+p+"cpDayColumnHeader{text-align:right;border:solid thin #C0C0C0;border-width:0 0 1 0;}\n";result += "."+p+"cpCurrentMonthDate, ."+p+"cpOtherMonthDate, ."+p+"cpCurrentDate{text-align:right;text-decoration:none;}\n";result += "."+p+"cpCurrentMonthDateDisabled, ."+p+"cpOtherMonthDateDisabled, ."+p+"cpCurrentDateDisabled{color:#D0D0D0;text-align:right;text-decoration:line-through;}\n";result += "."+p+"cpCurrentMonthDate, .cpCurrentDate{color:#000000;}\n";result += "."+p+"cpOtherMonthDate{color:#808080;}\n";result += "TD."+p+"cpCurrentDate{color:white;background-color: #C0C0C0;border-width:1;border:solid thin #800000;}\n";result += "TD."+p+"cpCurrentDateDisabled{border-width:1;border:solid thin #FFAAAA;}\n";result += "TD."+p+"cpTodayText, TD."+p+"cpTodayTextDisabled{border:solid thin #C0C0C0;border-width:1 0 0 0;}\n";result += "A."+p+"cpTodayText, SPAN."+p+"cpTodayTextDisabled{height:20px;}\n";result += "A."+p+"cpTodayText{color:black;}\n";result += "."+p+"cpTodayTextDisabled{color:#D0D0D0;}\n";result += "."+p+"cpBorder{border:solid thin #808080;}\n";result += "</STYLE>\n";return result;}
+function CP_getCalendar(){var now = new Date();if(this.type == "WINDOW"){var windowref = "window.opener.";}else{var windowref = "";}var result = "";if(this.type == "WINDOW"){result += "<HTML><HEAD><TITLE>Calendar</TITLE>"+this.getStyles()+"</HEAD><BODY MARGINWIDTH=0 MARGINHEIGHT=0 TOPMARGIN=0 RIGHTMARGIN=0 LEFTMARGIN=0>\n";result += '<CENTER><TABLE WIDTH=100% BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>\n';}else{result += '<TABLE CLASS="'+this.cssPrefix+'cpBorder" WIDTH=144 BORDER=1 BORDERWIDTH=1 CELLSPACING=0 CELLPADDING=1>\n';result += '<TR><TD ALIGN=CENTER>\n';result += '<CENTER>\n';}if(this.displayType=="date" || this.displayType=="week-end"){if(this.currentDate==null){this.currentDate = now;}if(arguments.length > 0){var month = arguments[0];}else{var month = this.currentDate.getMonth()+1;}if(arguments.length > 1 && arguments[1]>0 && arguments[1]-0==arguments[1]){var year = arguments[1];}else{var year = this.currentDate.getFullYear();}var daysinmonth= new Array(0,31,28,31,30,31,30,31,31,30,31,30,31);if( ((year%4 == 0)&&(year%100 != 0) ) ||(year%400 == 0) ){daysinmonth[2] = 29;}var current_month = new Date(year,month-1,1);var display_year = year;var display_month = month;var display_date = 1;var weekday= current_month.getDay();var offset = 0;offset =(weekday >= this.weekStartDay) ? weekday-this.weekStartDay : 7-this.weekStartDay+weekday ;if(offset > 0){display_month--;if(display_month < 1){display_month = 12;display_year--;}display_date = daysinmonth[display_month]-offset+1;}var next_month = month+1;var next_month_year = year;if(next_month > 12){next_month=1;next_month_year++;}var last_month = month-1;var last_month_year = year;if(last_month < 1){last_month=12;last_month_year--;}var date_class;if(this.type!="WINDOW"){result += "<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";}result += '<TR>\n';var refresh = 'javascript:'+windowref+'CP_refreshCalendar';if(this.isShowYearNavigation){result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refresh+'('+this.index+','+last_month+','+last_month_year+');">&lt;</A></TD>';result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="58"><SPAN CLASS="'+this.cssPrefix+'cpMonthNavigation">'+this.monthNames[month-1]+'</SPAN></TD>';result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refresh+'('+this.index+','+next_month+','+next_month_year+');">&gt;</A></TD>';result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10">&nbsp;</TD>';result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="'+refresh+'('+this.index+','+month+','+(year-1)+');">&lt;</A></TD>';if(this.isShowYearNavigationInput){result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="36"><INPUT NAME="cpYear" CLASS="'+this.cssPrefix+'cpYearNavigation" SIZE="4" MAXLENGTH="4" VALUE="'+year+'" onBlur="'+refresh+'('+this.index+','+month+',this.value-0);"></TD>';}else{result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="36"><SPAN CLASS="'+this.cssPrefix+'cpYearNavigation">'+year+'</SPAN></TD>';}result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="'+refresh+'('+this.index+','+month+','+(year+1)+');">&gt;</A></TD>';}else{result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refresh+'('+this.index+','+last_month+','+last_month_year+');">&lt;&lt;</A></TD>\n';result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="100"><SPAN CLASS="'+this.cssPrefix+'cpMonthNavigation">'+this.monthNames[month-1]+' '+year+'</SPAN></TD>\n';result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refresh+'('+this.index+','+next_month+','+next_month_year+');">&gt;&gt;</A></TD>\n';}result += '</TR></TABLE>\n';result += '<TABLE WIDTH=120 BORDER=0 CELLSPACING=0 CELLPADDING=1 ALIGN=CENTER>\n';result += '<TR>\n';for(var j=0;j<7;j++){result += '<TD CLASS="'+this.cssPrefix+'cpDayColumnHeader" WIDTH="14%"><SPAN CLASS="'+this.cssPrefix+'cpDayColumnHeader">'+this.dayHeaders[(this.weekStartDay+j)%7]+'</TD>\n';}result += '</TR>\n';for(var row=1;row<=6;row++){result += '<TR>\n';for(var col=1;col<=7;col++){var disabled=false;if(this.disabledDatesExpression!=""){var ds=""+display_year+LZ(display_month)+LZ(display_date);eval("disabled=("+this.disabledDatesExpression+")");}var dateClass = "";if((display_month == this.currentDate.getMonth()+1) &&(display_date==this.currentDate.getDate()) &&(display_year==this.currentDate.getFullYear())){dateClass = "cpCurrentDate";}else if(display_month == month){dateClass = "cpCurrentMonthDate";}else{dateClass = "cpOtherMonthDate";}if(disabled || this.disabledWeekDays[col-1]){result += '    <TD CLASS="'+this.cssPrefix+dateClass+'"><SPAN CLASS="'+this.cssPrefix+dateClass+'Disabled">'+display_date+'</SPAN></TD>\n';}else{var selected_date = display_date;var selected_month = display_month;var selected_year = display_year;if(this.displayType=="week-end"){var d = new Date(selected_year,selected_month-1,selected_date,0,0,0,0);d.setDate(d.getDate() +(7-col));selected_year = d.getYear();if(selected_year < 1000){selected_year += 1900;}selected_month = d.getMonth()+1;selected_date = d.getDate();}result += '     <TD CLASS="'+this.cssPrefix+dateClass+'"><A HREF="javascript:'+windowref+this.returnFunction+'('+selected_year+','+selected_month+','+selected_date+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+this.cssPrefix+dateClass+'">'+display_date+'</A></TD>\n';}display_date++;if(display_date > daysinmonth[display_month]){display_date=1;display_month++;}if(display_month > 12){display_month=1;display_year++;}}result += '</TR>';}var current_weekday = now.getDay() - this.weekStartDay;if(current_weekday < 0){current_weekday += 7;}result += '<TR>\n';result += '        <TD COLSPAN=7 ALIGN=CENTER CLASS="'+this.cssPrefix+'cpTodayText">\n';if(this.disabledDatesExpression!=""){var ds=""+now.getFullYear()+LZ(now.getMonth()+1)+LZ(now.getDate());eval("disabled=("+this.disabledDatesExpression+")");}if(disabled || this.disabledWeekDays[current_weekday+1]){result += '          <SPAN CLASS="'+this.cssPrefix+'cpTodayTextDisabled">'+this.todayText+'</SPAN>\n';}else{result += '              <A CLASS="'+this.cssPrefix+'cpTodayText" HREF="javascript:'+windowref+this.returnFunction+'(\''+now.getFullYear()+'\',\''+(now.getMonth()+1)+'\',\''+now.getDate()+'\');'+windowref+'CP_hideCalendar(\''+this.index+'\');">'+this.todayText+'</A>\n';}result += '               <BR>\n';result += '     </TD></TR></TABLE></CENTER></TD></TR></TABLE>\n';}if(this.displayType=="month" || this.displayType=="quarter" || this.displayType=="year"){if(arguments.length > 0){var year = arguments[0];}else{if(this.displayType=="year"){var year = now.getFullYear()-this.yearSelectStartOffset;}else{var year = now.getFullYear();}}if(this.displayType!="year" && this.isShowYearNavigation){result += "<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";result += '<TR>\n';result += '   <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year-1)+');">&lt;&lt;</A></TD>\n';result += '        <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="100">'+year+'</TD>\n';result += ' <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year+1)+');">&gt;&gt;</A></TD>\n';result += '</TR></TABLE>\n';}}if(this.displayType=="month"){result += '<TABLE WIDTH=120 BORDER=0 CELLSPACING=1 CELLPADDING=0 ALIGN=CENTER>\n';for(var i=0;i<4;i++){result += '<TR>';for(var j=0;j<3;j++){var monthindex =((i*3)+j);result += '<TD WIDTH=33% ALIGN=CENTER><A CLASS="'+this.cssPrefix+'cpText" HREF="javascript:'+windowref+this.returnMonthFunction+'('+year+','+(monthindex+1)+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+date_class+'">'+this.monthAbbreviations[monthindex]+'</A></TD>';}result += '</TR>';}result += '</TABLE></CENTER></TD></TR></TABLE>\n';}if(this.displayType=="quarter"){result += '<BR><TABLE WIDTH=120 BORDER=1 CELLSPACING=0 CELLPADDING=0 ALIGN=CENTER>\n';for(var i=0;i<2;i++){result += '<TR>';for(var j=0;j<2;j++){var quarter =((i*2)+j+1);result += '<TD WIDTH=50% ALIGN=CENTER><BR><A CLASS="'+this.cssPrefix+'cpText" HREF="javascript:'+windowref+this.returnQuarterFunction+'('+year+','+quarter+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+date_class+'">Q'+quarter+'</A><BR><BR></TD>';}result += '</TR>';}result += '</TABLE></CENTER></TD></TR></TABLE>\n';}if(this.displayType=="year"){var yearColumnSize = 4;result += "<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";result += '<TR>\n';result += '   <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="50%"><A CLASS="cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year-(yearColumnSize*2))+');">&lt;&lt;</A></TD>\n';result += '        <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="50%"><A CLASS="cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year+(yearColumnSize*2))+');">&gt;&gt;</A></TD>\n';result += '</TR></TABLE>\n';result += '<TABLE WIDTH=120 BORDER=0 CELLSPACING=1 CELLPADDING=0 ALIGN=CENTER>\n';for(var i=0;i<yearColumnSize;i++){for(var j=0;j<2;j++){var currentyear = year+(j*yearColumnSize)+i;result += '<TD WIDTH=50% ALIGN=CENTER><A CLASS="'+this.cssPrefix+'cpText" HREF="javascript:'+windowref+this.returnYearFunction+'('+currentyear+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+date_class+'">'+currentyear+'</A></TD>';}result += '</TR>';}result += '</TABLE></CENTER></TD></TR></TABLE>\n';}if(this.type == "WINDOW"){result += "</BODY></HTML>\n";}return result;}
+
diff --git a/Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib/AnchorPosition.js b/Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib/AnchorPosition.js
new file mode 100644 (file)
index 0000000..deb7922
--- /dev/null
@@ -0,0 +1,147 @@
+// ===================================================================
+// Author: Matt Kruse <matt@mattkruse.com>
+// WWW: http://www.mattkruse.com/
+//
+// NOTICE: You may use this code for any purpose, commercial or
+// private, without any further permission from the author. You may
+// remove this notice from your final code if you wish, however it is
+// appreciated by the author if at least my web site address is kept.
+//
+// You may *NOT* re-distribute this code in any way except through its
+// use. That means, you can include it in your product, or your web
+// site, or any other form where the code is actually being used. You
+// may not put the plain javascript up on your site for download or
+// include it in your javascript libraries for download. 
+// If you wish to share this code with others, please just point them
+// to the URL instead.
+// Please DO NOT link directly to my .js files from your site. Copy
+// the files to your server and use them there. Thank you.
+// ===================================================================
+
+/* 
+AnchorPosition.js
+Author: Matt Kruse
+Last modified: 10/11/02
+
+DESCRIPTION: These functions find the position of an <A> tag in a document,
+so other elements can be positioned relative to it.
+
+COMPATIBILITY: Netscape 4.x,6.x,Mozilla, IE 5.x,6.x on Windows. Some small
+positioning errors - usually with Window positioning - occur on the 
+Macintosh platform.
+
+FUNCTIONS:
+getAnchorPosition(anchorname)
+  Returns an Object() having .x and .y properties of the pixel coordinates
+  of the upper-left corner of the anchor. Position is relative to the PAGE.
+
+getAnchorWindowPosition(anchorname)
+  Returns an Object() having .x and .y properties of the pixel coordinates
+  of the upper-left corner of the anchor, relative to the WHOLE SCREEN.
+
+NOTES:
+
+1) For popping up separate browser windows, use getAnchorWindowPosition. 
+   Otherwise, use getAnchorPosition
+
+2) Your anchor tag MUST contain both NAME and ID attributes which are the 
+   same. For example:
+   <A NAME="test" ID="test"> </A>
+
+3) There must be at least a space between <A> </A> for IE5.5 to see the 
+   anchor tag correctly. Do not do <A></A> with no space.
+*/ 
+
+// getAnchorPosition(anchorname)
+//   This function returns an object having .x and .y properties which are the coordinates
+//   of the named anchor, relative to the page.
+function getAnchorPosition(anchorname) {
+       // This function will return an Object with x and y properties
+       var useWindow=false;
+       var coordinates=new Object();
+       var x=0,y=0;
+       // Browser capability sniffing
+       var use_gebi=false, use_css=false, use_layers=false;
+       if (document.getElementById) { use_gebi=true; }
+       else if (document.all) { use_css=true; }
+       else if (document.layers) { use_layers=true; }
+       // Logic to find position
+       if (use_gebi && document.all) {
+               x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]);
+               y=AnchorPosition_getPageOffsetTop(document.all[anchorname]);
+               }
+       else if (use_gebi) {
+               var o=document.getElementById(anchorname);
+               x=AnchorPosition_getPageOffsetLeft(o);
+               y=AnchorPosition_getPageOffsetTop(o);
+               }
+       else if (use_css) {
+               x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]);
+               y=AnchorPosition_getPageOffsetTop(document.all[anchorname]);
+               }
+       else if (use_layers) {
+               var found=0;
+               for (var i=0; i<document.anchors.length; i++) {
+                       if (document.anchors[i].name==anchorname) { found=1; break; }
+                       }
+               if (found==0) {
+                       coordinates.x=0; coordinates.y=0; return coordinates;
+                       }
+               x=document.anchors[i].x;
+               y=document.anchors[i].y;
+               }
+       else {
+               coordinates.x=0; coordinates.y=0; return coordinates;
+               }
+       coordinates.x=x;
+       coordinates.y=y;
+       return coordinates;
+       }
+
+// getAnchorWindowPosition(anchorname)
+//   This function returns an object having .x and .y properties which are the coordinates
+//   of the named anchor, relative to the window
+function getAnchorWindowPosition(anchorname) {
+       var coordinates=getAnchorPosition(anchorname);
+       var x=0;
+       var y=0;
+       if (document.getElementById) {
+               if (isNaN(window.screenX)) {
+                       x=coordinates.x-document.body.scrollLeft+window.screenLeft;
+                       y=coordinates.y-document.body.scrollTop+window.screenTop;
+                       }
+               else {
+                       x=coordinates.x+window.screenX+(window.outerWidth-window.innerWidth)-window.pageXOffset;
+                       y=coordinates.y+window.screenY+(window.outerHeight-24-window.innerHeight)-window.pageYOffset;
+                       }
+               }
+       else if (document.all) {
+               x=coordinates.x-document.body.scrollLeft+window.screenLeft;
+               y=coordinates.y-document.body.scrollTop+window.screenTop;
+               }
+       else if (document.layers) {
+               x=coordinates.x+window.screenX+(window.outerWidth-window.innerWidth)-window.pageXOffset;
+               y=coordinates.y+window.screenY+(window.outerHeight-24-window.innerHeight)-window.pageYOffset;
+               }
+       coordinates.x=x;
+       coordinates.y=y;
+       return coordinates;
+       }
+
+// Functions for IE to get position of an object
+function AnchorPosition_getPageOffsetLeft (el) {
+       var ol=el.offsetLeft;
+       while ((el=el.offsetParent) != null) { ol += el.offsetLeft; }
+       return ol;
+       }
+function AnchorPosition_getWindowOffsetLeft (el) {
+       return AnchorPosition_getPageOffsetLeft(el)-document.body.scrollLeft;
+       }       
+function AnchorPosition_getPageOffsetTop (el) {
+       var ot=el.offsetTop;
+       while((el=el.offsetParent) != null) { ot += el.offsetTop; }
+       return ot;
+       }
+function AnchorPosition_getWindowOffsetTop (el) {
+       return AnchorPosition_getPageOffsetTop(el)-document.body.scrollTop;
+       }
diff --git a/Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib/CalendarPopup.js b/Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib/CalendarPopup.js
new file mode 100644 (file)
index 0000000..65c8822
--- /dev/null
@@ -0,0 +1,688 @@
+// ===================================================================
+// Author: Matt Kruse <matt@mattkruse.com>
+// WWW: http://www.mattkruse.com/
+//
+// NOTICE: You may use this code for any purpose, commercial or
+// private, without any further permission from the author. You may
+// remove this notice from your final code if you wish, however it is
+// appreciated by the author if at least my web site address is kept.
+//
+// You may *NOT* re-distribute this code in any way except through its
+// use. That means, you can include it in your product, or your web
+// site, or any other form where the code is actually being used. You
+// may not put the plain javascript up on your site for download or
+// include it in your javascript libraries for download. 
+// If you wish to share this code with others, please just point them
+// to the URL instead.
+// Please DO NOT link directly to my .js files from your site. Copy
+// the files to your server and use them there. Thank you.
+// ===================================================================
+
+// HISTORY
+// ------------------------------------------------------------------
+// March 24, 2004: Fixed bug - when month name and abbreviations were
+//      changed, date format still used original values.
+// January 26, 2004: Added support for drop-down month and year
+//      navigation (Thanks to Chris Reid for the idea)
+// September 22, 2003: Fixed a minor problem in YEAR calendar with
+//      CSS prefix.
+// August 19, 2003: Renamed the function to get styles, and made it
+//      work correctly without an object reference
+// August 18, 2003: Changed showYearNavigation and 
+//      showYearNavigationInput to optionally take an argument of
+//      true or false
+// July 31, 2003: Added text input option for year navigation.
+//      Added a per-calendar CSS prefix option to optionally use 
+//      different styles for different calendars.
+// July 29, 2003: Fixed bug causing the Today link to be clickable 
+//      even though today falls in a disabled date range.
+//      Changed formatting to use pure CSS, allowing greater control
+//      over look-and-feel options.
+// June 11, 2003: Fixed bug causing the Today link to be unselectable
+//      under certain cases when some days of week are disabled
+// March 14, 2003: Added ability to disable individual dates or date
+//      ranges, display as light gray and strike-through
+// March 14, 2003: Removed dependency on graypixel.gif and instead 
+///     use table border coloring
+// March 12, 2003: Modified showCalendar() function to allow optional
+//      start-date parameter
+// March 11, 2003: Modified select() function to allow optional
+//      start-date parameter
+/* 
+DESCRIPTION: This object implements a popup calendar to allow the user to
+select a date, month, quarter, or year.
+
+COMPATABILITY: Works with Netscape 4.x, 6.x, IE 5.x on Windows. Some small
+positioning errors - usually with Window positioning - occur on the 
+Macintosh platform.
+The calendar can be modified to work for any location in the world by 
+changing which weekday is displayed as the first column, changing the month
+names, and changing the column headers for each day.
+
+USAGE:
+// Create a new CalendarPopup object of type WINDOW
+var cal = new CalendarPopup(); 
+
+// Create a new CalendarPopup object of type DIV using the DIV named 'mydiv'
+var cal = new CalendarPopup('mydiv'); 
+
+// Easy method to link the popup calendar with an input box. 
+cal.select(inputObject, anchorname, dateFormat);
+// Same method, but passing a default date other than the field's current value
+cal.select(inputObject, anchorname, dateFormat, '01/02/2000');
+// This is an example call to the popup calendar from a link to populate an 
+// input box. Note that to use this, date.js must also be included!!
+<A HREF="#" onClick="cal.select(document.forms[0].date,'anchorname','MM/dd/yyyy'); return false;">Select</A>
+
+// Set the type of date select to be used. By default it is 'date'.
+cal.setDisplayType(type);
+
+// When a date, month, quarter, or year is clicked, a function is called and
+// passed the details. You must write this function, and tell the calendar
+// popup what the function name is.
+// Function to be called for 'date' select receives y, m, d
+cal.setReturnFunction(functionname);
+// Function to be called for 'month' select receives y, m
+cal.setReturnMonthFunction(functionname);
+// Function to be called for 'quarter' select receives y, q
+cal.setReturnQuarterFunction(functionname);
+// Function to be called for 'year' select receives y
+cal.setReturnYearFunction(functionname);
+
+// Show the calendar relative to a given anchor
+cal.showCalendar(anchorname);
+
+// Hide the calendar. The calendar is set to autoHide automatically
+cal.hideCalendar();
+
+// Set the month names to be used. Default are English month names
+cal.setMonthNames("January","February","March",...);
+
+// Set the month abbreviations to be used. Default are English month abbreviations
+cal.setMonthAbbreviations("Jan","Feb","Mar",...);
+
+// Show navigation for changing by the year, not just one month at a time
+cal.showYearNavigation();
+
+// Show month and year dropdowns, for quicker selection of month of dates
+cal.showNavigationDropdowns();
+
+// Set the text to be used above each day column. The days start with 
+// sunday regardless of the value of WeekStartDay
+cal.setDayHeaders("S","M","T",...);
+
+// Set the day for the first column in the calendar grid. By default this
+// is Sunday (0) but it may be changed to fit the conventions of other
+// countries.
+cal.setWeekStartDay(1); // week is Monday - Saturday
+
+// Set the weekdays which should be disabled in the 'date' select popup. You can
+// then allow someone to only select week end dates, or Tuedays, for example
+cal.setDisabledWeekDays(0,1); // To disable selecting the 1st or 2nd days of the week
+
+// Selectively disable individual days or date ranges. Disabled days will not
+// be clickable, and show as strike-through text on current browsers.
+// Date format is any format recognized by parseDate() in date.js
+// Pass a single date to disable:
+cal.addDisabledDates("2003-01-01");
+// Pass null as the first parameter to mean "anything up to and including" the
+// passed date:
+cal.addDisabledDates(null, "01/02/03");
+// Pass null as the second parameter to mean "including the passed date and
+// anything after it:
+cal.addDisabledDates("Jan 01, 2003", null);
+// Pass two dates to disable all dates inbetween and including the two
+cal.addDisabledDates("January 01, 2003", "Dec 31, 2003");
+
+// When the 'year' select is displayed, set the number of years back from the 
+// current year to start listing years. Default is 2.
+// This is also used for year drop-down, to decide how many years +/- to display
+cal.setYearSelectStartOffset(2);
+
+// Text for the word "Today" appearing on the calendar
+cal.setTodayText("Today");
+
+// The calendar uses CSS classes for formatting. If you want your calendar to
+// have unique styles, you can set the prefix that will be added to all the
+// classes in the output.
+// For example, normal output may have this:
+//     <SPAN CLASS="cpTodayTextDisabled">Today<SPAN>
+// But if you set the prefix like this:
+cal.setCssPrefix("Test");
+// The output will then look like:
+//     <SPAN CLASS="TestcpTodayTextDisabled">Today<SPAN>
+// And you can define that style somewhere in your page.
+
+// When using Year navigation, you can make the year be an input box, so
+// the user can manually change it and jump to any year
+cal.showYearNavigationInput();
+
+// Set the calendar offset to be different than the default. By default it
+// will appear just below and to the right of the anchorname. So if you have
+// a text box where the date will go and and anchor immediately after the
+// text box, the calendar will display immediately under the text box.
+cal.offsetX = 20;
+cal.offsetY = 20;
+
+NOTES:
+1) Requires the functions in AnchorPosition.js and PopupWindow.js
+
+2) Your anchor tag MUST contain both NAME and ID attributes which are the 
+   same. For example:
+   <A NAME="test" ID="test"> </A>
+
+3) There must be at least a space between <A> </A> for IE5.5 to see the 
+   anchor tag correctly. Do not do <A></A> with no space.
+
+4) When a CalendarPopup object is created, a handler for 'onmouseup' is
+   attached to any event handler you may have already defined. Do NOT define
+   an event handler for 'onmouseup' after you define a CalendarPopup object 
+   or the autoHide() will not work correctly.
+   
+5) The calendar popup display uses style sheets to make it look nice.
+
+*/ 
+
+// CONSTRUCTOR for the CalendarPopup Object
+function CalendarPopup() {
+       var c;
+       if (arguments.length>0) {
+               c = new PopupWindow(arguments[0]);
+               }
+       else {
+               c = new PopupWindow();
+               c.setSize(150,175);
+               }
+       c.offsetX = -152;
+       c.offsetY = 25;
+       c.autoHide();
+       // Calendar-specific properties
+       c.monthNames = new Array("January","February","March","April","May","June","July","August","September","October","November","December");
+       c.monthAbbreviations = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
+       c.dayHeaders = new Array("S","M","T","W","T","F","S");
+       c.returnFunction = "CP_tmpReturnFunction";
+       c.returnMonthFunction = "CP_tmpReturnMonthFunction";
+       c.returnQuarterFunction = "CP_tmpReturnQuarterFunction";
+       c.returnYearFunction = "CP_tmpReturnYearFunction";
+       c.weekStartDay = 0;
+       c.isShowYearNavigation = false;
+       c.displayType = "date";
+       c.disabledWeekDays = new Object();
+       c.disabledDatesExpression = "";
+       c.yearSelectStartOffset = 2;
+       c.currentDate = null;
+       c.todayText="Today";
+       c.cssPrefix="";
+       c.isShowNavigationDropdowns=false;
+       c.isShowYearNavigationInput=false;
+       window.CP_calendarObject = null;
+       window.CP_targetInput = null;
+       window.CP_dateFormat = "MM/dd/yyyy";
+       // Method mappings
+       c.copyMonthNamesToWindow = CP_copyMonthNamesToWindow;
+       c.setReturnFunction = CP_setReturnFunction;
+       c.setReturnMonthFunction = CP_setReturnMonthFunction;
+       c.setReturnQuarterFunction = CP_setReturnQuarterFunction;
+       c.setReturnYearFunction = CP_setReturnYearFunction;
+       c.setMonthNames = CP_setMonthNames;
+       c.setMonthAbbreviations = CP_setMonthAbbreviations;
+       c.setDayHeaders = CP_setDayHeaders;
+       c.setWeekStartDay = CP_setWeekStartDay;
+       c.setDisplayType = CP_setDisplayType;
+       c.setDisabledWeekDays = CP_setDisabledWeekDays;
+       c.addDisabledDates = CP_addDisabledDates;
+       c.setYearSelectStartOffset = CP_setYearSelectStartOffset;
+       c.setTodayText = CP_setTodayText;
+       c.showYearNavigation = CP_showYearNavigation;
+       c.showCalendar = CP_showCalendar;
+       c.hideCalendar = CP_hideCalendar;
+       c.getStyles = getCalendarStyles;
+       c.refreshCalendar = CP_refreshCalendar;
+       c.getCalendar = CP_getCalendar;
+       c.select = CP_select;
+       c.setCssPrefix = CP_setCssPrefix;
+       c.showNavigationDropdowns = CP_showNavigationDropdowns;
+       c.showYearNavigationInput = CP_showYearNavigationInput;
+       c.copyMonthNamesToWindow();
+       // Return the object
+       return c;
+       }
+function CP_copyMonthNamesToWindow() {
+       // Copy these values over to the date.js 
+       if (typeof(window.MONTH_NAMES)!="undefined" && window.MONTH_NAMES!=null) {
+               window.MONTH_NAMES = new Array();
+               for (var i=0; i<this.monthNames.length; i++) {
+                       window.MONTH_NAMES[window.MONTH_NAMES.length] = this.monthNames[i];
+               }
+               for (var i=0; i<this.monthAbbreviations.length; i++) {
+                       window.MONTH_NAMES[window.MONTH_NAMES.length] = this.monthAbbreviations[i];
+               }
+       }
+}
+// Temporary default functions to be called when items clicked, so no error is thrown
+function CP_tmpReturnFunction(y,m,d) { 
+       if (window.CP_targetInput!=null) {
+               var dt = new Date(y,m-1,d,0,0,0);
+               if (window.CP_calendarObject!=null) { window.CP_calendarObject.copyMonthNamesToWindow(); }
+               window.CP_targetInput.value = formatDate(dt,window.CP_dateFormat);
+               }
+       else {
+               alert('Use setReturnFunction() to define which function will get the clicked results!'); 
+               }
+       }
+function CP_tmpReturnMonthFunction(y,m) { 
+       alert('Use setReturnMonthFunction() to define which function will get the clicked results!\nYou clicked: year='+y+' , month='+m); 
+       }
+function CP_tmpReturnQuarterFunction(y,q) { 
+       alert('Use setReturnQuarterFunction() to define which function will get the clicked results!\nYou clicked: year='+y+' , quarter='+q); 
+       }
+function CP_tmpReturnYearFunction(y) { 
+       alert('Use setReturnYearFunction() to define which function will get the clicked results!\nYou clicked: year='+y); 
+       }
+
+// Set the name of the functions to call to get the clicked item
+function CP_setReturnFunction(name) { this.returnFunction = name; }
+function CP_setReturnMonthFunction(name) { this.returnMonthFunction = name; }
+function CP_setReturnQuarterFunction(name) { this.returnQuarterFunction = name; }
+function CP_setReturnYearFunction(name) { this.returnYearFunction = name; }
+
+// Over-ride the built-in month names
+function CP_setMonthNames() {
+       for (var i=0; i<arguments.length; i++) { this.monthNames[i] = arguments[i]; }
+       this.copyMonthNamesToWindow();
+       }
+
+// Over-ride the built-in month abbreviations
+function CP_setMonthAbbreviations() {
+       for (var i=0; i<arguments.length; i++) { this.monthAbbreviations[i] = arguments[i]; }
+       this.copyMonthNamesToWindow();
+       }
+
+// Over-ride the built-in column headers for each day
+function CP_setDayHeaders() {
+       for (var i=0; i<arguments.length; i++) { this.dayHeaders[i] = arguments[i]; }
+       }
+
+// Set the day of the week (0-7) that the calendar display starts on
+// This is for countries other than the US whose calendar displays start on Monday(1), for example
+function CP_setWeekStartDay(day) { this.weekStartDay = day; }
+
+// Show next/last year navigation links
+function CP_showYearNavigation() { this.isShowYearNavigation = (arguments.length>0)?arguments[0]:true; }
+
+// Which type of calendar to display
+function CP_setDisplayType(type) {
+       if (type!="date"&&type!="week-end"&&type!="month"&&type!="quarter"&&type!="year") { alert("Invalid display type! Must be one of: date,week-end,month,quarter,year"); return false; }
+       this.displayType=type;
+       }
+
+// How many years back to start by default for year display
+function CP_setYearSelectStartOffset(num) { this.yearSelectStartOffset=num; }
+
+// Set which weekdays should not be clickable
+function CP_setDisabledWeekDays() {
+       this.disabledWeekDays = new Object();
+       for (var i=0; i<arguments.length; i++) { this.disabledWeekDays[arguments[i]] = true; }
+       }
+       
+// Disable individual dates or ranges
+// Builds an internal logical test which is run via eval() for efficiency
+function CP_addDisabledDates(start, end) {
+       if (arguments.length==1) { end=start; }
+       if (start==null && end==null) { return; }
+       if (this.disabledDatesExpression!="") { this.disabledDatesExpression+= "||"; }
+       if (start!=null) { start = parseDate(start); start=""+start.getFullYear()+LZ(start.getMonth()+1)+LZ(start.getDate());}
+       if (end!=null) { end=parseDate(end); end=""+end.getFullYear()+LZ(end.getMonth()+1)+LZ(end.getDate());}
+       if (start==null) { this.disabledDatesExpression+="(ds<="+end+")"; }
+       else if (end  ==null) { this.disabledDatesExpression+="(ds>="+start+")"; }
+       else { this.disabledDatesExpression+="(ds>="+start+"&&ds<="+end+")"; }
+       }
+       
+// Set the text to use for the "Today" link
+function CP_setTodayText(text) {
+       this.todayText = text;
+       }
+
+// Set the prefix to be added to all CSS classes when writing output
+function CP_setCssPrefix(val) { 
+       this.cssPrefix = val; 
+       }
+
+// Show the navigation as an dropdowns that can be manually changed
+function CP_showNavigationDropdowns() { this.isShowNavigationDropdowns = (arguments.length>0)?arguments[0]:true; }
+
+// Show the year navigation as an input box that can be manually changed
+function CP_showYearNavigationInput() { this.isShowYearNavigationInput = (arguments.length>0)?arguments[0]:true; }
+
+// Hide a calendar object
+function CP_hideCalendar() {
+       if (arguments.length > 0) { window.popupWindowObjects[arguments[0]].hidePopup(); }
+       else { this.hidePopup(); }
+       }
+
+// Refresh the contents of the calendar display
+function CP_refreshCalendar(index) {
+       var calObject = window.popupWindowObjects[index];
+       if (arguments.length>1) { 
+               calObject.populate(calObject.getCalendar(arguments[1],arguments[2],arguments[3],arguments[4],arguments[5]));
+               }
+       else {
+               calObject.populate(calObject.getCalendar());
+               }
+       calObject.refresh();
+       }
+
+// Populate the calendar and display it
+function CP_showCalendar(anchorname) {
+       if (arguments.length>1) {
+               if (arguments[1]==null||arguments[1]=="") {
+                       this.currentDate=new Date();
+                       }
+               else {
+                       this.currentDate=new Date(parseDate(arguments[1]));
+                       }
+               }
+       this.populate(this.getCalendar());
+       this.showPopup(anchorname);
+       }
+
+// Simple method to interface popup calendar with a text-entry box
+function CP_select(inputobj, linkname, format) {
+       var selectedDate=(arguments.length>3)?arguments[3]:null;
+       if (!window.getDateFromFormat) {
+               alert("calendar.select: To use this method you must also include 'date.js' for date formatting");
+               return;
+               }
+       if (this.displayType!="date"&&this.displayType!="week-end") {
+               alert("calendar.select: This function can only be used with displayType 'date' or 'week-end'");
+               return;
+               }
+       if (inputobj.type!="text" && inputobj.type!="hidden" && inputobj.type!="textarea") { 
+               alert("calendar.select: Input object passed is not a valid form input object"); 
+               window.CP_targetInput=null;
+               return;
+               }
+       window.CP_targetInput = inputobj;
+       window.CP_calendarObject = this;
+       this.currentDate=null;
+       var time=0;
+       if (selectedDate!=null) {
+               time = getDateFromFormat(selectedDate,format)
+               }
+       else if (inputobj.value!="") {
+               time = getDateFromFormat(inputobj.value,format);
+               }
+       if (selectedDate!=null || inputobj.value!="") {
+               if (time==0) { this.currentDate=null; }
+               else { this.currentDate=new Date(time); }
+               }
+       window.CP_dateFormat = format;
+       this.showCalendar(linkname);
+       }
+       
+// Get style block needed to display the calendar correctly
+function getCalendarStyles() {
+       var result = "";
+       var p = "";
+       if (this!=null && typeof(this.cssPrefix)!="undefined" && this.cssPrefix!=null && this.cssPrefix!="") { p=this.cssPrefix; }
+       result += "<STYLE>\n";
+       result += "."+p+"cpYearNavigation,."+p+"cpMonthNavigation { background-color:#C0C0C0; text-align:center; vertical-align:center; text-decoration:none; color:#000000; font-weight:bold; }\n";
+       result += "."+p+"cpDayColumnHeader, ."+p+"cpYearNavigation,."+p+"cpMonthNavigation,."+p+"cpCurrentMonthDate,."+p+"cpCurrentMonthDateDisabled,."+p+"cpOtherMonthDate,."+p+"cpOtherMonthDateDisabled,."+p+"cpCurrentDate,."+p+"cpCurrentDateDisabled,."+p+"cpTodayText,."+p+"cpTodayTextDisabled,."+p+"cpText { font-family:arial; font-size:8pt; }\n";
+       result += "TD."+p+"cpDayColumnHeader { text-align:right; border:solid thin #C0C0C0;border-width:0 0 1 0; }\n";
+       result += "."+p+"cpCurrentMonthDate, ."+p+"cpOtherMonthDate, ."+p+"cpCurrentDate  { text-align:right; text-decoration:none; }\n";
+       result += "."+p+"cpCurrentMonthDateDisabled, ."+p+"cpOtherMonthDateDisabled, ."+p+"cpCurrentDateDisabled { color:#D0D0D0; text-align:right; text-decoration:line-through; }\n";
+       result += "."+p+"cpCurrentMonthDate, .cpCurrentDate { color:#000000; }\n";
+       result += "."+p+"cpOtherMonthDate { color:#808080; }\n";
+       result += "TD."+p+"cpCurrentDate { color:white; background-color: #C0C0C0; border-width:1; border:solid thin #800000; }\n";
+       result += "TD."+p+"cpCurrentDateDisabled { border-width:1; border:solid thin #FFAAAA; }\n";
+       result += "TD."+p+"cpTodayText, TD."+p+"cpTodayTextDisabled { border:solid thin #C0C0C0; border-width:1 0 0 0;}\n";
+       result += "A."+p+"cpTodayText, SPAN."+p+"cpTodayTextDisabled { height:20px; }\n";
+       result += "A."+p+"cpTodayText { color:black; }\n";
+       result += "."+p+"cpTodayTextDisabled { color:#D0D0D0; }\n";
+       result += "."+p+"cpBorder { border:solid thin #808080; }\n";
+       result += "</STYLE>\n";
+       return result;
+       }
+
+// Return a string containing all the calendar code to be displayed
+function CP_getCalendar() {
+       var now = new Date();
+       // Reference to window
+       if (this.type == "WINDOW") { var windowref = "window.opener."; }
+       else { var windowref = ""; }
+       var result = "";
+       // If POPUP, write entire HTML document
+       if (this.type == "WINDOW") {
+               result += "<HTML><HEAD><TITLE>Calendar</TITLE>"+this.getStyles()+"</HEAD><BODY MARGINWIDTH=0 MARGINHEIGHT=0 TOPMARGIN=0 RIGHTMARGIN=0 LEFTMARGIN=0>\n";
+               result += '<CENTER><TABLE WIDTH=100% BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>\n';
+               }
+       else {
+               result += '<TABLE CLASS="'+this.cssPrefix+'cpBorder" WIDTH=144 BORDER=1 BORDERWIDTH=1 CELLSPACING=0 CELLPADDING=1>\n';
+               result += '<TR><TD ALIGN=CENTER>\n';
+               result += '<CENTER>\n';
+               }
+       // Code for DATE display (default)
+       // -------------------------------
+       if (this.displayType=="date" || this.displayType=="week-end") {
+               if (this.currentDate==null) { this.currentDate = now; }
+               if (arguments.length > 0) { var month = arguments[0]; }
+                       else { var month = this.currentDate.getMonth()+1; }
+               if (arguments.length > 1 && arguments[1]>0 && arguments[1]-0==arguments[1]) { var year = arguments[1]; }
+                       else { var year = this.currentDate.getFullYear(); }
+               var daysinmonth= new Array(0,31,28,31,30,31,30,31,31,30,31,30,31);
+               if ( ( (year%4 == 0)&&(year%100 != 0) ) || (year%400 == 0) ) {
+                       daysinmonth[2] = 29;
+                       }
+               var current_month = new Date(year,month-1,1);
+               var display_year = year;
+               var display_month = month;
+               var display_date = 1;
+               var weekday= current_month.getDay();
+               var offset = 0;
+               
+               offset = (weekday >= this.weekStartDay) ? weekday-this.weekStartDay : 7-this.weekStartDay+weekday ;
+               if (offset > 0) {
+                       display_month--;
+                       if (display_month < 1) { display_month = 12; display_year--; }
+                       display_date = daysinmonth[display_month]-offset+1;
+                       }
+               var next_month = month+1;
+               var next_month_year = year;
+               if (next_month > 12) { next_month=1; next_month_year++; }
+               var last_month = month-1;
+               var last_month_year = year;
+               if (last_month < 1) { last_month=12; last_month_year--; }
+               var date_class;
+               if (this.type!="WINDOW") {
+                       result += "<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";
+                       }
+               result += '<TR>\n';
+               var refresh = windowref+'CP_refreshCalendar';
+               var refreshLink = 'javascript:' + refresh;
+               if (this.isShowNavigationDropdowns) {
+                       result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="78" COLSPAN="3"><select CLASS="'+this.cssPrefix+'cpMonthNavigation" name="cpMonth" onChange="'+refresh+'('+this.index+',this.options[this.selectedIndex].value-0,'+(year-0)+');">';
+                       for( var monthCounter=1; monthCounter<=12; monthCounter++ ) {
+                               var selected = (monthCounter==month) ? 'SELECTED' : '';
+                               result += '<option value="'+monthCounter+'" '+selected+'>'+this.monthNames[monthCounter-1]+'</option>';
+                               }
+                       result += '</select></TD>';
+                       result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10">&nbsp;</TD>';
+
+                       result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="56" COLSPAN="3"><select CLASS="'+this.cssPrefix+'cpYearNavigation" name="cpYear" onChange="'+refresh+'('+this.index+','+month+',this.options[this.selectedIndex].value-0);">';
+                       for( var yearCounter=year-this.yearSelectStartOffset; yearCounter<=year+this.yearSelectStartOffset; yearCounter++ ) {
+                               var selected = (yearCounter==year) ? 'SELECTED' : '';
+                               result += '<option value="'+yearCounter+'" '+selected+'>'+yearCounter+'</option>';
+                               }
+                       result += '</select></TD>';
+                       }
+               else {
+                       if (this.isShowYearNavigation) {
+                               result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+last_month+','+last_month_year+');">&lt;</A></TD>';
+                               result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="58"><SPAN CLASS="'+this.cssPrefix+'cpMonthNavigation">'+this.monthNames[month-1]+'</SPAN></TD>';
+                               result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+next_month+','+next_month_year+');">&gt;</A></TD>';
+                               result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="10">&nbsp;</TD>';
+
+                               result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="'+refreshLink+'('+this.index+','+month+','+(year-1)+');">&lt;</A></TD>';
+                               if (this.isShowYearNavigationInput) {
+                                       result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="36"><INPUT NAME="cpYear" CLASS="'+this.cssPrefix+'cpYearNavigation" SIZE="4" MAXLENGTH="4" VALUE="'+year+'" onBlur="'+refresh+'('+this.index+','+month+',this.value-0);"></TD>';
+                                       }
+                               else {
+                                       result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="36"><SPAN CLASS="'+this.cssPrefix+'cpYearNavigation">'+year+'</SPAN></TD>';
+                                       }
+                               result += '<TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="10"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="'+refreshLink+'('+this.index+','+month+','+(year+1)+');">&gt;</A></TD>';
+                               }
+                       else {
+                               result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+last_month+','+last_month_year+');">&lt;&lt;</A></TD>\n';
+                               result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="100"><SPAN CLASS="'+this.cssPrefix+'cpMonthNavigation">'+this.monthNames[month-1]+' '+year+'</SPAN></TD>\n';
+                               result += '<TD CLASS="'+this.cssPrefix+'cpMonthNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpMonthNavigation" HREF="'+refreshLink+'('+this.index+','+next_month+','+next_month_year+');">&gt;&gt;</A></TD>\n';
+                               }
+                       }
+               result += '</TR></TABLE>\n';
+               result += '<TABLE WIDTH=120 BORDER=0 CELLSPACING=0 CELLPADDING=1 ALIGN=CENTER>\n';
+               result += '<TR>\n';
+               for (var j=0; j<7; j++) {
+
+                       result += '<TD CLASS="'+this.cssPrefix+'cpDayColumnHeader" WIDTH="14%"><SPAN CLASS="'+this.cssPrefix+'cpDayColumnHeader">'+this.dayHeaders[(this.weekStartDay+j)%7]+'</TD>\n';
+                       }
+               result += '</TR>\n';
+               for (var row=1; row<=6; row++) {
+                       result += '<TR>\n';
+                       for (var col=1; col<=7; col++) {
+                               var disabled=false;
+                               if (this.disabledDatesExpression!="") {
+                                       var ds=""+display_year+LZ(display_month)+LZ(display_date);
+                                       eval("disabled=("+this.disabledDatesExpression+")");
+                                       }
+                               var dateClass = "";
+                               if ((display_month == this.currentDate.getMonth()+1) && (display_date==this.currentDate.getDate()) && (display_year==this.currentDate.getFullYear())) {
+                                       dateClass = "cpCurrentDate";
+                                       }
+                               else if (display_month == month) {
+                                       dateClass = "cpCurrentMonthDate";
+                                       }
+                               else {
+                                       dateClass = "cpOtherMonthDate";
+                                       }
+                               if (disabled || this.disabledWeekDays[col-1]) {
+                                       result += '     <TD CLASS="'+this.cssPrefix+dateClass+'"><SPAN CLASS="'+this.cssPrefix+dateClass+'Disabled">'+display_date+'</SPAN></TD>\n';
+                                       }
+                               else {
+                                       var selected_date = display_date;
+                                       var selected_month = display_month;
+                                       var selected_year = display_year;
+                                       if (this.displayType=="week-end") {
+                                               var d = new Date(selected_year,selected_month-1,selected_date,0,0,0,0);
+                                               d.setDate(d.getDate() + (7-col));
+                                               selected_year = d.getYear();
+                                               if (selected_year < 1000) { selected_year += 1900; }
+                                               selected_month = d.getMonth()+1;
+                                               selected_date = d.getDate();
+                                               }
+                                       result += '     <TD CLASS="'+this.cssPrefix+dateClass+'"><A HREF="javascript:'+windowref+this.returnFunction+'('+selected_year+','+selected_month+','+selected_date+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+this.cssPrefix+dateClass+'">'+display_date+'</A></TD>\n';
+                                       }
+                               display_date++;
+                               if (display_date > daysinmonth[display_month]) {
+                                       display_date=1;
+                                       display_month++;
+                                       }
+                               if (display_month > 12) {
+                                       display_month=1;
+                                       display_year++;
+                                       }
+                               }
+                       result += '</TR>';
+                       }
+               var current_weekday = now.getDay() - this.weekStartDay;
+               if (current_weekday < 0) {
+                       current_weekday += 7;
+                       }
+               result += '<TR>\n';
+               result += '     <TD COLSPAN=7 ALIGN=CENTER CLASS="'+this.cssPrefix+'cpTodayText">\n';
+               if (this.disabledDatesExpression!="") {
+                       var ds=""+now.getFullYear()+LZ(now.getMonth()+1)+LZ(now.getDate());
+                       eval("disabled=("+this.disabledDatesExpression+")");
+                       }
+               if (disabled || this.disabledWeekDays[current_weekday+1]) {
+                       result += '             <SPAN CLASS="'+this.cssPrefix+'cpTodayTextDisabled">'+this.todayText+'</SPAN>\n';
+                       }
+               else {
+                       result += '             <A CLASS="'+this.cssPrefix+'cpTodayText" HREF="javascript:'+windowref+this.returnFunction+'(\''+now.getFullYear()+'\',\''+(now.getMonth()+1)+'\',\''+now.getDate()+'\');'+windowref+'CP_hideCalendar(\''+this.index+'\');">'+this.todayText+'</A>\n';
+                       }
+               result += '             <BR>\n';
+               result += '     </TD></TR></TABLE></CENTER></TD></TR></TABLE>\n';
+       }
+
+       // Code common for MONTH, QUARTER, YEAR
+       // ------------------------------------
+       if (this.displayType=="month" || this.displayType=="quarter" || this.displayType=="year") {
+               if (arguments.length > 0) { var year = arguments[0]; }
+               else { 
+                       if (this.displayType=="year") { var year = now.getFullYear()-this.yearSelectStartOffset; }
+                       else { var year = now.getFullYear(); }
+                       }
+               if (this.displayType!="year" && this.isShowYearNavigation) {
+                       result += "<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";
+                       result += '<TR>\n';
+                       result += '     <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year-1)+');">&lt;&lt;</A></TD>\n';
+                       result += '     <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="100">'+year+'</TD>\n';
+                       result += '     <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="22"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year+1)+');">&gt;&gt;</A></TD>\n';
+                       result += '</TR></TABLE>\n';
+                       }
+               }
+               
+       // Code for MONTH display 
+       // ----------------------
+       if (this.displayType=="month") {
+               // If POPUP, write entire HTML document
+               result += '<TABLE WIDTH=120 BORDER=0 CELLSPACING=1 CELLPADDING=0 ALIGN=CENTER>\n';
+               for (var i=0; i<4; i++) {
+                       result += '<TR>';
+                       for (var j=0; j<3; j++) {
+                               var monthindex = ((i*3)+j);
+                               result += '<TD WIDTH=33% ALIGN=CENTER><A CLASS="'+this.cssPrefix+'cpText" HREF="javascript:'+windowref+this.returnMonthFunction+'('+year+','+(monthindex+1)+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+date_class+'">'+this.monthAbbreviations[monthindex]+'</A></TD>';
+                               }
+                       result += '</TR>';
+                       }
+               result += '</TABLE></CENTER></TD></TR></TABLE>\n';
+               }
+       
+       // Code for QUARTER display
+       // ------------------------
+       if (this.displayType=="quarter") {
+               result += '<BR><TABLE WIDTH=120 BORDER=1 CELLSPACING=0 CELLPADDING=0 ALIGN=CENTER>\n';
+               for (var i=0; i<2; i++) {
+                       result += '<TR>';
+                       for (var j=0; j<2; j++) {
+                               var quarter = ((i*2)+j+1);
+                               result += '<TD WIDTH=50% ALIGN=CENTER><BR><A CLASS="'+this.cssPrefix+'cpText" HREF="javascript:'+windowref+this.returnQuarterFunction+'('+year+','+quarter+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+date_class+'">Q'+quarter+'</A><BR><BR></TD>';
+                               }
+                       result += '</TR>';
+                       }
+               result += '</TABLE></CENTER></TD></TR></TABLE>\n';
+               }
+
+       // Code for YEAR display
+       // ---------------------
+       if (this.displayType=="year") {
+               var yearColumnSize = 4;
+               result += "<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";
+               result += '<TR>\n';
+               result += '     <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="50%"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year-(yearColumnSize*2))+');">&lt;&lt;</A></TD>\n';
+               result += '     <TD CLASS="'+this.cssPrefix+'cpYearNavigation" WIDTH="50%"><A CLASS="'+this.cssPrefix+'cpYearNavigation" HREF="javascript:'+windowref+'CP_refreshCalendar('+this.index+','+(year+(yearColumnSize*2))+');">&gt;&gt;</A></TD>\n';
+               result += '</TR></TABLE>\n';
+               result += '<TABLE WIDTH=120 BORDER=0 CELLSPACING=1 CELLPADDING=0 ALIGN=CENTER>\n';
+               for (var i=0; i<yearColumnSize; i++) {
+                       for (var j=0; j<2; j++) {
+                               var currentyear = year+(j*yearColumnSize)+i;
+                               result += '<TD WIDTH=50% ALIGN=CENTER><A CLASS="'+this.cssPrefix+'cpText" HREF="javascript:'+windowref+this.returnYearFunction+'('+currentyear+');'+windowref+'CP_hideCalendar(\''+this.index+'\');" CLASS="'+date_class+'">'+currentyear+'</A></TD>';
+                               }
+                       result += '</TR>';
+                       }
+               result += '</TABLE></CENTER></TD></TR></TABLE>\n';
+               }
+       // Common
+       if (this.type == "WINDOW") {
+               result += "</BODY></HTML>\n";
+               }
+       return result;
+       }
diff --git a/Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib/OptionTransfer.js b/Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib/OptionTransfer.js
new file mode 100644 (file)
index 0000000..4e19afa
--- /dev/null
@@ -0,0 +1,187 @@
+// ===================================================================
+// Author: Matt Kruse <matt@mattkruse.com>
+// WWW: http://www.mattkruse.com/
+//
+// NOTICE: You may use this code for any purpose, commercial or
+// private, without any further permission from the author. You may
+// remove this notice from your final code if you wish, however it is
+// appreciated by the author if at least my web site address is kept.
+//
+// You may *NOT* re-distribute this code in any way except through its
+// use. That means, you can include it in your product, or your web
+// site, or any other form where the code is actually being used. You
+// may not put the plain javascript up on your site for download or
+// include it in your javascript libraries for download. 
+// If you wish to share this code with others, please just point them
+// to the URL instead.
+// Please DO NOT link directly to my .js files from your site. Copy
+// the files to your server and use them there. Thank you.
+// ===================================================================
+
+/* 
+OptionTransfer.js
+Last Modified: 11/18/2002
+
+DESCRIPTION: This widget is used to easily and quickly create an interface
+where the user can transfer choices from one select box to another. For
+example, when selecting which columns to show or hide in search results.
+This object adds value by automatically storing the values that were added
+or removed from each list, as well as the state of the final list. 
+
+COMPATIBILITY: Should work on all Javascript-compliant browsers.
+
+USAGE:
+// Create a new OptionTransfer object. Pass it the field names of the left
+// select box and the right select box.
+var ot = new OptionTransfer("from","to");
+
+// Optionally tell the lists whether or not to auto-sort when options are 
+// moved. By default, the lists will be sorted.
+ot.setAutoSort(true);
+
+// Optionally set the delimiter to be used to separate values that are
+// stored in hidden fields for the added and removed options, as well as
+// final state of the lists. Defaults to a comma.
+ot.setDelimiter("|");
+
+// These functions assign the form fields which will store the state of
+// the lists. Each one is optional, so you can pick to only store the
+// new options which were transferred to the right list, for example.
+// Each function takes the name of a HIDDEN or TEXT input field.
+
+// Store list of options removed from left list into an input field
+ot.saveRemovedLeftOptions("removedLeft");
+// Store list of options removed from right list into an input field
+ot.saveRemovedRightOptions("removedRight");
+// Store list of options added to left list into an input field
+ot.saveAddedLeftOptions("addedLeft");
+// Store list of options radded to right list into an input field
+ot.saveAddedRightOptions("addedRight");
+// Store all options existing in the left list into an input field
+ot.saveNewLeftOptions("newLeft");
+// Store all options existing in the right list into an input field
+ot.saveNewRightOptions("newRight");
+
+// IMPORTANT: This step is required for the OptionTransfer object to work
+// correctly.
+// Add a call to the BODY onLoad="" tag of the page, and pass a reference to
+// the form which contains the select boxes and input fields.
+BODY onLoad="ot.init(document.forms[0])"
+
+// ADDING ACTIONS INTO YOUR PAGE
+// Finally, add calls to the object to move options back and forth, either
+// from links in your page or from double-clicking the options themselves.
+// See example page, and use the following methods:
+ot.transferRight();
+ot.transferAllRight();
+ot.transferLeft();
+ot.transferAllLeft();
+
+
+NOTES:
+1) Requires the functions in selectbox.js
+
+*/ 
+function OT_transferLeft() { moveSelectedOptions(this.right,this.left,this.autoSort); this.update(); }
+function OT_transferRight() { moveSelectedOptions(this.left,this.right,this.autoSort); this.update(); }
+function OT_transferAllLeft() { moveAllOptions(this.right,this.left,this.autoSort); this.update(); }
+function OT_transferAllRight() { moveAllOptions(this.left,this.right,this.autoSort); this.update(); }
+function OT_saveRemovedLeftOptions(f) { this.removedLeftField = f; }
+function OT_saveRemovedRightOptions(f) { this.removedRightField = f; }
+function OT_saveAddedLeftOptions(f) { this.addedLeftField = f; }
+function OT_saveAddedRightOptions(f) { this.addedRightField = f; }
+function OT_saveNewLeftOptions(f) { this.newLeftField = f; }
+function OT_saveNewRightOptions(f) { this.newRightField = f; }
+function OT_update() {
+       var removedLeft = new Object();
+       var removedRight = new Object();
+       var addedLeft = new Object();
+       var addedRight = new Object();
+       var newLeft = new Object();
+       var newRight = new Object();
+       for (var i=0;i<this.left.options.length;i++) {
+               var o=this.left.options[i];
+               newLeft[o.value]=1;
+               if (typeof(this.originalLeftValues[o.value])=="undefined") {
+                       addedLeft[o.value]=1;
+                       removedRight[o.value]=1;
+                       }
+               }
+       for (var i=0;i<this.right.options.length;i++) {
+               var o=this.right.options[i];
+               newRight[o.value]=1;
+               if (typeof(this.originalRightValues[o.value])=="undefined") {
+                       addedRight[o.value]=1;
+                       removedLeft[o.value]=1;
+                       }
+               }
+       if (this.removedLeftField!=null) { this.removedLeftField.value = OT_join(removedLeft,this.delimiter); }
+       if (this.removedRightField!=null) { this.removedRightField.value = OT_join(removedRight,this.delimiter); }
+       if (this.addedLeftField!=null) { this.addedLeftField.value = OT_join(addedLeft,this.delimiter); }
+       if (this.addedRightField!=null) { this.addedRightField.value = OT_join(addedRight,this.delimiter); }
+       if (this.newLeftField!=null) { this.newLeftField.value = OT_join(newLeft,this.delimiter); }
+       if (this.newRightField!=null) { this.newRightField.value = OT_join(newRight,this.delimiter); }
+       }
+function OT_join(o,delimiter) {
+       var val; var str="";
+       for(val in o){
+               if (str.length>0) { str=str+delimiter; }
+               str=str+val;
+               }
+       return str;
+       }
+function OT_setDelimiter(val) { this.delimiter=val; }
+function OT_setAutoSort(val) { this.autoSort=val; }
+function OT_init(theform) {
+       this.form = theform;
+       if(!theform[this.left]){alert("OptionTransfer init(): Left select list does not exist in form!");return false;}
+       if(!theform[this.right]){alert("OptionTransfer init(): Right select list does not exist in form!");return false;}
+       this.left=theform[this.left];
+       this.right=theform[this.right];
+       for(var i=0;i<this.left.options.length;i++) {
+               this.originalLeftValues[this.left.options[i].value]=1;
+               }
+       for(var i=0;i<this.right.options.length;i++) {
+               this.originalRightValues[this.right.options[i].value]=1;
+               }
+       if(this.removedLeftField!=null) { this.removedLeftField=theform[this.removedLeftField]; }
+       if(this.removedRightField!=null) { this.removedRightField=theform[this.removedRightField]; }
+       if(this.addedLeftField!=null) { this.addedLeftField=theform[this.addedLeftField]; }
+       if(this.addedRightField!=null) { this.addedRightField=theform[this.addedRightField]; }
+       if(this.newLeftField!=null) { this.newLeftField=theform[this.newLeftField]; }
+       if(this.newRightField!=null) { this.newRightField=theform[this.newRightField]; }
+       this.update();
+       }
+// -------------------------------------------------------------------
+// OptionTransfer()
+//  This is the object interface.
+// -------------------------------------------------------------------
+function OptionTransfer(l,r) {
+       this.form = null;
+       this.left=l;
+       this.right=r;
+       this.autoSort=true;
+       this.delimiter=",";
+       this.originalLeftValues = new Object();
+       this.originalRightValues = new Object();
+       this.removedLeftField = null;
+       this.removedRightField = null;
+       this.addedLeftField = null;
+       this.addedRightField = null;
+       this.newLeftField = null;
+       this.newRightField = null;
+       this.transferLeft=OT_transferLeft;
+       this.transferRight=OT_transferRight;
+       this.transferAllLeft=OT_transferAllLeft;
+       this.transferAllRight=OT_transferAllRight;
+       this.saveRemovedLeftOptions=OT_saveRemovedLeftOptions;
+       this.saveRemovedRightOptions=OT_saveRemovedRightOptions;
+       this.saveAddedLeftOptions=OT_saveAddedLeftOptions;
+       this.saveAddedRightOptions=OT_saveAddedRightOptions;
+       this.saveNewLeftOptions=OT_saveNewLeftOptions;
+       this.saveNewRightOptions=OT_saveNewRightOptions;
+       this.setDelimiter=OT_setDelimiter;
+       this.setAutoSort=OT_setAutoSort;
+       this.init=OT_init;
+       this.update=OT_update;
+       }
diff --git a/Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib/PopupWindow.js b/Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib/PopupWindow.js
new file mode 100644 (file)
index 0000000..e45b171
--- /dev/null
@@ -0,0 +1,336 @@
+// ===================================================================
+// Author: Matt Kruse <matt@mattkruse.com>
+// WWW: http://www.mattkruse.com/
+//
+// NOTICE: You may use this code for any purpose, commercial or
+// private, without any further permission from the author. You may
+// remove this notice from your final code if you wish, however it is
+// appreciated by the author if at least my web site address is kept.
+//
+// You may *NOT* re-distribute this code in any way except through its
+// use. That means, you can include it in your product, or your web
+// site, or any other form where the code is actually being used. You
+// may not put the plain javascript up on your site for download or
+// include it in your javascript libraries for download. 
+// If you wish to share this code with others, please just point them
+// to the URL instead.
+// Please DO NOT link directly to my .js files from your site. Copy
+// the files to your server and use them there. Thank you.
+// ===================================================================
+
+/* 
+PopupWindow.js
+Author: Matt Kruse
+Last modified: 02/16/04
+
+DESCRIPTION: This object allows you to easily and quickly popup a window
+in a certain place. The window can either be a DIV or a separate browser
+window.
+
+COMPATIBILITY: Works with Netscape 4.x, 6.x, IE 5.x on Windows. Some small
+positioning errors - usually with Window positioning - occur on the 
+Macintosh platform. Due to bugs in Netscape 4.x, populating the popup 
+window with <STYLE> tags may cause errors.
+
+USAGE:
+// Create an object for a WINDOW popup
+var win = new PopupWindow(); 
+
+// Create an object for a DIV window using the DIV named 'mydiv'
+var win = new PopupWindow('mydiv'); 
+
+// Set the window to automatically hide itself when the user clicks 
+// anywhere else on the page except the popup
+win.autoHide(); 
+
+// Show the window relative to the anchor name passed in
+win.showPopup(anchorname);
+
+// Hide the popup
+win.hidePopup();
+
+// Set the size of the popup window (only applies to WINDOW popups
+win.setSize(width,height);
+
+// Populate the contents of the popup window that will be shown. If you 
+// change the contents while it is displayed, you will need to refresh()
+win.populate(string);
+
+// set the URL of the window, rather than populating its contents
+// manually
+win.setUrl("http://www.site.com/");
+
+// Refresh the contents of the popup
+win.refresh();
+
+// Specify how many pixels to the right of the anchor the popup will appear
+win.offsetX = 50;
+
+// Specify how many pixels below the anchor the popup will appear
+win.offsetY = 100;
+
+NOTES:
+1) Requires the functions in AnchorPosition.js
+
+2) Your anchor tag MUST contain both NAME and ID attributes which are the 
+   same. For example:
+   <A NAME="test" ID="test"> </A>
+
+3) There must be at least a space between <A> </A> for IE5.5 to see the 
+   anchor tag correctly. Do not do <A></A> with no space.
+
+4) When a PopupWindow object is created, a handler for 'onmouseup' is
+   attached to any event handler you may have already defined. Do NOT define
+   an event handler for 'onmouseup' after you define a PopupWindow object or
+   the autoHide() will not work correctly.
+*/ 
+
+// Set the position of the popup window based on the anchor
+function PopupWindow_getXYPosition(anchorname) {
+       var coordinates;
+       if (this.type == "WINDOW") {
+               coordinates = getAnchorWindowPosition(anchorname);
+               }
+       else {
+               coordinates = getAnchorPosition(anchorname);
+               }
+       this.x = coordinates.x;
+       this.y = coordinates.y;
+       }
+// Set width/height of DIV/popup window
+function PopupWindow_setSize(width,height) {
+       this.width = width;
+       this.height = height;
+       }
+// Fill the window with contents
+function PopupWindow_populate(contents) {
+       this.contents = contents;
+       this.populated = false;
+       }
+// Set the URL to go to
+function PopupWindow_setUrl(url) {
+       this.url = url;
+       }
+// Set the window popup properties
+function PopupWindow_setWindowProperties(props) {
+       this.windowProperties = props;
+       }
+// Refresh the displayed contents of the popup
+function PopupWindow_refresh() {
+       if (this.divName != null) {
+               // refresh the DIV object
+               if (this.use_gebi) {
+                       document.getElementById(this.divName).innerHTML = this.contents;
+                       }
+               else if (this.use_css) { 
+                       document.all[this.divName].innerHTML = this.contents;
+                       }
+               else if (this.use_layers) { 
+                       var d = document.layers[this.divName]; 
+                       d.document.open();
+                       d.document.writeln(this.contents);
+                       d.document.close();
+                       }
+               }
+       else {
+               if (this.popupWindow != null && !this.popupWindow.closed) {
+                       if (this.url!="") {
+                               this.popupWindow.location.href=this.url;
+                               }
+                       else {
+                               this.popupWindow.document.open();
+                               this.popupWindow.document.writeln(this.contents);
+                               this.popupWindow.document.close();
+                       }
+                       this.popupWindow.focus();
+                       }
+               }
+       }
+// Position and show the popup, relative to an anchor object
+function PopupWindow_showPopup(anchorname) {
+       this.getXYPosition(anchorname);
+       this.x += this.offsetX;
+       this.y += this.offsetY;
+       if (!this.populated && (this.contents != "")) {
+               this.populated = true;
+               this.refresh();
+               }
+       if (this.divName != null) {
+               // Show the DIV object
+               if (this.use_gebi) {
+                       document.getElementById(this.divName).style.left = this.x + "px";
+                       document.getElementById(this.divName).style.top = this.y + "px";
+                       document.getElementById(this.divName).style.visibility = "visible";
+                       }
+               else if (this.use_css) {
+                       document.all[this.divName].style.left = this.x;
+                       document.all[this.divName].style.top = this.y;
+                       document.all[this.divName].style.visibility = "visible";
+                       }
+               else if (this.use_layers) {
+                       document.layers[this.divName].left = this.x;
+                       document.layers[this.divName].top = this.y;
+                       document.layers[this.divName].visibility = "visible";
+                       }
+               }
+       else {
+               if (this.popupWindow == null || this.popupWindow.closed) {
+                       // If the popup window will go off-screen, move it so it doesn't
+                       if (this.x<0) { this.x=0; }
+                       if (this.y<0) { this.y=0; }
+                       if (screen && screen.availHeight) {
+                               if ((this.y + this.height) > screen.availHeight) {
+                                       this.y = screen.availHeight - this.height;
+                                       }
+                               }
+                       if (screen && screen.availWidth) {
+                               if ((this.x + this.width) > screen.availWidth) {
+                                       this.x = screen.availWidth - this.width;
+                                       }
+                               }
+                       var avoidAboutBlank = window.opera || ( document.layers && !navigator.mimeTypes['*'] ) || navigator.vendor == 'KDE' || ( document.childNodes && !document.all && !navigator.taintEnabled );
+                       this.popupWindow = window.open(avoidAboutBlank?"":"about:blank","window_"+anchorname,this.windowProperties+",width="+this.width+",height="+this.height+",screenX="+this.x+",left="+this.x+",screenY="+this.y+",top="+this.y+"");
+                       }
+               this.refresh();
+               }
+       }
+// Hide the popup
+function PopupWindow_hidePopup() {
+       if (this.divName != null) {
+               if (this.use_gebi) {
+                       document.getElementById(this.divName).style.visibility = "hidden";
+                       }
+               else if (this.use_css) {
+                       document.all[this.divName].style.visibility = "hidden";
+                       }
+               else if (this.use_layers) {
+                       document.layers[this.divName].visibility = "hidden";
+                       }
+               }
+       else {
+               if (this.popupWindow && !this.popupWindow.closed) {
+                       this.popupWindow.close();
+                       this.popupWindow = null;
+                       }
+               }
+       }
+// Pass an event and return whether or not it was the popup DIV that was clicked
+function PopupWindow_isClicked(e) {
+       if (this.divName != null) {
+               if (this.use_layers) {
+                       var clickX = e.pageX;
+                       var clickY = e.pageY;
+                       var t = document.layers[this.divName];
+                       if ((clickX > t.left) && (clickX < t.left+t.clip.width) && (clickY > t.top) && (clickY < t.top+t.clip.height)) {
+                               return true;
+                               }
+                       else { return false; }
+                       }
+               else if (document.all) { // Need to hard-code this to trap IE for error-handling
+                       var t = window.event.srcElement;
+                       while (t.parentElement != null) {
+                               if (t.id==this.divName) {
+                                       return true;
+                                       }
+                               t = t.parentElement;
+                               }
+                       return false;
+                       }
+               else if (this.use_gebi && e) {
+                       var t = e.originalTarget;
+                       while (t.parentNode != null) {
+                               if (t.id==this.divName) {
+                                       return true;
+                                       }
+                               t = t.parentNode;
+                               }
+                       return false;
+                       }
+               return false;
+               }
+       return false;
+       }
+
+// Check an onMouseDown event to see if we should hide
+function PopupWindow_hideIfNotClicked(e) {
+       if (this.autoHideEnabled && !this.isClicked(e)) {
+               this.hidePopup();
+               }
+       }
+// Call this to make the DIV disable automatically when mouse is clicked outside it
+function PopupWindow_autoHide() {
+       this.autoHideEnabled = true;
+       }
+// This global function checks all PopupWindow objects onmouseup to see if they should be hidden
+function PopupWindow_hidePopupWindows(e) {
+       for (var i=0; i<popupWindowObjects.length; i++) {
+               if (popupWindowObjects[i] != null) {
+                       var p = popupWindowObjects[i];
+                       p.hideIfNotClicked(e);
+                       }
+               }
+       }
+// Run this immediately to attach the event listener
+function PopupWindow_attachListener() {
+       if (document.layers) {
+               document.captureEvents(Event.MOUSEUP);
+               }
+       window.popupWindowOldEventListener = document.onmouseup;
+       if (window.popupWindowOldEventListener != null) {
+               document.onmouseup = new Function("window.popupWindowOldEventListener(); PopupWindow_hidePopupWindows();");
+               }
+       else {
+               document.onmouseup = PopupWindow_hidePopupWindows;
+               }
+       }
+// CONSTRUCTOR for the PopupWindow object
+// Pass it a DIV name to use a DHTML popup, otherwise will default to window popup
+function PopupWindow() {
+       if (!window.popupWindowIndex) { window.popupWindowIndex = 0; }
+       if (!window.popupWindowObjects) { window.popupWindowObjects = new Array(); }
+       if (!window.listenerAttached) {
+               window.listenerAttached = true;
+               PopupWindow_attachListener();
+               }
+       this.index = popupWindowIndex++;
+       popupWindowObjects[this.index] = this;
+       this.divName = null;
+       this.popupWindow = null;
+       this.width=0;
+       this.height=0;
+       this.populated = false;
+       this.visible = false;
+       this.autoHideEnabled = false;
+       
+       this.contents = "";
+       this.url="";
+       this.windowProperties="toolbar=no,location=no,status=no,menubar=no,scrollbars=auto,resizable,alwaysRaised,dependent,titlebar=no";
+       if (arguments.length>0) {
+               this.type="DIV";
+               this.divName = arguments[0];
+               }
+       else {
+               this.type="WINDOW";
+               }
+       this.use_gebi = false;
+       this.use_css = false;
+       this.use_layers = false;
+       if (document.getElementById) { this.use_gebi = true; }
+       else if (document.all) { this.use_css = true; }
+       else if (document.layers) { this.use_layers = true; }
+       else { this.type = "WINDOW"; }
+       this.offsetX = 0;
+       this.offsetY = 0;
+       // Method mappings
+       this.getXYPosition = PopupWindow_getXYPosition;
+       this.populate = PopupWindow_populate;
+       this.setUrl = PopupWindow_setUrl;
+       this.setWindowProperties = PopupWindow_setWindowProperties;
+       this.refresh = PopupWindow_refresh;
+       this.showPopup = PopupWindow_showPopup;
+       this.hidePopup = PopupWindow_hidePopup;
+       this.setSize = PopupWindow_setSize;
+       this.isClicked = PopupWindow_isClicked;
+       this.autoHide = PopupWindow_autoHide;
+       this.hideIfNotClicked = PopupWindow_hideIfNotClicked;
+       }
diff --git a/Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib/README.txt b/Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib/README.txt
new file mode 100644 (file)
index 0000000..e4513eb
--- /dev/null
@@ -0,0 +1,3 @@
+This directory contains the original unpacked JS files that are combined and packed in "mattkruse-lib.js" for reference.
+
+If you add more scripts from this site, please add them here too.
diff --git a/Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib/date.js b/Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib/date.js
new file mode 100644 (file)
index 0000000..9a92340
--- /dev/null
@@ -0,0 +1,335 @@
+// ===================================================================
+// Author: Matt Kruse <matt@mattkruse.com>
+// WWW: http://www.mattkruse.com/
+//
+// NOTICE: You may use this code for any purpose, commercial or
+// private, without any further permission from the author. You may
+// remove this notice from your final code if you wish, however it is
+// appreciated by the author if at least my web site address is kept.
+//
+// You may *NOT* re-distribute this code in any way except through its
+// use. That means, you can include it in your product, or your web
+// site, or any other form where the code is actually being used. You
+// may not put the plain javascript up on your site for download or
+// include it in your javascript libraries for download. 
+// If you wish to share this code with others, please just point them
+// to the URL instead.
+// Please DO NOT link directly to my .js files from your site. Copy
+// the files to your server and use them there. Thank you.
+// ===================================================================
+
+// HISTORY
+// ------------------------------------------------------------------
+// May 17, 2003: Fixed bug in parseDate() for dates <1970
+// March 11, 2003: Added parseDate() function
+// March 11, 2003: Added "NNN" formatting option. Doesn't match up
+//                 perfectly with SimpleDateFormat formats, but 
+//                 backwards-compatability was required.
+
+// ------------------------------------------------------------------
+// These functions use the same 'format' strings as the 
+// java.text.SimpleDateFormat class, with minor exceptions.
+// The format string consists of the following abbreviations:
+// 
+// Field        | Full Form          | Short Form
+// -------------+--------------------+-----------------------
+// Year         | yyyy (4 digits)    | yy (2 digits), y (2 or 4 digits)
+// Month        | MMM (name or abbr.)| MM (2 digits), M (1 or 2 digits)
+//              | NNN (abbr.)        |
+// Day of Month | dd (2 digits)      | d (1 or 2 digits)
+// Day of Week  | EE (name)          | E (abbr)
+// Hour (1-12)  | hh (2 digits)      | h (1 or 2 digits)
+// Hour (0-23)  | HH (2 digits)      | H (1 or 2 digits)
+// Hour (0-11)  | KK (2 digits)      | K (1 or 2 digits)
+// Hour (1-24)  | kk (2 digits)      | k (1 or 2 digits)
+// Minute       | mm (2 digits)      | m (1 or 2 digits)
+// Second       | ss (2 digits)      | s (1 or 2 digits)
+// AM/PM        | a                  |
+//
+// NOTE THE DIFFERENCE BETWEEN MM and mm! Month=MM, not mm!
+// Examples:
+//  "MMM d, y" matches: January 01, 2000
+//                      Dec 1, 1900
+//                      Nov 20, 00
+//  "M/d/yy"   matches: 01/20/00
+//                      9/2/00
+//  "MMM dd, yyyy hh:mm:ssa" matches: "January 01, 2000 12:30:45AM"
+// ------------------------------------------------------------------
+
+var MONTH_NAMES=new Array('January','February','March','April','May','June','July','August','September','October','November','December','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
+var DAY_NAMES=new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sun','Mon','Tue','Wed','Thu','Fri','Sat');
+function LZ(x) {return(x<0||x>9?"":"0")+x}
+
+// ------------------------------------------------------------------
+// isDate ( date_string, format_string )
+// Returns true if date string matches format of format string and
+// is a valid date. Else returns false.
+// It is recommended that you trim whitespace around the value before
+// passing it to this function, as whitespace is NOT ignored!
+// ------------------------------------------------------------------
+function isDate(val,format) {
+       var date=getDateFromFormat(val,format);
+       if (date==0) { return false; }
+       return true;
+       }
+
+// -------------------------------------------------------------------
+// compareDates(date1,date1format,date2,date2format)
+//   Compare two date strings to see which is greater.
+//   Returns:
+//   1 if date1 is greater than date2
+//   0 if date2 is greater than date1 of if they are the same
+//  -1 if either of the dates is in an invalid format
+// -------------------------------------------------------------------
+function compareDates(date1,dateformat1,date2,dateformat2) {
+       var d1=getDateFromFormat(date1,dateformat1);
+       var d2=getDateFromFormat(date2,dateformat2);
+       if (d1==0 || d2==0) {
+               return -1;
+               }
+       else if (d1 > d2) {
+               return 1;
+               }
+       return 0;
+       }
+
+// ------------------------------------------------------------------
+// formatDate (date_object, format)
+// Returns a date in the output format specified.
+// The format string uses the same abbreviations as in getDateFromFormat()
+// ------------------------------------------------------------------
+function formatDate(date,format) {
+       format=format+"";
+       var result="";
+       var i_format=0;
+       var c="";
+       var token="";
+       var y=date.getYear()+"";
+       var M=date.getMonth()+1;
+       var d=date.getDate();
+       var E=date.getDay();
+       var H=date.getHours();
+       var m=date.getMinutes();
+       var s=date.getSeconds();
+       var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,H,KK,K,kk,k;
+       // Convert real date parts into formatted versions
+       var value=new Object();
+       if (y.length < 4) {y=""+(y-0+1900);}
+       value["y"]=""+y;
+       value["yyyy"]=y;
+       value["yy"]=y.substring(2,4);
+       value["M"]=M;
+       value["MM"]=LZ(M);
+       value["MMM"]=MONTH_NAMES[M-1];
+       value["NNN"]=MONTH_NAMES[M+11];
+       value["d"]=d;
+       value["dd"]=LZ(d);
+       value["E"]=DAY_NAMES[E+7];
+       value["EE"]=DAY_NAMES[E];
+       value["H"]=H;
+       value["HH"]=LZ(H);
+       if (H==0){value["h"]=12;}
+       else if (H>12){value["h"]=H-12;}
+       else {value["h"]=H;}
+       value["hh"]=LZ(value["h"]);
+       if (H>11){value["K"]=H-12;} else {value["K"]=H;}
+       value["k"]=H+1;
+       value["KK"]=LZ(value["K"]);
+       value["kk"]=LZ(value["k"]);
+       if (H > 11) { value["a"]="PM"; }
+       else { value["a"]="AM"; }
+       value["m"]=m;
+       value["mm"]=LZ(m);
+       value["s"]=s;
+       value["ss"]=LZ(s);
+       while (i_format < format.length) {
+               c=format.charAt(i_format);
+               token="";
+               while ((format.charAt(i_format)==c) && (i_format < format.length)) {
+                       token += format.charAt(i_format++);
+                       }
+               if (value[token] != null) { result=result + value[token]; }
+               else { result=result + token; }
+               }
+       return result;
+       }
+       
+// ------------------------------------------------------------------
+// Utility functions for parsing in getDateFromFormat()
+// ------------------------------------------------------------------
+function _isInteger(val) {
+       var digits="1234567890";
+       for (var i=0; i < val.length; i++) {
+               if (digits.indexOf(val.charAt(i))==-1) { return false; }
+               }
+       return true;
+       }
+function _getInt(str,i,minlength,maxlength) {
+       for (var x=maxlength; x>=minlength; x--) {
+               var token=str.substring(i,i+x);
+               if (token.length < minlength) { return null; }
+               if (_isInteger(token)) { return token; }
+               }
+       return null;
+       }
+       
+// ------------------------------------------------------------------
+// getDateFromFormat( date_string , format_string )
+//
+// This function takes a date string and a format string. It matches
+// If the date string matches the format string, it returns the 
+// getTime() of the date. If it does not match, it returns 0.
+// ------------------------------------------------------------------
+function getDateFromFormat(val,format) {
+       val=val+"";
+       format=format+"";
+       var i_val=0;
+       var i_format=0;
+       var c="";
+       var token="";
+       var token2="";
+       var x,y;
+       var now=new Date();
+       var year=now.getYear();
+       var month=now.getMonth()+1;
+       var date=1;
+       var hh=now.getHours();
+       var mm=now.getMinutes();
+       var ss=now.getSeconds();
+       var ampm="";
+       
+       while (i_format < format.length) {
+               // Get next token from format string
+               c=format.charAt(i_format);
+               token="";
+               while ((format.charAt(i_format)==c) && (i_format < format.length)) {
+                       token += format.charAt(i_format++);
+                       }
+               // Extract contents of value based on format token
+               if (token=="yyyy" || token=="yy" || token=="y") {
+                       if (token=="yyyy") { x=4;y=4; }
+                       if (token=="yy")   { x=2;y=2; }
+                       if (token=="y")    { x=2;y=4; }
+                       year=_getInt(val,i_val,x,y);
+                       if (year==null) { return 0; }
+                       i_val += year.length;
+                       if (year.length==2) {
+                               if (year > 70) { year=1900+(year-0); }
+                               else { year=2000+(year-0); }
+                               }
+                       }
+               else if (token=="MMM"||token=="NNN"){
+                       month=0;
+                       for (var i=0; i<MONTH_NAMES.length; i++) {
+                               var month_name=MONTH_NAMES[i];
+                               if (val.substring(i_val,i_val+month_name.length).toLowerCase()==month_name.toLowerCase()) {
+                                       if (token=="MMM"||(token=="NNN"&&i>11)) {
+                                               month=i+1;
+                                               if (month>12) { month -= 12; }
+                                               i_val += month_name.length;
+                                               break;
+                                               }
+                                       }
+                               }
+                       if ((month < 1)||(month>12)){return 0;}
+                       }
+               else if (token=="EE"||token=="E"){
+                       for (var i=0; i<DAY_NAMES.length; i++) {
+                               var day_name=DAY_NAMES[i];
+                               if (val.substring(i_val,i_val+day_name.length).toLowerCase()==day_name.toLowerCase()) {
+                                       i_val += day_name.length;
+                                       break;
+                                       }
+                               }
+                       }
+               else if (token=="MM"||token=="M") {
+                       month=_getInt(val,i_val,token.length,2);
+                       if(month==null||(month<1)||(month>12)){return 0;}
+                       i_val+=month.length;}
+               else if (token=="dd"||token=="d") {
+                       date=_getInt(val,i_val,token.length,2);
+                       if(date==null||(date<1)||(date>31)){return 0;}
+                       i_val+=date.length;}
+               else if (token=="hh"||token=="h") {
+                       hh=_getInt(val,i_val,token.length,2);
+                       if(hh==null||(hh<1)||(hh>12)){return 0;}
+                       i_val+=hh.length;}
+               else if (token=="HH"||token=="H") {
+                       hh=_getInt(val,i_val,token.length,2);
+                       if(hh==null||(hh<0)||(hh>23)){return 0;}
+                       i_val+=hh.length;}
+               else if (token=="KK"||token=="K") {
+                       hh=_getInt(val,i_val,token.length,2);
+                       if(hh==null||(hh<0)||(hh>11)){return 0;}
+                       i_val+=hh.length;}
+               else if (token=="kk"||token=="k") {
+                       hh=_getInt(val,i_val,token.length,2);
+                       if(hh==null||(hh<1)||(hh>24)){return 0;}
+                       i_val+=hh.length;hh--;}
+               else if (token=="mm"||token=="m") {
+                       mm=_getInt(val,i_val,token.length,2);
+                       if(mm==null||(mm<0)||(mm>59)){return 0;}
+                       i_val+=mm.length;}
+               else if (token=="ss"||token=="s") {
+                       ss=_getInt(val,i_val,token.length,2);
+                       if(ss==null||(ss<0)||(ss>59)){return 0;}
+                       i_val+=ss.length;}
+               else if (token=="a") {
+                       if (val.substring(i_val,i_val+2).toLowerCase()=="am") {ampm="AM";}
+                       else if (val.substring(i_val,i_val+2).toLowerCase()=="pm") {ampm="PM";}
+                       else {return 0;}
+                       i_val+=2;}
+               else {
+                       if (val.substring(i_val,i_val+token.length)!=token) {return 0;}
+                       else {i_val+=token.length;}
+                       }
+               }
+       // If there are any trailing characters left in the value, it doesn't match
+       if (i_val != val.length) { return 0; }
+       // Is date valid for month?
+       if (month==2) {
+               // Check for leap year
+               if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year
+                       if (date > 29){ return 0; }
+                       }
+               else { if (date > 28) { return 0; } }
+               }
+       if ((month==4)||(month==6)||(month==9)||(month==11)) {
+               if (date > 30) { return 0; }
+               }
+       // Correct hours value
+       if (hh<12 && ampm=="PM") { hh=hh-0+12; }
+       else if (hh>11 && ampm=="AM") { hh-=12; }
+       var newdate=new Date(year,month-1,date,hh,mm,ss);
+       return newdate.getTime();
+       }
+
+// ------------------------------------------------------------------
+// parseDate( date_string [, prefer_euro_format] )
+//
+// This function takes a date string and tries to match it to a
+// number of possible date formats to get the value. It will try to
+// match against the following international formats, in this order:
+// y-M-d   MMM d, y   MMM d,y   y-MMM-d   d-MMM-y  MMM d
+// M/d/y   M-d-y      M.d.y     MMM-d     M/d      M-d
+// d/M/y   d-M-y      d.M.y     d-MMM     d/M      d-M
+// A second argument may be passed to instruct the method to search
+// for formats like d/M/y (european format) before M/d/y (American).
+// Returns a Date object or null if no patterns match.
+// ------------------------------------------------------------------
+function parseDate(val) {
+       var preferEuro=(arguments.length==2)?arguments[1]:false;
+       generalFormats=new Array('y-M-d','MMM d, y','MMM d,y','y-MMM-d','d-MMM-y','MMM d');
+       monthFirst=new Array('M/d/y','M-d-y','M.d.y','MMM-d','M/d','M-d');
+       dateFirst =new Array('d/M/y','d-M-y','d.M.y','d-MMM','d/M','d-M');
+       var checkList=new Array('generalFormats',preferEuro?'dateFirst':'monthFirst',preferEuro?'monthFirst':'dateFirst');
+       var d=null;
+       for (var i=0; i<checkList.length; i++) {
+               var l=window[checkList[i]];
+               for (var j=0; j<l.length; j++) {
+                       d=getDateFromFormat(val,l[j]);
+                       if (d!=0) { return new Date(d); }
+                       }
+               }
+       return null;
+       }
diff --git a/Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib/selectbox.js b/Open-ILS/src/extras/authcon/auth/resources/mattkruse-lib/selectbox.js
new file mode 100644 (file)
index 0000000..a6db92d
--- /dev/null
@@ -0,0 +1,315 @@
+// ===================================================================
+// Author: Matt Kruse <matt@mattkruse.com>
+// WWW: http://www.mattkruse.com/
+//
+// NOTICE: You may use this code for any purpose, commercial or
+// private, without any further permission from the author. You may
+// remove this notice from your final code if you wish, however it is
+// appreciated by the author if at least my web site address is kept.
+//
+// You may *NOT* re-distribute this code in any way except through its
+// use. That means, you can include it in your product, or your web
+// site, or any other form where the code is actually being used. You
+// may not put the plain javascript up on your site for download or
+// include it in your javascript libraries for download. 
+// If you wish to share this code with others, please just point them
+// to the URL instead.
+// Please DO NOT link directly to my .js files from your site. Copy
+// the files to your server and use them there. Thank you.
+// ===================================================================
+
+// HISTORY
+// ------------------------------------------------------------------
+// June 12, 2003: Modified up and down functions to support more than
+//                selected option
+/*
+DESCRIPTION: These are general functions to deal with and manipulate
+select boxes. Also see the OptionTransfer library to more easily 
+handle transferring options between two lists
+
+COMPATIBILITY: These are fairly basic functions - they should work on
+all browsers that support Javascript.
+*/
+
+// -------------------------------------------------------------------
+// selectUnselectMatchingOptions(select_object,regex,select/unselect,true/false)
+//  This is a general function used by the select functions below, to
+//  avoid code duplication
+// -------------------------------------------------------------------
+function selectUnselectMatchingOptions(obj,regex,which,only) {
+       if (window.RegExp) {
+               if (which == "select") {
+                       var selected1=true;
+                       var selected2=false;
+                       }
+               else if (which == "unselect") {
+                       var selected1=false;
+                       var selected2=true;
+                       }
+               else {
+                       return;
+                       }
+               var re = new RegExp(regex);
+               for (var i=0; i<obj.options.length; i++) {
+                       if (re.test(obj.options[i].text)) {
+                               obj.options[i].selected = selected1;
+                               }
+                       else {
+                               if (only == true) {
+                                       obj.options[i].selected = selected2;
+                                       }
+                               }
+                       }
+               }
+       }
+               
+// -------------------------------------------------------------------
+// selectMatchingOptions(select_object,regex)
+//  This function selects all options that match the regular expression
+//  passed in. Currently-selected options will not be changed.
+// -------------------------------------------------------------------
+function selectMatchingOptions(obj,regex) {
+       selectUnselectMatchingOptions(obj,regex,"select",false);
+       }
+// -------------------------------------------------------------------
+// selectOnlyMatchingOptions(select_object,regex)
+//  This function selects all options that match the regular expression
+//  passed in. Selected options that don't match will be un-selected.
+// -------------------------------------------------------------------
+function selectOnlyMatchingOptions(obj,regex) {
+       selectUnselectMatchingOptions(obj,regex,"select",true);
+       }
+// -------------------------------------------------------------------
+// unSelectMatchingOptions(select_object,regex)
+//  This function Unselects all options that match the regular expression
+//  passed in. 
+// -------------------------------------------------------------------
+function unSelectMatchingOptions(obj,regex) {
+       selectUnselectMatchingOptions(obj,regex,"unselect",false);
+       }
+       
+// -------------------------------------------------------------------
+// sortSelect(select_object)
+//   Pass this function a SELECT object and the options will be sorted
+//   by their text (display) values
+// -------------------------------------------------------------------
+function sortSelect(obj) {
+       var o = new Array();
+       if (obj.options==null) { return; }
+       for (var i=0; i<obj.options.length; i++) {
+               o[o.length] = new Option( obj.options[i].text, obj.options[i].value, obj.options[i].defaultSelected, obj.options[i].selected) ;
+               }
+       if (o.length==0) { return; }
+       o = o.sort( 
+               function(a,b) { 
+                       if ((a.text+"") < (b.text+"")) { return -1; }
+                       if ((a.text+"") > (b.text+"")) { return 1; }
+                       return 0;
+                       } 
+               );
+
+       for (var i=0; i<o.length; i++) {
+               obj.options[i] = new Option(o[i].text, o[i].value, o[i].defaultSelected, o[i].selected);
+               }
+       }
+
+// -------------------------------------------------------------------
+// selectAllOptions(select_object)
+//  This function takes a select box and selects all options (in a 
+//  multiple select object). This is used when passing values between
+//  two select boxes. Select all options in the right box before 
+//  submitting the form so the values will be sent to the server.
+// -------------------------------------------------------------------
+function selectAllOptions(obj) {
+       for (var i=0; i<obj.options.length; i++) {
+               obj.options[i].selected = true;
+               }
+       }
+       
+// -------------------------------------------------------------------
+// moveSelectedOptions(select_object,select_object[,autosort(true/false)[,regex]])
+//  This function moves options between select boxes. Works best with
+//  multi-select boxes to create the common Windows control effect.
+//  Passes all selected values from the first object to the second
+//  object and re-sorts each box.
+//  If a third argument of 'false' is passed, then the lists are not
+//  sorted after the move.
+//  If a fourth string argument is passed, this will function as a
+//  Regular Expression to match against the TEXT or the options. If 
+//  the text of an option matches the pattern, it will NOT be moved.
+//  It will be treated as an unmoveable option.
+//  You can also put this into the <SELECT> object as follows:
+//    onDblClick="moveSelectedOptions(this,this.form.target)
+//  This way, when the user double-clicks on a value in one box, it
+//  will be transferred to the other (in browsers that support the 
+//  onDblClick() event handler).
+// -------------------------------------------------------------------
+function moveSelectedOptions(from,to) {
+       // Unselect matching options, if required
+       if (arguments.length>3) {
+               var regex = arguments[3];
+               if (regex != "") {
+                       unSelectMatchingOptions(from,regex);
+                       }
+               }
+       // Move them over
+       for (var i=0; i<from.options.length; i++) {
+               var o = from.options[i];
+               if (o.selected) {
+                       to.options[to.options.length] = new Option( o.text, o.value, false, false);
+                       }
+               }
+       // Delete them from original
+       for (var i=(from.options.length-1); i>=0; i--) {
+               var o = from.options[i];
+               if (o.selected) {
+                       from.options[i] = null;
+                       }
+               }
+       if ((arguments.length<3) || (arguments[2]==true)) {
+               sortSelect(from);
+               sortSelect(to);
+               }
+       from.selectedIndex = -1;
+       to.selectedIndex = -1;
+       }
+
+// -------------------------------------------------------------------
+// copySelectedOptions(select_object,select_object[,autosort(true/false)])
+//  This function copies options between select boxes instead of 
+//  moving items. Duplicates in the target list are not allowed.
+// -------------------------------------------------------------------
+function copySelectedOptions(from,to) {
+       var options = new Object();
+       for (var i=0; i<to.options.length; i++) {
+               options[to.options[i].value] = to.options[i].text;
+               }
+       for (var i=0; i<from.options.length; i++) {
+               var o = from.options[i];
+               if (o.selected) {
+                       if (options[o.value] == null || options[o.value] == "undefined" || options[o.value]!=o.text) {
+                               to.options[to.options.length] = new Option( o.text, o.value, false, false);
+                               }
+                       }
+               }
+       if ((arguments.length<3) || (arguments[2]==true)) {
+               sortSelect(to);
+               }
+       from.selectedIndex = -1;
+       to.selectedIndex = -1;
+       }
+
+// -------------------------------------------------------------------
+// moveAllOptions(select_object,select_object[,autosort(true/false)[,regex]])
+//  Move all options from one select box to another.
+// -------------------------------------------------------------------
+function moveAllOptions(from,to) {
+       selectAllOptions(from);
+       if (arguments.length==2) {
+               moveSelectedOptions(from,to);
+               }
+       else if (arguments.length==3) {
+               moveSelectedOptions(from,to,arguments[2]);
+               }
+       else if (arguments.length==4) {
+               moveSelectedOptions(from,to,arguments[2],arguments[3]);
+               }
+       }
+
+// -------------------------------------------------------------------
+// copyAllOptions(select_object,select_object[,autosort(true/false)])
+//  Copy all options from one select box to another, instead of
+//  removing items. Duplicates in the target list are not allowed.
+// -------------------------------------------------------------------
+function copyAllOptions(from,to) {
+       selectAllOptions(from);
+       if (arguments.length==2) {
+               copySelectedOptions(from,to);
+               }
+       else if (arguments.length==3) {
+               copySelectedOptions(from,to,arguments[2]);
+               }
+       }
+
+// -------------------------------------------------------------------
+// swapOptions(select_object,option1,option2)
+//  Swap positions of two options in a select list
+// -------------------------------------------------------------------
+function swapOptions(obj,i,j) {
+       var o = obj.options;
+       var i_selected = o[i].selected;
+       var j_selected = o[j].selected;
+       var temp = new Option(o[i].text, o[i].value, o[i].defaultSelected, o[i].selected);
+       var temp2= new Option(o[j].text, o[j].value, o[j].defaultSelected, o[j].selected);
+       o[i] = temp2;
+       o[j] = temp;
+       o[i].selected = j_selected;
+       o[j].selected = i_selected;
+       }
+       
+// -------------------------------------------------------------------
+// moveOptionUp(select_object)
+//  Move selected option in a select list up one
+// -------------------------------------------------------------------
+function moveOptionUp(obj) {
+       for (i=0; i<obj.options.length; i++) {
+               if (obj.options[i].selected) {
+                       if (i != 0 && !obj.options[i-1].selected) {
+                               swapOptions(obj,i,i-1);
+                               obj.options[i-1].selected = true;
+                               }
+                       }
+               }
+       }
+
+// -------------------------------------------------------------------
+// moveOptionDown(select_object)
+//  Move selected option in a select list down one
+// -------------------------------------------------------------------
+function moveOptionDown(obj) {
+       for (i=obj.options.length-1; i>=0; i--) {
+               if (obj.options[i].selected) {
+                       if (i != (obj.options.length-1) && ! obj.options[i+1].selected) {
+                               swapOptions(obj,i,i+1);
+                               obj.options[i+1].selected = true;
+                               }
+                       }
+               }
+       }
+
+// -------------------------------------------------------------------
+// removeSelectedOptions(select_object)
+//  Remove all selected options from a list
+//  (Thanks to Gene Ninestein)
+// -------------------------------------------------------------------
+function removeSelectedOptions(from) { 
+       for (var i=(from.options.length-1); i>=0; i--) { 
+               var o=from.options[i]; 
+               if (o.selected) { 
+                       from.options[i] = null; 
+                       } 
+               } 
+       from.selectedIndex = -1; 
+       } 
+
+// -------------------------------------------------------------------
+// removeAllOptions(select_object)
+//  Remove all options from a list
+// -------------------------------------------------------------------
+function removeAllOptions(from) { 
+       for (var i=(from.options.length-1); i>=0; i--) { 
+               from.options[i] = null; 
+               } 
+       from.selectedIndex = -1; 
+       } 
+
+// -------------------------------------------------------------------
+// addOption(select_object,display_text,value,selected)
+//  Add an option to a list
+// -------------------------------------------------------------------
+function addOption(obj,text,value,selected) {
+       if (obj!=null && obj.options!=null) {
+               obj.options[obj.options.length] = new Option(text, value, false, selected);
+               }
+       }
+
diff --git a/Open-ILS/src/extras/authcon/auth/resources/move_down.gif b/Open-ILS/src/extras/authcon/auth/resources/move_down.gif
new file mode 100644 (file)
index 0000000..82ac5bf
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/move_down.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/move_up.gif b/Open-ILS/src/extras/authcon/auth/resources/move_up.gif
new file mode 100644 (file)
index 0000000..c794d5d
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/move_up.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/resources/new.gif b/Open-ILS/src/extras/authcon/auth/resources/new.gif
new file mode 100644 (file)
index 0000000..df044bb
Binary files /dev/null and b/Open-ILS/src/extras/authcon/auth/resources/new.gif differ
diff --git a/Open-ILS/src/extras/authcon/auth/scripts/ip_check.xsp b/Open-ILS/src/extras/authcon/auth/scripts/ip_check.xsp
new file mode 100644 (file)
index 0000000..d7fe61b
--- /dev/null
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<xsp:page language="java"
+  xmlns:xsp="http://apache.org/xsp"
+  xmlns:action="http://apache.org/cocoon/action/1.0"
+  xmlns:xsp-request="http://apache.org/xsp/request/2.0"
+  xmlns:xsp-session="http://apache.org/xsp/session/2.0"
+  xmlns:util="http://apache.org/xsp/util/2.0"
+  xmlns:wibs="http://wibs.sourceforge.net"
+       create-session="true">
+
+<!-- ip_check.xsp: check an IP address for sitemap entry 
+                @author <a href="http://librarycog.uwindsor.ca">art rhyno</a>
+-->
+
+<xsp:structure>
+       <xsp:include>java.net.InetAddress</xsp:include>
+</xsp:structure>
+
+<authentication>
+<xsp:logic>
+try {
+       String remoteAddress = <xsp-request:get-remote-address/>;
+       String allowedIP = "";
+       allowedIP = <util:get-sitemap-parameter name="ipdomain"/>;
+        System.out.println("IP = " + remoteAddress + " and allowed is " + allowedIP);
+
+       //for demo only, uncomment next line for checking
+       //if( allowedIP.indexOf(remoteAddress) != -1 )
+       if( remoteAddress.startsWith(allowedIP))
+               <action:set-success/>
+       else
+               <action:set-failure/>
+} catch(Exception e) { 
+       e.printStackTrace() ;
+       <action:set-failure/>
+}
+</xsp:logic>
+</authentication>
+</xsp:page>
diff --git a/Open-ILS/src/extras/authcon/auth/sitemap.xmap b/Open-ILS/src/extras/authcon/auth/sitemap.xmap
new file mode 100644 (file)
index 0000000..31ee0af
--- /dev/null
@@ -0,0 +1,250 @@
+<?xml version="1.0"?>
+<!--
+       authentication setup using cocoon and opensrf
+
+        (c) Copyright GNU General Public License (GPL)
+        @author <a href="http://projectconifer.ca">art rhyno</a>
+
+-->
+
+<map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0">
+
+<map:pipelines>
+
+       <map:component-configurations>
+       <global-variables>
+               <!--
+               | we do a double check on the ip address, ezproxy
+               | will not normally pass these on but just in case.
+               | note: leave this until you have tested the
+               | the connection
+               -->
+               <ipdomain>937.207</ipdomain>
+               <conifer-org>OWA</conifer-org>
+               <conifer-host>evergreen.concat.ca</conifer-host>
+               <library-home-page>www.uwindsor.ca</library-home-page>
+               <!-- production -->
+               <opensrf-host>https://evergreen.concat.ca/osrf-gateway-v1</opensrf-host>
+               <!-- test -->
+               <!--
+               <opensrf-host>https://evergreen.concat.ca/osrf-gateway-v1</opensrf-host>
+               -->
+               <!-- field to highlight on auth form --<
+               <first-field>barcode</first-field>
+               <!-- ezproxy parameters -->
+               <ez-host>http://ezproxy.concat.ca</ez-host>
+               <ez-user>ezuser</ez-user>
+               <ez-password>ezpassword</ez-password>
+               <!--
+                       list of IP addresses to block (if necessary)
+               -->
+               <problist>
+               111.111.111.111, 222.222.222.222
+               </problist>
+               <!--
+                       list of user  addresses to block (if necessary)
+               -->
+               <banlist>
+               compromized_account
+               </banlist>
+       </global-variables>
+       </map:component-configurations>
+
+       <map:pipeline>
+               <!--
+               | EZproxy pipeline
+               -->
+               <map:match pattern="check*">
+                       <map:call function="authorization">
+                       <map:parameter name="ezhost" 
+                               value="{global:ez-host}"/>
+                       <map:parameter name="ezuser" 
+                               value="{global:ez-user}"/>
+                       <map:parameter name="ezpassword" 
+                               value="{global:ez-password}"/>
+                       <map:parameter name="ipdomain" 
+                               value="{global:ipdomain}"/>
+                       <map:parameter name="banlist" 
+                               value="{global:banlist}"/>
+                       <map:parameter name="problist" 
+                               value="{global:problist}"/>
+                       <map:parameter name="coniferorg" 
+                               value="{global:conifer-org}"/>
+                       <map:parameter name="thisurl" 
+                               value="{request:queryString}"/>
+                       </map:call>
+               </map:match>
+
+               <!--
+               | OpenSRF pipeline
+               -->
+               <map:match pattern="opensrf">
+                       <map:generate type="jx" src="content/opensrf.xml"/>
+                       <map:transform src="stylesheets/opensrf.xsl">
+                               <map:parameter name="osrfHost"         
+                                       value="{global:opensrf-host}"/>
+                       </map:transform>
+                       <map:transform type="sethTransform"/>
+                       <map:transform src="stylesheets/as_is.xsl"/>
+                       <map:transform src="stylesheets/response2json.xsl"/>
+                       <map:serialize type="json"/>
+               </map:match>
+
+               <!--
+               | Authorization form
+               -->
+               <map:match pattern="*-display-pipeline">
+                               <map:generate src="forms/{1}_template.xml"/>
+                       <map:transform type="forms"/>
+                       <!--
+                       cocoon has i18n support
+                       -->
+                       <!--
+                               <map:transform type="i18n">
+                               <map:parameter name="locale" value="en-US"/>
+                               </map:transform>
+                       -->
+                       <map:call resource="simple-page2html">
+                               <map:parameter name="file" value="forms/{1}_template.xml"/>
+                               </map:call>
+                               <map:transform src="resources/forms-samples-styling.xsl">
+                               <map:parameter name="focusfield" value="{global:first-field}"/>
+                       </map:transform>
+                               <map:serialize/>
+               </map:match>
+
+               <!--
+               | continuations support
+               -->
+               <map:match pattern="*.continue">
+                               <map:call continuation="{1}"/>
+               </map:match>
+
+               <!--
+               | convenience pipeline for sending on urls
+               -->
+               <map:match pattern="pass-on">
+                       <map:redirect-to uri="{request-param:url}"/>
+               </map:match>
+       
+       
+               <!--
+               | authenticate status
+               -->
+               <map:match pattern="authenticate.jx">
+                       <map:generate src="content/kickoff.xml"/>
+                       <map:transform src="stylesheets/reportstatus.xsl">
+                               <map:parameter name="use-request-parameters" 
+                                       value="true"/>
+                               <map:parameter name="ezhost" 
+                                       value="{global:ez-host}"/>
+                               <map:parameter name="ezuser" 
+                                       value="{global:ez-user}"/>
+                               <map:parameter name="ezpassword" 
+                                       value="{global:ez-password}"/>
+                       </map:transform>
+                       <map:serialize type="html"/>
+               </map:match>
+
+               <map:match pattern="showedinfo">
+                       <map:redirect-to uri="../auth/"/>
+               </map:match>
+
+               <!--
+               | basic image support
+               -->
+               <map:match pattern="*.jpg">
+                       <map:read src="images/{1}.jpg"/>
+               </map:match>
+
+               <map:match pattern="*.gif">
+                       <map:read src="images/{1}.gif"/>
+               </map:match>
+
+               <map:match pattern="resources/**">
+                               <map:read src="{0}"/>
+               </map:match>
+    
+               <map:match pattern="**">
+                       <map:redirect-to uri="http://{global:library-home-page}"/>
+               </map:match>
+       </map:pipeline>
+       </map:pipelines>
+
+       <map:components>
+               <map:generators default="file">
+                       <map:generator name="form" 
+                               src="org.apache.cocoon.forms.generation.FormsGenerator"/>
+               </map:generators>
+
+               <!--
+               | seth support comes in here
+               -->
+               <map:transformers default="xslt">    
+                       <map:transformer name="sethTransform" 
+                               src="org.apache.cocoon.transformation.sethTransformer"/>                
+                       <map:transformer name="form" 
+                               src="org.apache.cocoon.forms.transformation.FormsTemplateTransformer"/>
+               </map:transformers>
+       
+               <map:serializers default="html">
+                       <map:serializer logger="sitemap.serializer.json" mime-type="text/javascript" 
+                               name="json" src="org.apache.cocoon.serialization.TextSerializer"
+                       >
+                               <encoding>UTF-8</encoding><!-- JSON responses are expected to be in UTF-8 -->
+                       </map:serializer>
+               </map:serializers>
+
+               <map:actions>
+                       <map:action name="make-form" 
+                               src="org.apache.cocoon.forms.acting.MakeFormAction" logger="forms"/>
+                       <map:action name="init-form" 
+                               src="org.apache.cocoon.forms.samples.InitForm1Action" logger="forms"/>
+                       <map:action name="handle-form-submit" 
+                               src="org.apache.cocoon.forms.acting.HandleFormSubmitAction" logger="forms"/>
+                       <map:action logger="sitemap.action.xsp-action" name="xsp-action"
+                               src="org.apache.cocoon.acting.ServerPagesAction"/>
+               </map:actions>
+       </map:components>
+
+       <!--
+       | standard cocoon plumbing
+       -->
+       <map:views>
+               <map:view name="content" from-label="content">
+                       <map:serialize type="xml"/>
+               </map:view>
+
+               <map:view from-label="content" name="pretty-content">
+                       <map:transform src="stylesheets/xml2html.xslt"/>
+                       <map:serialize type="html"/>
+               </map:view>
+
+               <map:view name="links" from-position="last">
+                       <map:serialize type="links"/>
+               </map:view>
+       </map:views>
+       <map:resources>
+               <map:resource name="simple-page2html">
+                       <map:transform src="stylesheets/simple-page2html.xsl">
+                                       <map:parameter name="contextPath" value="{request:contextPath}"/>
+                                       <map:parameter name="servletPath" value="{request:servletPath}"/>
+                                       <map:parameter name="sitemapURI" value="{request:sitemapURI}"/>
+                                       <map:parameter name="file" value="{file}"/>
+                                       <map:parameter name="remove" value="{../0}"/>
+                       </map:transform> 
+               </map:resource>
+       </map:resources>
+
+       <!--
+       | flowscript support
+       -->
+       <map:flow language="javascript">
+               <map:script src="flow/auth.js"/>
+               <map:script src="flow/md5.js"/>
+               <map:script src="flow/opensrf.js"/>
+               <map:script src="flow/util.js"/>
+       </map:flow>
+
+</map:sitemap>
diff --git a/Open-ILS/src/extras/authcon/auth/stylesheets/as_is.xsl b/Open-ILS/src/extras/authcon/auth/stylesheets/as_is.xsl
new file mode 100644 (file)
index 0000000..3648bab
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!--
+        (c) Copyright GNU General Public License (GPL)
+        @author <a href="http://projectconifer.ca">art rhyno</a>
+
+       ok, this is a silly stylesheet, it simply passes everything
+       through it receives, but is needed for syncing SAX
+       events
+-->
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xhtml="http://www.w3.org/1999/xhtml">
+       <xsl:output method="xml"/>
+       <xsl:namespace-alias stylesheet-prefix="xhtml" result-prefix="xsl"/>
+       <xsl:template match="/">
+               <xsl:copy-of select="./*"/>
+       </xsl:template>
+</xsl:stylesheet>
diff --git a/Open-ILS/src/extras/authcon/auth/stylesheets/opensrf.xsl b/Open-ILS/src/extras/authcon/auth/stylesheets/opensrf.xsl
new file mode 100644 (file)
index 0000000..bfe52f6
--- /dev/null
@@ -0,0 +1,41 @@
+<xsl:stylesheet version="1.0"\r
+       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"\r
+       xmlns:seth="http://seth.sourceforge.net">\r
+\r
+<!-- token.xsl:        \r
+       set up HTTP interaction with evergreen\r
\r
+       (c) Copyright GNU General Public License (GPL)\r
+       @author <a href="http://librarycog.uwindsor.ca">art rhyno</a>\r
+-->\r
+\r
+<xsl:param name="osrfHost"/>\r
+\r
+<xsl:template match="text()"/>\r
+\r
+<xsl:template match="/opensrf">\r
+       <seth:execute-retrieval>\r
+\r
+       <!-- use specific User Agent -->\r
+       <seth:useragent>Mozilla/4.5</seth:useragent>\r
+\r
+       <!-- timeout (in seconds) -->\r
+       <seth:timeout>60</seth:timeout>\r
+\r
+       <!-- where to go -->\r
+       <!--\r
+       <seth:url>https://windsor.concat.ca/osrf-gateway-v1</seth:url>\r
+       -->\r
+       <seth:url><xsl:value-of select="$osrfHost"/></seth:url>\r
+\r
+       <seth:nvp name="method"><xsl:value-of select="method"/></seth:nvp>\r
+       <seth:nvp name="service"><xsl:value-of select="service"/></seth:nvp>\r
+       <xsl:for-each select="parms/parm">\r
+               <seth:nvp name="param" jsspace="true"><xsl:value-of select="."/></seth:nvp>\r
+       </xsl:for-each>\r
+       <seth:method>POST</seth:method>\r
+\r
+       </seth:execute-retrieval>\r
+</xsl:template>\r
+\r
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/Open-ILS/src/extras/authcon/auth/stylesheets/reportstatus.xsl b/Open-ILS/src/extras/authcon/auth/stylesheets/reportstatus.xsl
new file mode 100644 (file)
index 0000000..2112fda
--- /dev/null
@@ -0,0 +1,152 @@
+<?xml version="1.0"?>
+<!--
+        (c) Copyright GNU General Public License (GPL)
+        @author <a href="http://projectconifer.ca">art rhyno</a>
+-->
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:sql="http://apache.org/cocoon/SQL/2.0">
+
+<xsl:param name="ezhost"/>
+<xsl:param name="ezuser"/>
+<xsl:param name="ezpassword"/>
+<xsl:param name="url"/>
+<xsl:param name="flag"/>
+
+
+<xsl:template match="/">
+       <xsl:choose>
+               <!--
+                       we don't do this, and it would be a bad idea
+                       but redir is an example of how to have a web
+                       page do a redirect back to ezproxy instead of
+                       the servlet container, would only consider
+                       this if a network environment demanded the
+                       browser do the redirect
+               -->
+               <xsl:when test="contains($flag,'true')">
+                       <xsl:call-template name="redir"/>
+               </xsl:when>
+               <xsl:otherwise>
+                       <xsl:call-template name="showmsg">
+                               <xsl:with-param name="msg" 
+                                       select="'Sorry, this account has not been found or is no longer active, please try again.'"/>
+                       </xsl:call-template>
+               </xsl:otherwise>
+       </xsl:choose>
+</xsl:template>
+
+<xsl:template name="redir">
+       <meta HTTP-EQUIV="REFRESH"> 
+       <xsl:attribute name="content">
+               <xsl:text>0;url=http://</xsl:text>
+               <xsl:value-of select="$ezhost"/>
+               <xsl:text>/login?user=</xsl:text>
+               <xsl:value-of select="$ezuser"/>
+               <xsl:text>&amp;pass=</xsl:text>
+               <xsl:value-of select="$ezpassword"/>
+               <xsl:text>&amp;url=</xsl:text>
+               <xsl:choose>
+               <xsl:when test="contains($url,'%26')">
+                <xsl:call-template name="replaceCharsInString">
+                        <xsl:with-param name="stringIn"
+                                select="$url"/>
+                        <xsl:with-param name="charsIn" select="'%26'"/>
+                        <xsl:with-param name="charsOut" select="'&amp;'"/>
+                </xsl:call-template>
+               </xsl:when>
+               <xsl:otherwise>
+                       <xsl:value-of select="$url"/>
+               </xsl:otherwise>
+               </xsl:choose>
+       </xsl:attribute>
+       </meta>
+</xsl:template>
+
+<!--
+       this is typically what is used by the auth application
+-->
+<xsl:template name="showmsg">
+       <xsl:param name="msg"/>
+
+       <html>
+                <head>
+                        <title>Authorization Status</title>
+                </head>
+
+                <body bgcolor="#ffffff">
+                <table style="border-collapse: collapse"
+                       cellSpacing="" cellPadding="0" border="0">
+                <tr>
+                       <td valign="top" background="bback.gif">
+                        <img src="status.gif"/>
+                       </td>
+                       <td  width="100%" background="bback.gif" bgColor="#cae2f0"/>
+                       <td  valign="top" background="bback.gif" bgColor="#cae2f0">
+                               <img src="end.gif"/>
+                       </td>
+                </tr>
+                </table>
+               <table style="border-collapse: collapse" align="middle"
+               borderColor="#cae2f0" cellSpacing="0" cellPadding="0" width="100%" border="0">
+               <tr>
+                       <td bgColor="#cae2f0"/>
+                       <td valign="top" align="middle" 
+                               bgColor="#cae2f0">
+                       <form method="get" action="javascript:history.go(-1)" name="showform">
+                       <table>
+                       <tr>
+                       <td/>
+                       <td>
+                       <center>
+                       <strong>
+                       <xsl:value-of select="$msg"/>
+                       </strong>
+                       </center>
+                       </td>
+                       </tr>
+                       <tr>
+                       <td/>
+                       <td>
+                       <center>
+                       <input type="image" height="21" alt="OK" width="21"
+                       src="ok.gif" value="OK" border="0" />
+                       </center>
+                       </td>
+                       </tr>
+                       </table>
+                       <br clear="left"/>
+                       </form>
+                       </td>
+               </tr>
+                </table>
+                </body>
+        </html>
+</xsl:template>
+
+<!--
+       why xml programming is such a bad idea...
+-->
+<xsl:template name="replaceCharsInString">
+       <xsl:param name="stringIn"/>
+       <xsl:param name="charsIn"/>
+       <xsl:param name="charsOut"/>
+
+       <xsl:choose>
+       <xsl:when test="contains($stringIn,$charsIn)">
+               <xsl:value-of select="concat(substring-before
+                       ($stringIn,$charsIn),$charsOut)"/>
+               <xsl:call-template name="replaceCharsInString">
+                       <xsl:with-param name="stringIn" select="substring-after(
+                               $stringIn,$charsIn)"/>
+                       <xsl:with-param name="charsIn" select="$charsIn"/>
+                       <xsl:with-param name="charsOut" select="$charsOut"/>
+               </xsl:call-template>
+       </xsl:when>
+       <xsl:otherwise>
+               <xsl:value-of select="$stringIn"/>
+       </xsl:otherwise>
+       </xsl:choose>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/Open-ILS/src/extras/authcon/auth/stylesheets/response2json.xsl b/Open-ILS/src/extras/authcon/auth/stylesheets/response2json.xsl
new file mode 100644 (file)
index 0000000..0ad6351
--- /dev/null
@@ -0,0 +1,29 @@
+<xsl:stylesheet version="1.0"\r
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">\r
+\r
+<!-- xml2json.xsl:     \r
+       convert XML to JSON\r
+       this xslt needs more work for complex xml, really\r
+       used at this point for coordinating pipeline\r
+       processing and status information rather\r
+       than gobs of XML output\r
\r
+       (c) Copyright GNU General Public License (GPL)\r
+       @author <a href="http://librarycog.uwindsor.ca">art rhyno</a>\r
+-->\r
+\r
+<!--\r
+-->\r
+<xsl:output method="json"/>\r
+\r
+<xsl:template match="text()" />\r
+\r
+<xsl:template match="/">\r
+               <xsl:apply-templates select="*"/>\r
+</xsl:template>\r
+\r
+<xsl:template match="//body">\r
+       <xsl:value-of select="."/>\r
+</xsl:template>\r
+\r
+</xsl:stylesheet>\r
diff --git a/Open-ILS/src/extras/authcon/auth/stylesheets/seth1.xsl b/Open-ILS/src/extras/authcon/auth/stylesheets/seth1.xsl
new file mode 100644 (file)
index 0000000..b2d27d9
--- /dev/null
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+               xmlns:seth="http://seth.sourceforge.net">
+
+<!-- ssrl1.xsl: put together seth paramters based on current HTML display 
+                @author <a href="http://librarycog.uwindsor.ca">art rhyno</a>
+-->
+<xsl:param name="q"/>
+<xsl:param name="start"/>
+<xsl:param name="cluster"/>
+
+<!--
+<xsl:template match="text()"/>
+-->
+
+<xsl:template match="dynamic-query">
+<seth:execute-retrieval>
+        <seth:url>http://scholar.google.com/scholar</seth:url>
+        <seth:method>GET</seth:method>
+        <seth:useragent>Mozilla/4.5</seth:useragent>
+        <seth:timeout>60</seth:timeout>
+        <seth:nvp name="q">
+               <xsl:value-of select="$q"/>
+       </seth:nvp>
+        <seth:nvp name="start">
+               <xsl:value-of select="$start"/>
+       </seth:nvp>
+        <seth:nvp name="cluster">
+               <xsl:value-of select="$cluster"/>
+       </seth:nvp>
+        <seth:nvp name="btnG">Search</seth:nvp>
+        <seth:nvp name="hl">en</seth:nvp>
+        <seth:nvp name="ie">UTF-8</seth:nvp>
+</seth:execute-retrieval>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/Open-ILS/src/extras/authcon/auth/stylesheets/seth2.xsl b/Open-ILS/src/extras/authcon/auth/stylesheets/seth2.xsl
new file mode 100644 (file)
index 0000000..1543b3e
--- /dev/null
@@ -0,0 +1,55 @@
+<?xml version="1.0"?>
+<!DOCTYPE stylesheet [
+        <!ENTITY UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ-">
+        <!ENTITY LOWERCASE "abcdefghijklmnopqrstuvwxyz-">
+       <!ENTITY UPPER_TO_LOWER "'&UPPERCASE;','&LOWERCASE;'">
+]>
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:seth="http://seth.sourceforge.net">
+
+<!-- seth.xsl: another step involving pulling info from an HTML page
+                and setting up the parameters for the next step for
+                seth
+
+                @author <a href="http://librarycog.uwindsor.ca">art rhyno</a>
+-->
+
+<xsl:template match="text()"/>
+
+<xsl:template match="retrieval-results">
+
+       <sethtarget xmlns:seth="http://seth.sourceforge.net">
+       <seth:execute-retrieval>
+        <seth:url>http://racer.scholarsportal.info/zportal/zengine</seth:url>
+        <seth:useragent>Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)</seth:useragent>
+<!--
+-->
+        <seth:timeout>60</seth:timeout>
+       <seth:barcode>
+               <xsl:value-of select="wibs-info/barcode"/>
+       </seth:barcode>
+
+        <!-- GET or POST -->
+        <seth:method>POST</seth:method>
+
+        <seth:cookie name="JSESSIONID" path="/zportal" domain="racer.scholarsportal.info">
+               <xsl:value-of select="cookies/cookie"/>
+       </seth:cookie>
+       <seth:nvp name="login_user">
+               <xsl:value-of select="wibs-info/barcode"/>
+       </seth:nvp>
+       <seth:nvp name="login_password">
+               <xsl:value-of 
+               select="translate(normalize-space(wibs-info/pin),&UPPER_TO_LOWER;)"/>
+       </seth:nvp>
+       <seth:nvp name="login_service_id">7</seth:nvp>
+       <seth:nvp name="VDXaction">Login</seth:nvp>
+       <seth:nvp name="nextAction">ZSearchSimple</seth:nvp>
+        <!-- put extra information in log if true -->
+        <seth:debug>FALSE</seth:debug>
+       </seth:execute-retrieval>
+       </sethtarget>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/Open-ILS/src/extras/authcon/auth/stylesheets/seth3.xsl b/Open-ILS/src/extras/authcon/auth/stylesheets/seth3.xsl
new file mode 100644 (file)
index 0000000..143bd81
--- /dev/null
@@ -0,0 +1,139 @@
+<?xml version="1.0"?>
+<xsl:stylesheet version="1.0"
+               xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+               xmlns:cinclude="http://apache.org/cocoon/include/1.0"
+               xmlns:text="http://chaperon.sourceforge.net/schema/text/1.0"
+               xmlns:seth="http://seth.sourceforge.net"
+               xmlns="http://www.w3.org/1999/xhtml">
+
+<!-- 
+-->
+<xsl:include href="common.xsl"/>
+
+<xsl:variable name="proxy">
+       <xsl:text>proxy/</xsl:text>
+</xsl:variable>
+
+<xsl:variable name="proxy_fixslash">
+       <xsl:text>proxy_fixslash/</xsl:text>
+</xsl:variable>
+
+<xsl:variable name="ezproxy_hosts">
+       <xsl:value-of select="/seth:resultsproxy/text:text"/>
+</xsl:variable>
+
+<xsl:template match="@* | node()">
+       <xsl:copy>
+               <xsl:apply-templates select="@* | node()"/>
+       </xsl:copy>
+</xsl:template>
+
+<xsl:template match="text:text"/>
+
+<xsl:template match="seth:resultsproxy">
+       <xsl:apply-templates select="html"/>
+</xsl:template>
+
+<xsl:template match="a[starts-with(@href,'http://')]">
+       <xsl:variable name="temp1">
+               <xsl:if test="contains(@href,'http://')">
+               <xsl:value-of select="substring-after(@href,'http://')"/>
+               </xsl:if>
+       </xsl:variable>
+       <xsl:variable name="temp2">
+               <xsl:choose>
+               <xsl:when test="contains($temp1,'/')">
+               <xsl:value-of select="substring-before($temp1,'/')"/>
+               </xsl:when>
+               <xsl:otherwise>
+                       <xsl:value-of select="$temp1"/>
+               </xsl:otherwise>
+               </xsl:choose>
+       </xsl:variable>
+       <xsl:variable name="temp3">
+               <xsl:if test="contains($temp2,'.')">
+               <xsl:choose>
+               <xsl:when test="contains(substring-after($temp2,'.'),'.')">
+                       <xsl:value-of select="substring-after($temp2,'.')"/>
+               </xsl:when>
+               <xsl:otherwise>
+                       <xsl:value-of select="$temp2"/>
+               </xsl:otherwise>
+               </xsl:choose>
+               </xsl:if>
+       </xsl:variable>
+       <xsl:variable name="the_host">
+               <xsl:choose>
+               <xsl:when test="string-length($temp3) = 0">
+                       <xsl:text>nada.nada</xsl:text>
+               </xsl:when>
+               <xsl:otherwise>
+                       <xsl:value-of select="$temp3"/>
+               </xsl:otherwise>
+               </xsl:choose>
+       </xsl:variable>
+       <a>
+               <xsl:attribute name="target">
+                       <xsl:text>_blank</xsl:text>
+               </xsl:attribute>
+               <xsl:choose>
+               <xsl:when test="contains($ezproxy_hosts,$the_host)">
+                       <xsl:variable name="temp4">
+                       <xsl:choose>
+                       <xsl:when test="contains(@href,'/url?q=')">
+                               <xsl:value-of select="substring-after(
+                                       @href,'/url?q=')"/>
+                       </xsl:when>
+                       <xsl:otherwise>
+                               <xsl:value-of select="@href"/>
+                       </xsl:otherwise>
+                       </xsl:choose>
+                       </xsl:variable>
+
+                       <xsl:variable name="temp5">
+                       <xsl:choose>
+                       <xsl:when test="starts-with($temp4,'http://')">
+                               <xsl:value-of select="substring-after(
+                                       $temp4,'http://')"/>
+                       </xsl:when>
+                       <xsl:otherwise>
+                               <xsl:value-of select="@href" />
+                       </xsl:otherwise>
+                       </xsl:choose>
+                       </xsl:variable>
+
+                       <xsl:attribute name="href"> 
+                       <xsl:choose>
+                       <xsl:when test="contains($temp5,'://')">
+                       <xsl:value-of select="$proxy_fixslash"/>
+                       <!--
+                       <xsl:call-template name="replaceCharsInString">
+                               <xsl:with-param name="stringIn" 
+                                       select="$temp5"/>
+                               <xsl:with-param name="charsIn" 
+                                       select="'://'"/>
+                               <xsl:with-param name="charsOut" 
+                                       select="''"/>
+                       </xsl:call-template>
+                       -->
+                       </xsl:when>
+                       <xsl:otherwise>
+                       <xsl:value-of select="$proxy"/>
+                       </xsl:otherwise>
+                       </xsl:choose>
+                       <xsl:value-of select="$temp5"/>
+                       </xsl:attribute>
+                       <xsl:value-of select="."/>
+                       <xsl:text> (proxied)</xsl:text>
+               </xsl:when>
+               <xsl:otherwise>
+                       <xsl:attribute name="href">
+                       <xsl:value-of select="@href"/>
+                       </xsl:attribute>
+                       <xsl:apply-templates/>
+               </xsl:otherwise>
+               </xsl:choose>
+       </a>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/Open-ILS/src/extras/authcon/auth/stylesheets/sethfinal.xsl b/Open-ILS/src/extras/authcon/auth/stylesheets/sethfinal.xsl
new file mode 100644 (file)
index 0000000..013eb62
--- /dev/null
@@ -0,0 +1,146 @@
+<?xml version="1.0"?>
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+               xmlns:seth="http://seth.sourceforge.net">
+
+
+<xsl:template match="text()"/>
+
+<xsl:template match="retrieval-results">
+       <xsl:variable name="barcode">
+               <xsl:value-of select="wibs-info/barcode"/>
+       </xsl:variable>
+       <xsl:choose>
+               <xsl:when test="contains($barcode,'Sorry')">
+                       <xsl:call-template name="showmsg">
+                               <xsl:with-param name="msg" 
+                                       select="$barcode"/>
+                       </xsl:call-template>
+               </xsl:when>
+               <xsl:otherwise>
+                       <xsl:call-template name="passthru">
+                               <xsl:with-param name="cookie" 
+                                       select="cookies/cookie[1]"/>
+                       </xsl:call-template>
+               </xsl:otherwise>
+       </xsl:choose>
+
+</xsl:template>
+
+<xsl:template name="showmsg">
+       <xsl:param name="msg"/>
+
+       <html>
+                <head>
+                        <title>Authorization Status</title>
+                </head>
+
+                <body bgcolor="#ffffff">
+                <table style="border-collapse: collapse"
+                       cellSpacing="" cellPadding="0" border="0">
+                <tr>
+                       <td valign="top" background="bback.gif">
+                        <img src="status.gif"/>
+                       </td>
+                       <td  width="100%" background="bback.gif" bgColor="#cae2f0"/>
+                       <td  valign="top" background="bback.gif" bgColor="#cae2f0">
+                               <img src="end.gif"/>
+                       </td>
+                </tr>
+                </table>
+               <table style="border-collapse: collapse" align="middle"
+               borderColor="#cae2f0" cellSpacing="0" cellPadding="0" width="100%" border="0">
+               <tr>
+                       <td bgColor="#cae2f0"/>
+                       <td valign="top" align="middle" 
+                               bgColor="#cae2f0">
+                       <form method="get" action="showedinfo" name="showform">
+                       <table>
+                       <tr>
+                       <td/>
+                       <td>
+                       <center>
+                       <strong>
+                       <xsl:value-of select="$msg"/>
+                       </strong>
+                       </center>
+                       </td>
+                       </tr>
+                       <tr>
+                       <td/>
+                       <td>
+                       <center>
+                       <input type="image" height="21" alt="OK" width="21"
+                       src="ok.gif" value="OK" border="0" />
+                       </center>
+                       </td>
+                       </tr>
+                       </table>
+                       <br clear="left"/>
+                       </form>
+                       </td>
+               </tr>
+                </table>
+                </body>
+        </html>
+</xsl:template>
+
+<xsl:template name="passthru">
+       <xsl:param name="cookie"/>
+
+       <html>
+       <head>
+       <title>Connecting to Racer</title>
+       <xsl:text disable-output-escaping="yes"> 
+       <![CDATA[
+       <meta HTTP-EQUIV="REFRESH" 
+       content="10; url=http://racer.scholarsportal.info/zportal/zengine?VDXaction=IllAdmin">
+       <script type="text/javascript">
+       <!--
+       function SetCookie(days,thiscookie) {
+               var today = new Date();
+               var expire = new Date();
+               if (days==null || days==0) days=1;
+               expire.setTime(today.getTime() + 3600000*24*days);
+               cookieStr = 'JSESSIONID='+escape(thiscookie);
+               document.cookie = cookieStr;
+               alert(cookieStr);
+               alert('7. cookie set' + document.cookie + ' ' + getCookie('JSESSIONID'));
+       }
+function getCookie(name)
+{
+    var dc = document.cookie;
+    var prefix = name + "=";
+    var begin = dc.indexOf("; " + prefix);
+    if (begin == -1)
+    {
+        begin = dc.indexOf(prefix);
+        if (begin != 0) return null;
+    }
+    else
+    {
+        begin += 2;
+    }
+    var end = document.cookie.indexOf(";", begin);
+    if (end == -1)
+    {
+        end = dc.length;
+    }
+    return unescape(dc.substring(begin + prefix.length, end));
+}
+       // -->
+        </script>
+       ]]>
+       </xsl:text>
+       </head>
+                <body bgcolor="#ffffff">
+               <xsl:attribute name="onload">
+                       <xsl:text>SetCookie(1,'</xsl:text>
+                       <xsl:value-of select="$cookie"/>
+                       <xsl:text>');</xsl:text>
+               </xsl:attribute>
+               <h3>Connecting, please wait...</h3>
+                </body>
+        </html>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/Open-ILS/src/extras/authcon/auth/stylesheets/simple-page2html.xsl b/Open-ILS/src/extras/authcon/auth/stylesheets/simple-page2html.xsl
new file mode 100644 (file)
index 0000000..0ea8fb3
--- /dev/null
@@ -0,0 +1,103 @@
+<?xml version="1.0"?>
+<!--
+  Copyright 1999-2004 The Apache Software Foundation
+
+  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.
+-->
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+  <xsl:param name="contextPath"/>
+  <xsl:param name="servletPath" select="string('/samples')"/>
+  <xsl:param name="sitemapURI"/>
+
+  <xsl:variable name="directory" select="substring-before($servletPath,$sitemapURI)"/>
+  <!-- assume that sitemapURIs don't occur in servletPath more than once -->
+  <xsl:variable name="sitemap" select="concat($directory,'sitemap.xmap')"/>
+
+  <xsl:template match="page">
+   <html>
+     <head>
+       <title><xsl:value-of select="title"/></title>
+       <link rel="stylesheet" href="{$contextPath}/styles/main.css" title="Default Style"/>
+       <!-- copy local CSS, if any -->
+       <xsl:copy-of select="style"/>
+     </head>
+     <body>
+       <xsl:call-template name="resources"/>
+       <xsl:apply-templates/>
+     </body>
+   </html>
+  </xsl:template>
+
+  <xsl:template name="resources">
+    <div class="resources">
+       <!--
+      <a href="?cocoon-view=content">Content View</a>
+      <a href="?cocoon-view=pretty-content">Source</a>
+      <a href="{$sitemap}?cocoon-view=pretty-content">Sitemap</a>
+      <xsl:for-each select="resources/resource">
+        <xsl:variable name="href">
+          <xsl:choose>
+            <xsl:when test="@type='file'">
+              <xsl:value-of select="@href"/>
+            </xsl:when>
+            <xsl:when test="@type='doc'">
+              <xsl:value-of select="concat($contextPath, '/docs/', @href)"/>
+            </xsl:when>
+            <xsl:otherwise>
+              <xsl:value-of select="concat($contextPath, '/', @href)"/>
+            </xsl:otherwise>
+          </xsl:choose>
+        </xsl:variable>
+        <a class="{@type}" href="{$href}">
+          <xsl:apply-templates/>
+        </a>
+      </xsl:for-each>
+       -->
+    </div>
+  </xsl:template>
+
+  <xsl:template match="resources"/>
+
+  <xsl:template match="title">
+   <h2>
+     <xsl:apply-templates/>
+   </h2>
+  </xsl:template>
+
+  <xsl:template match="content">
+    <xsl:apply-templates/>
+  </xsl:template>
+
+  <xsl:template match="para">
+   <p>
+     <xsl:apply-templates/>
+   </p>
+  </xsl:template>
+
+  <xsl:template match="link">
+   <a href="{@href}">
+     <xsl:apply-templates/>
+   </a>
+  </xsl:template>
+
+  <xsl:template match="error">
+    <span class="error">
+      <xsl:apply-templates/>
+    </span>
+  </xsl:template>
+
+  <xsl:template match="@*|node()" priority="-2"><xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy></xsl:template>
+  <xsl:template match="text()" priority="-1"><xsl:value-of select="."/></xsl:template>
+</xsl:stylesheet>
diff --git a/Open-ILS/src/extras/authcon/auth/stylesheets/xml2html.xslt b/Open-ILS/src/extras/authcon/auth/stylesheets/xml2html.xslt
new file mode 100644 (file)
index 0000000..043df49
--- /dev/null
@@ -0,0 +1,254 @@
+<?xml version="1.0"?>
+<!--
+  Copyright 1999-2004 The Apache Software Foundation
+
+  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.
+-->
+
+<!--+
+    | XSLT REC Compliant Version of IE5 Default Stylesheet
+    |
+    | Original version by Jonathan Marsh (jmarsh@microsoft.com)
+    | Conversion to XSLT 1.0 REC Syntax by Steve Muench (smuench@oracle.com)
+    | Added script support by Andrew Timberlake (andrew@timberlake.co.za)
+    | Cleaned up and ported to standard DOM by Stefano Mazzocchi (stefano@apache.org)
+    |
+    | CVS $Id: xml2html.xslt 30932 2004-07-29 17:35:38Z vgritsenko $
+    +-->
+    
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+   <xsl:template match="/">
+      <HTML>
+         <xsl:call-template name="head"/>
+         <BODY>
+            <xsl:apply-templates/>
+         </BODY>
+      </HTML>
+   </xsl:template>
+
+   <xsl:template name="head">
+         <HEAD>
+            <STYLE>
+              BODY  {background-color: white; color: black; font-family: monospace;}
+                .b  {cursor:pointer; color:red; font-weight:bold; text-decoration:none; padding-right: 2px;}
+                .e  {border: 0px; padding: 0px; margin: 0px 0px 0px 2em; text-indent:-1em;}
+                .en {color:#000088; font-weight:bold;}
+                .an {color:#880000}
+                .av {color:#888888}
+                .c  {color:#008800}
+                .t  {color:black}
+                .m  {color:navy}
+                .pi {color:red}
+                PRE {margin:0px; display:inline}
+                DIV {border:0; padding:0; margin:0;}
+            </STYLE>
+            <SCRIPT><xsl:comment><![CDATA[
+function click(event) {
+
+    var mark = event.target;
+    while ((mark.className != "b") && (mark.nodeName != "BODY")) {
+        mark = mark.parentNode
+    }
+
+    var e = mark;
+    while ((e.className != "e") && (e.nodeName != "BODY")) {
+        e = e.parentNode
+    }
+
+    if (mark.childNodes[0].nodeValue == "+") {
+        mark.childNodes[0].nodeValue = "-";
+        for (var i = 2; i < e.childNodes.length; i++) {
+            var name = e.childNodes[i].nodeName;
+            if (name != "#text") {
+                if (name == "PRE" || name == "SPAN") {
+                   window.status = "inline";
+                   e.childNodes[i].style.display = "inline";
+                } else {
+                   e.childNodes[i].style.display = "block";
+                }
+            }
+        }
+    } else if (mark.childNodes[0].nodeValue == "-") {
+        mark.childNodes[0].nodeValue = "+";
+        for (var i = 2; i < e.childNodes.length; i++) {
+            if (e.childNodes[i].nodeName != "#text") {
+                e.childNodes[i].style.display = "none";
+            }
+        }
+    }
+}  
+]]></xsl:comment>
+            </SCRIPT>
+         </HEAD>
+   </xsl:template>
+
+   <!-- match processing instructions -->
+   <xsl:template match="processing-instruction()">
+      <DIV class="e">
+         <SPAN class="m">&lt;?</SPAN>
+         <SPAN class="pi">
+            <xsl:value-of select="name(.)"/>
+            <xsl:text> </xsl:text>
+            <xsl:value-of select="."/>
+         </SPAN>
+         <SPAN class="m">?></SPAN>
+      </DIV>
+   </xsl:template>
+
+   <!-- match text -->
+   <xsl:template match="text()">
+      <DIV class="e">
+         <SPAN class="t">
+            <xsl:value-of select="."/>
+         </SPAN>
+      </DIV>
+   </xsl:template>
+
+   <!-- match comments -->
+   <xsl:template match="comment()">
+      <DIV class="e">
+         <SPAN class="b" onclick="click(event)">-</SPAN>
+         <SPAN class="m">&lt;!--</SPAN>
+         <SPAN class="c">
+            <PRE>
+               <xsl:value-of select="."/>
+            </PRE>
+         </SPAN>
+         <SPAN class="m">--></SPAN>
+      </DIV>
+   </xsl:template>
+
+   <!-- match attributes -->
+   <xsl:template match="@*">
+      <SPAN class="an">
+         <xsl:value-of select="name(.)"/>
+      </SPAN>
+      <SPAN class="m">="</SPAN>
+      <SPAN class="av">
+         <xsl:value-of select="."/>
+      </SPAN>
+      <SPAN class="m">"</SPAN>
+      <xsl:if test="position()!=last()">
+         <xsl:text> </xsl:text>
+      </xsl:if>
+   </xsl:template>
+   
+   <!-- match empty elements -->
+   <xsl:template match="*[not(node())]">
+      <DIV class="e">
+        <SPAN class="m">&lt;</SPAN>
+        <SPAN class="en">
+           <xsl:value-of select="name(.)"/>
+        </SPAN>
+        <xsl:if test="@*">
+           <xsl:text> </xsl:text>
+        </xsl:if>
+        <xsl:apply-templates select="@*"/>
+        <xsl:apply-templates select="." mode="namespace"/>
+        <SPAN class="m">/&gt;</SPAN>
+      </DIV>
+   </xsl:template>
+
+   <!-- match elements with only text(), they are not closeable -->
+   <xsl:template match="*[text()][not(* or comment() or processing-instruction())]" priority="10">
+      <DIV class="e">
+        <SPAN class="m">&lt;</SPAN>
+        <SPAN class="en">
+           <xsl:value-of select="name(.)"/>
+        </SPAN>
+        <xsl:if test="@*">
+           <xsl:text> </xsl:text>
+        </xsl:if>
+        <xsl:apply-templates select="@*"/>
+        <xsl:apply-templates select="." mode="namespace"/>
+        <SPAN class="m">
+           <xsl:text>></xsl:text>
+        </SPAN>
+        <SPAN class="t">
+           <xsl:value-of select="."/>
+        </SPAN>
+        <SPAN class="m">&lt;/</SPAN>
+        <SPAN class="en">
+           <xsl:value-of select="name(.)"/>
+        </SPAN>
+        <SPAN class="m">
+           <xsl:text>></xsl:text>
+        </SPAN>
+      </DIV>
+   </xsl:template>
+
+   <xsl:template match="*[node()]">
+      <DIV class="e">
+         <DIV>
+            <SPAN class="b" onclick="click(event)">-</SPAN>
+            <SPAN class="m">&lt;</SPAN>
+            <SPAN class="en">
+               <xsl:value-of select="name(.)"/>
+            </SPAN>
+            <xsl:if test="@*">
+               <xsl:text> </xsl:text>
+            </xsl:if>
+            <xsl:apply-templates select="@*"/>
+            <xsl:apply-templates select="." mode="namespace"/>
+            <SPAN class="m">
+               <xsl:text>></xsl:text>
+            </SPAN>
+         </DIV>
+         <DIV>
+            <xsl:apply-templates/>
+            <DIV>
+               <SPAN class="m">&lt;/</SPAN>
+               <SPAN class="en">
+                  <xsl:value-of select="name(.)"/>
+               </SPAN>
+               <SPAN class="m">
+                  <xsl:text>></xsl:text>
+               </SPAN>
+            </DIV>
+         </DIV>
+      </DIV>
+   </xsl:template>
+
+   <xsl:template match="*" mode="namespace">
+     <xsl:variable name="context" select="."/>
+     <xsl:for-each select="namespace::node()">
+       <xsl:variable name="nsuri" select="."/>
+       <xsl:variable name="nsprefix" select="name()"/>
+       <xsl:choose>
+        <xsl:when test="$nsprefix = 'xml'">
+          <!-- xml namespace -->
+        </xsl:when>
+        <xsl:when test="$context/../namespace::node()[name() = $nsprefix and . = $nsuri]">
+          <!-- namespace already declared on the parent -->
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:text> </xsl:text>
+          <SPAN class="an">
+            <xsl:text>xmlns</xsl:text>
+            <xsl:if test="$nsprefix">
+              <xsl:text>:</xsl:text>
+              <xsl:value-of select="$nsprefix"/>
+            </xsl:if>
+          </SPAN>
+          <SPAN class="m">="</SPAN>
+          <SPAN class="av">
+            <xsl:value-of select="."/>
+          </SPAN>
+          <SPAN class="m">"</SPAN>
+        </xsl:otherwise>
+       </xsl:choose>
+     </xsl:for-each>
+   </xsl:template>
+
+</xsl:stylesheet>
diff --git a/Open-ILS/src/extras/authcon/seth/build.xml b/Open-ILS/src/extras/authcon/seth/build.xml
new file mode 100644 (file)
index 0000000..bf921c4
--- /dev/null
@@ -0,0 +1,256 @@
+<!-- PLEASE LOOK AT THE README FILE BEFORE EDITING THIS FILE -->
+
+<project name="sethTransformer" default="compile" basedir=".">
+
+  <property name="app.name"      value="sethTransformer"/>
+  <property name="app.version"   value="1.0"/>
+  <property name="cocoon.home"   value="/home/administrator/src/evergreen/authcon/cocoon-2.1.11/build/webapp"/>
+  <property name="build.home"    value="build"/>
+  <property name="deploy.home"   value="${cocoon.home}/WEB-INF/lib"/>
+  <property name="dist.home"     value="dist"/>
+
+
+
+<!--  ==================== Compilation Control Options ==================== -->
+
+<!--
+
+  These properties control option settings on the Javac compiler when it
+  is invoked using the <javac> task.
+
+  compile.debug        Should compilation include the debug option?
+
+  compile.deprecation  Should compilation include the deprecation option?
+
+  compile.optimize     Should compilation include the optimize option?
+
+-->
+
+  <property name="compile.debug"       value="true"/>
+  <property name="compile.deprecation" value="false"/>
+  <property name="compile.optimize"    value="true"/>
+
+
+
+<!-- ==================== External Dependencies =========================== -->
+
+
+<!--
+
+  Use property values to define the locations of external JAR files on which
+  your application will depend.  In general, these values will be used for
+  two purposes:
+  * Inclusion on the classpath that is passed to the Javac compiler
+  * Being copied into the "/WEB-INF/lib" directory during execution
+    of the "deploy" target.
+
+  Because we will automatically include all of the Java classes that Tomcat 4
+  exposes to web applications, we will not need to explicitly list any of those
+  dependencies.  You only need to worry about external dependencies for JAR
+  files that you are going to include inside your "/WEB-INF/lib" directory.
+
+-->
+
+<!-- Dummy external dependency -->
+<!--
+  <property name="foo.jar"
+           value="/path/to/foo.jar"/>
+-->
+<!-- IF USING HSQL
+  <property name="hsql.jar"
+           value="\pytheas\osdls\servlet\lib\hsql.jar"/>
+-->
+  
+<!-- ==================== Compilation Classpath =========================== -->
+
+<!--
+
+  Rather than relying on the CLASSPATH environment variable, Ant includes
+  features that makes it easy to dynamically construct the classpath you
+  need for each compilation.  The example below constructs the compile
+  classpath to include the servlet.jar file, as well as the other components
+  that Tomcat makes available to web applications automatically, plus anything
+  that you explicitly added.
+
+-->
+
+  <path id="compile.classpath">
+
+    <!-- Include all JAR files that will be included in /WEB-INF/lib -->
+    <!-- *** CUSTOMIZE HERE AS REQUIRED BY YOUR APPLICATION *** -->
+<!--
+    <pathelement location="${foo.jar}"/>
+-->
+
+<!-- Include all elements that Cocoon exposes to applications -->
+    <fileset dir="${cocoon.home}/WEB-INF/lib">
+      <include name="*.jar"/>
+    </fileset>
+
+  </path>
+
+
+
+<!-- ==================== All Target ====================================== -->
+
+<!--
+
+  The "all" target is a shortcut for running the "clean" target followed
+  by the "compile" target, to force a complete recompile.
+
+-->
+
+  <target name="all" depends="clean,compile"
+   description="Clean build and dist, then compile"/>
+
+
+
+<!-- ==================== Clean Target ==================================== -->
+
+<!--
+
+  The "clean" target deletes any previous "build" and "dist" directory,
+  so that you can be ensured the application can be built from scratch.
+
+-->
+
+  <target name="clean"
+   description="Delete old build and dist directories">
+    <delete dir="${build.home}"/>
+    <delete dir="${dist.home}"/>
+    <!-- delete dir="${webapp.root}"/ -->    
+  </target>
+
+
+<!-- The "env" target prints the JAVA environment variables out -->
+  <target name="env">
+    <echo message="${java.home}"/>
+  </target>
+
+
+<!-- ==================== Compile Target ================================== -->
+
+<!--
+
+  The "compile" target transforms source files (from your "src" directory)
+  into object files in the appropriate location in the build directory.
+  This example assumes that you will be including your classes in an
+  unpacked directory hierarchy under "/WEB-INF/classes".
+
+-->
+
+  <target name="compile" depends="prepare"
+   description="Compile Java sources">
+
+    <!-- Compile Java classes as necessary -->
+    <mkdir    dir="${build.home}/classes"/>
+    <javac srcdir="src"
+          destdir="${build.home}/classes"
+           debug="${compile.debug}"
+     deprecation="${compile.deprecation}"
+        optimize="${compile.optimize}">
+        <classpath refid="compile.classpath"/>
+    </javac>
+
+    <!-- Copy associated resource files -->
+    <copy  todir="${build.home}/classes">
+    <fileset dir="src" includes="**/*.properties"/>
+    </copy>
+
+  </target>
+
+
+
+<!-- ==================== Deploy Target =================================== -->
+
+<!--
+
+  The "deploy" target copies the contents of the build directory into a
+  location required by our servlet container, and picks up any external
+  dependencies along the way.  AFter restarting the servlet container, you
+  can now test your web application.
+
+-->
+
+  <target name="deploy" depends="dist"
+   description="Deploy application to servlet container">
+
+    <!-- Copy associated resource files -->
+
+   <copy todir="${deploy.home}" file="${dist.home}/${app.name}.jar"/>
+  </target>
+
+
+
+<!-- ==================== Dist Target ===================================== -->
+
+
+<!--
+
+  The "dist" target creates a binary distribution of your application
+  in a directory structure ready to be archived in a tar.gz or zip file.
+  Note that this target depends on two others:
+  * "deploy" so that the entire web application (including external
+    dependencies) will have been assembled
+  * "javadoc" so that the application Javadocs will have been created
+
+-->
+
+  <target name="dist" depends="compile"
+   description="Create binary distribution">
+    <mkdir    dir="${dist.home}"/>
+
+    <!-- Create application JAR file -->
+    <jar jarfile="${dist.home}/${app.name}.jar"
+         basedir="${build.home}/classes"/>
+
+    <!-- Copy additional files to ${dist.home} as necessary -->
+
+  </target>
+
+
+
+<!-- ==================== Javadoc Target ================================== -->
+
+<!--
+
+  The "javadoc" target creates Javadoc API documentation for the Java
+  classes included in your application.  Normally, this is only required
+  when preparing a distribution release, but is available as a separate
+  target in case the developer wants to create Javadocs independently.
+
+-->
+
+  <target name="javadoc" depends="compile"
+   description="Create Javadoc API documentation">
+
+    <mkdir          dir="${dist.home}/docs/api"/>
+    <!-- javadoc sourcepath="src" destdir="${dist.home}/docs/api" packagenames="mypackage.*"/ -->
+
+  </target>
+
+
+
+<!-- ==================== Prepare Target ================================== -->
+
+<!--
+
+  The "prepare" target is used to create the "build" destination directory,
+  and copy the static contents of your web application to it.  If you need
+  to copy static files from external dependencies, you can customize the
+  contents of this task.
+
+  Normally, this task is executed indirectly when needed.
+
+-->
+
+  <target name="prepare">
+
+    <!-- Create build directory and copy static content -->
+    <mkdir  dir="${build.home}"/>
+
+    <!-- Copy static files from external dependencies as needed -->
+
+  </target>
+
+</project>
diff --git a/Open-ILS/src/extras/authcon/seth/src/EasySSLProtocolSocketFactory.java b/Open-ILS/src/extras/authcon/seth/src/EasySSLProtocolSocketFactory.java
new file mode 100644 (file)
index 0000000..cd332ab
--- /dev/null
@@ -0,0 +1,238 @@
+package org.apache.cocoon.transformation;
+
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ * 
+ * ====================================================================
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.UnknownHostException;
+
+import javax.net.SocketFactory;
+//import javax.net.ssl.SSLContext;
+//import javax.net.ssl.TrustManager;
+import com.sun.net.ssl.SSLContext;
+import com.sun.net.ssl.TrustManagerFactory;
+import com.sun.net.ssl.TrustManager;
+import com.sun.net.ssl.X509TrustManager;
+
+import org.apache.commons.httpclient.ConnectTimeoutException;
+import org.apache.commons.httpclient.HttpClientError;
+import org.apache.commons.httpclient.params.HttpConnectionParams;
+import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+//import org.apache.commons.httpclient.contrib.ssl.EasyX509TrustManager;
+
+/**
+ * <p>
+ * EasySSLProtocolSocketFactory can be used to creats SSL {@link Socket}s 
+ * that accept self-signed certificates. 
+ * </p>
+ * <p>
+ * This socket factory SHOULD NOT be used for productive systems 
+ * due to security reasons, unless it is a concious decision and 
+ * you are perfectly aware of security implications of accepting 
+ * self-signed certificates
+ * </p>
+ *
+ * <p>
+ * Example of using custom protocol socket factory for a specific host:
+ *     <pre>
+ *     Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
+ *
+ *     URI uri = new URI("https://localhost/", true);
+ *     // use relative url only
+ *     GetMethod httpget = new GetMethod(uri.getPathQuery());
+ *     HostConfiguration hc = new HostConfiguration();
+ *     hc.setHost(uri.getHost(), uri.getPort(), easyhttps);
+ *     HttpClient client = new HttpClient();
+ *     client.executeMethod(hc, httpget);
+ *     </pre>
+ * </p>
+ * <p>
+ * Example of using custom protocol socket factory per default instead of the standard one:
+ *     <pre>
+ *     Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
+ *     Protocol.registerProtocol("https", easyhttps);
+ *
+ *     HttpClient client = new HttpClient();
+ *     GetMethod httpget = new GetMethod("https://localhost/");
+ *     client.executeMethod(httpget);
+ *     </pre>
+ * </p>
+ * 
+ * @author <a href="mailto:oleg -at- ural.ru">Oleg Kalnichevski</a>
+ * 
+ * <p>
+ * DISCLAIMER: HttpClient developers DO NOT actively support this component.
+ * The component is provided as a reference material, which may be inappropriate
+ * for use without additional customization.
+ * </p>
+ */
+
+public class EasySSLProtocolSocketFactory implements SecureProtocolSocketFactory {
+
+    /** Log object for this class. */
+    private static final Log LOG = LogFactory.getLog(EasySSLProtocolSocketFactory.class);
+
+    private SSLContext sslcontext = null;
+
+    /**
+     * Constructor for EasySSLProtocolSocketFactory.
+     */
+    public EasySSLProtocolSocketFactory() {
+        super();
+    }
+
+    private static SSLContext createEasySSLContext() {
+        try {
+            SSLContext context = SSLContext.getInstance("SSL");
+            context.init(
+              null, 
+              new TrustManager[] {new EasyX509TrustManager(null)}, 
+              null);
+            return context;
+        } catch (Exception e) {
+            LOG.error(e.getMessage(), e);
+            throw new HttpClientError(e.toString());
+        }
+    }
+
+    private SSLContext getSSLContext() {
+        if (this.sslcontext == null) {
+            this.sslcontext = createEasySSLContext();
+        }
+        return this.sslcontext;
+    }
+
+    /**
+     * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int)
+     */
+    public Socket createSocket(
+        String host,
+        int port,
+        InetAddress clientHost,
+        int clientPort)
+        throws IOException, UnknownHostException {
+
+        return getSSLContext().getSocketFactory().createSocket(
+            host,
+            port,
+            clientHost,
+            clientPort
+        );
+    }
+
+    /**
+     * Attempts to get a new socket connection to the given host within the given time limit.
+     * <p>
+     * To circumvent the limitations of older JREs that do not support connect timeout a 
+     * controller thread is executed. The controller thread attempts to create a new socket 
+     * within the given limit of time. If socket constructor does not return until the 
+     * timeout expires, the controller terminates and throws an {@link ConnectTimeoutException}
+     * </p>
+     *  
+     * @param host the host name/IP
+     * @param port the port on the host
+     * @param clientHost the local host name/IP to bind the socket to
+     * @param clientPort the port on the local machine
+     * @param params {@link HttpConnectionParams Http connection parameters}
+     * 
+     * @return Socket a new socket
+     * 
+     * @throws IOException if an I/O error occurs while creating the socket
+     * @throws UnknownHostException if the IP address of the host cannot be
+     * determined
+     */
+    public Socket createSocket(
+        final String host,
+        final int port,
+        final InetAddress localAddress,
+        final int localPort,
+        final HttpConnectionParams params
+    ) throws IOException, UnknownHostException, ConnectTimeoutException {
+        if (params == null) {
+            throw new IllegalArgumentException("Parameters may not be null");
+        }
+        int timeout = params.getConnectionTimeout();
+        SocketFactory socketfactory = getSSLContext().getSocketFactory();
+        if (timeout == 0) {
+            return socketfactory.createSocket(host, port, localAddress, localPort);
+        } else {
+            Socket socket = socketfactory.createSocket();
+            SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
+            SocketAddress remoteaddr = new InetSocketAddress(host, port);
+            socket.bind(localaddr);
+            socket.connect(remoteaddr, timeout);
+            return socket;
+        }
+    }
+
+    /**
+     * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int)
+     */
+    public Socket createSocket(String host, int port)
+        throws IOException, UnknownHostException {
+        return getSSLContext().getSocketFactory().createSocket(
+            host,
+            port
+        );
+    }
+
+    /**
+     * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean)
+     */
+    public Socket createSocket(
+        Socket socket,
+        String host,
+        int port,
+        boolean autoClose)
+        throws IOException, UnknownHostException {
+        return getSSLContext().getSocketFactory().createSocket(
+            socket,
+            host,
+            port,
+            autoClose
+        );
+    }
+
+    public boolean equals(Object obj) {
+        return ((obj != null) && obj.getClass().equals(EasySSLProtocolSocketFactory.class));
+    }
+
+    public int hashCode() {
+        return EasySSLProtocolSocketFactory.class.hashCode();
+    }
+
+}
diff --git a/Open-ILS/src/extras/authcon/seth/src/EasyX509TrustManager.java b/Open-ILS/src/extras/authcon/seth/src/EasyX509TrustManager.java
new file mode 100644 (file)
index 0000000..0090dd0
--- /dev/null
@@ -0,0 +1,121 @@
+package org.apache.cocoon.transformation;
+/*
+ * ====================================================================
+ *
+ *  Copyright 2002-2004 The Apache Software Foundation
+ *
+ *  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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import com.sun.net.ssl.TrustManagerFactory;
+import com.sun.net.ssl.TrustManager;
+import com.sun.net.ssl.X509TrustManager;
+import org.apache.commons.logging.Log; 
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * <p>
+ * EasyX509TrustManager unlike default {@link X509TrustManager} accepts 
+ * self-signed certificates. 
+ * </p>
+ * <p>
+ * This trust manager SHOULD NOT be used for productive systems 
+ * due to security reasons, unless it is a concious decision and 
+ * you are perfectly aware of security implications of accepting 
+ * self-signed certificates
+ * </p>
+ * 
+ * @author <a href="mailto:adrian.sutton@ephox.com">Adrian Sutton</a>
+ * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
+ * 
+ * <p>
+ * DISCLAIMER: HttpClient developers DO NOT actively support this component.
+ * The component is provided as a reference material, which may be inappropriate
+ * for use without additional customization.
+ * </p>
+ */
+
+public class EasyX509TrustManager implements X509TrustManager
+{
+    private X509TrustManager standardTrustManager = null;
+
+    /** Log object for this class. */
+    private static final Log LOG = LogFactory.getLog(EasyX509TrustManager.class);
+
+    /**
+     * Constructor for EasyX509TrustManager.
+     */
+    public EasyX509TrustManager(KeyStore keystore) throws NoSuchAlgorithmException, KeyStoreException {
+        super();
+        TrustManagerFactory factory = TrustManagerFactory.getInstance("SunX509");
+        factory.init(keystore);
+        TrustManager[] trustmanagers = factory.getTrustManagers();
+        if (trustmanagers.length == 0) {
+            throw new NoSuchAlgorithmException("SunX509 trust manager not supported");
+        }
+        this.standardTrustManager = (X509TrustManager)trustmanagers[0];
+    }
+
+    /**
+     * @see com.sun.net.ssl.X509TrustManager#isClientTrusted(X509Certificate[])
+     */
+    public boolean isClientTrusted(X509Certificate[] certificates) {
+        return this.standardTrustManager.isClientTrusted(certificates);
+    }
+
+    /**
+     * @see com.sun.net.ssl.X509TrustManager#isServerTrusted(X509Certificate[])
+     */
+    public boolean isServerTrusted(X509Certificate[] certificates) {
+        if ((certificates != null) && LOG.isDebugEnabled()) {
+            LOG.debug("Server certificate chain:");
+            for (int i = 0; i < certificates.length; i++) {
+                LOG.debug("X509Certificate[" + i + "]=" + certificates[i]);
+            }
+        }
+        if ((certificates != null) && (certificates.length == 1)) {
+            X509Certificate certificate = certificates[0];
+            try {
+                certificate.checkValidity(); 
+            }
+            catch (CertificateException e) {
+                LOG.error(e.toString());
+                return false;
+            }
+            return true;
+        } else {
+            return this.standardTrustManager.isServerTrusted(certificates);
+        }
+    }
+
+    /**
+     * @see com.sun.net.ssl.X509TrustManager#getAcceptedIssuers()
+     */
+    public X509Certificate[] getAcceptedIssuers() {
+        return this.standardTrustManager.getAcceptedIssuers();
+    }
+}
diff --git a/Open-ILS/src/extras/authcon/seth/src/sethTransformer.java b/Open-ILS/src/extras/authcon/seth/src/sethTransformer.java
new file mode 100644 (file)
index 0000000..99caf63
--- /dev/null
@@ -0,0 +1,1517 @@
+/*
+       sethTransformer - written in May 2004
+       * updated 2005 for hackfest
+       * updated 2009 for ssl sockets/certificate handling
+
+       (c) Copyright GNU General Public License (GPL)
+       @author <a href="http://librarycog.uwindsor.ca">art rhyno</a>
+*/
+package org.apache.cocoon.transformation;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+
+import java.net.*;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.environment.SourceResolver;
+
+import org.apache.cocoon.xml.dom.DOMStreamer;
+import org.apache.cocoon.xml.XMLConsumer;
+import org.apache.cocoon.xml.XMLUtils;
+
+import org.apache.commons.httpclient.*;
+import org.apache.commons.httpclient.auth.AuthPolicy;
+import org.apache.commons.httpclient.auth.AuthScope;
+import org.apache.commons.httpclient.util.HttpURLConnection;
+import org.apache.commons.httpclient.cookie.CookiePolicy;
+import org.apache.commons.httpclient.methods.*;
+import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.protocol.Protocol;
+import org.apache.commons.httpclient.util.URIUtil;
+
+//import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory;
+
+import org.apache.regexp.RE;
+import org.apache.regexp.RESyntaxException;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.tidy.Tidy;
+
+/**
+ * SETH Transformer - May, 2004
+ *
+ * @author <a href="http://librarycog.uwindsor.ca">art rhyno</a>
+ */
+public class sethTransformer extends AbstractTransformer {
+
+    public static final String my_uri = "http://seth.sourceforge.net";
+    public static final String my_name = "sethTransformer";
+
+    /** Outgoing tags */
+    public static final String RESULTS_ELEMENT = "retrieval-results";
+    public static final String URL_ELEMENT = "url";
+    public static final String RESPONSE_ELEMENT = "responses";
+    public static final String REQUEST_ELEMENT = "requests";
+    public static final String COOKIES_ELEMENT = "cookies";
+    public static final String CONTENTS_ELEMENT = "contents";
+    public static final String REGEXP_ELEMENT = "regexpval";
+
+    /** Our allowed tags */
+    public static final String MAGIC_EXECUTE_RETRIEVAL = "execute-retrieval";
+    public static final String MAGIC_URL_ELEMENT = "url";
+    public static final String MAGIC_USERNAME_ELEMENT = "username";
+    public static final String MAGIC_PASSWORD_ELEMENT = "password";
+    public static final String MAGIC_LIMIT_ELEMENT = "limit";
+    public static final String MAGIC_USERAGENT_ELEMENT = "useragent";
+    public static final String MAGIC_TIMEOUT_ELEMENT = "timeout";
+    public static final String MAGIC_REDIRECT_LIMIT_ELEMENT = "redirect_limit";
+    public static final String MAGIC_REGEXP_ELEMENT = "regexp";
+    public static final String MAGIC_NVP_ELEMENT = "nvp";
+    public static final String MAGIC_COOKIE_ELEMENT = "cookie";
+    public static final String MAGIC_METHOD_ELEMENT = "method";
+    public static final String MAGIC_REDIRECT_ELEMENT = "redirect";
+    public static final String MAGIC_DEBUG_ELEMENT = "debug";
+
+    /** The states we are allowed to be in */
+    public static final int STATE_OUTSIDE = 0;
+    public static final int STATE_INSIDE_EXECUTE_RETRIEVAL = 1;
+    public static final int STATE_INSIDE_URL_ELEMENT = 2;
+    public static final int STATE_INSIDE_USERNAME_ELEMENT = 3;
+    public static final int STATE_INSIDE_PASSWORD_ELEMENT = 4;
+    public static final int STATE_INSIDE_LIMIT_ELEMENT = 5;
+    public static final int STATE_INSIDE_USERAGENT_ELEMENT = 6;
+    public static final int STATE_INSIDE_TIMEOUT_ELEMENT = 7;
+    public static final int STATE_INSIDE_REDIRECT_LIMIT_ELEMENT = 8;
+    public static final int STATE_INSIDE_REGEXP_ELEMENT = 9;
+    public static final int STATE_INSIDE_NVP_ELEMENT = 10;
+    public static final int STATE_INSIDE_COOKIE_ELEMENT = 11;
+    public static final int STATE_INSIDE_METHOD_ELEMENT = 12;
+    public static final int STATE_INSIDE_REDIRECT_ELEMENT = 13;
+    public static final int STATE_INSIDE_DEBUG_ELEMENT = 14;
+
+    /** Default parameters that might apply to all retrievals */
+    protected Properties default_properties = new Properties();
+
+    /** The name of the value element we're currently receiving */
+    protected String current_name;
+
+    /** The current state of the event receiving FSM */
+    protected int current_state = STATE_OUTSIDE;
+
+    /** The value of the value element we're currently receiving */
+    protected StringBuffer current_value = new StringBuffer();
+
+    /** The list of retrievals that we're currently working on */
+    protected Vector retrievals = new Vector();
+
+    /** The offset of the current retrieval in the retrievals list */
+    protected int current_retrieval_index = -1;
+
+    /** SAX producing state information */
+    protected XMLConsumer xml_consumer;
+    protected LexicalHandler lexical_handler;
+
+    /** BEGIN SitemapComponent methods */
+
+    public void setup(SourceResolver resolver, Map objectModel, String source, Parameters parameters)
+        throws ProcessingException, SAXException, IOException {
+        current_state = STATE_OUTSIDE;
+
+       String parameter;
+
+        // Check the url
+        parameter = parameters.getParameter(MAGIC_URL_ELEMENT, null);
+        if (parameter != null) {
+            default_properties.setProperty(MAGIC_URL_ELEMENT, parameter);
+        }
+
+        // Check the username
+        parameter = parameters.getParameter(MAGIC_USERNAME_ELEMENT, null);
+        if (parameter != null) {
+            default_properties.setProperty(MAGIC_USERNAME_ELEMENT, parameter);
+        }
+
+        // Check the password
+        parameter = parameters.getParameter(MAGIC_PASSWORD_ELEMENT, null);
+        if (parameter != null) {
+            default_properties.setProperty(MAGIC_PASSWORD_ELEMENT, parameter);
+        }
+
+        // Check the limit
+        parameter = parameters.getParameter(MAGIC_LIMIT_ELEMENT, null);
+        if (parameter != null) {
+            default_properties.setProperty(MAGIC_LIMIT_ELEMENT, parameter);
+        }
+
+        // Check the useragent
+        parameter = parameters.getParameter(MAGIC_USERAGENT_ELEMENT, null);
+        if (parameter != null) {
+            default_properties.setProperty(MAGIC_USERAGENT_ELEMENT, parameter);
+        }
+
+        // Check the timeout
+        parameter = parameters.getParameter(MAGIC_TIMEOUT_ELEMENT, null);
+        if (parameter != null) {
+            default_properties.setProperty(MAGIC_TIMEOUT_ELEMENT, parameter);
+        }
+
+        // Check the redirect_limit
+        parameter = parameters.getParameter(MAGIC_REDIRECT_LIMIT_ELEMENT, null);
+        if (parameter != null) {
+            default_properties.setProperty(MAGIC_REDIRECT_LIMIT_ELEMENT, parameter);
+        }
+
+        // Check the regexp
+        parameter = parameters.getParameter(MAGIC_REGEXP_ELEMENT, null);
+        if (parameter != null) {
+            default_properties.setProperty(MAGIC_REGEXP_ELEMENT, parameter);
+        }
+
+        // Check the method
+        parameter = parameters.getParameter(MAGIC_METHOD_ELEMENT, null);
+        if (parameter != null) {
+            default_properties.setProperty(MAGIC_METHOD_ELEMENT, parameter);
+        }
+
+        // Check the nvp
+        parameter = parameters.getParameter(MAGIC_NVP_ELEMENT, null);
+        if (parameter != null) {
+            default_properties.setProperty(MAGIC_NVP_ELEMENT, parameter);
+        }
+
+        // Check the cookie
+        parameter = parameters.getParameter(MAGIC_COOKIE_ELEMENT, null);
+        if (parameter != null) {
+            default_properties.setProperty(MAGIC_COOKIE_ELEMENT, parameter);
+        }
+
+        // Check the redirect element
+        parameter = parameters.getParameter(MAGIC_REDIRECT_ELEMENT, null);
+        if (parameter != null) {
+            default_properties.setProperty(MAGIC_REDIRECT_ELEMENT, parameter);
+        }
+
+        // Check the debug element
+        parameter = parameters.getParameter(MAGIC_DEBUG_ELEMENT, null);
+        if (parameter != null) {
+            default_properties.setProperty(MAGIC_DEBUG_ELEMENT, parameter);
+        }
+
+    }
+
+    /** END SitemapComponent methods */
+
+    /**
+     * This will be the meat of sethTransformer, where the retrieval is run.
+     */
+    protected void executeRetrieval(int index) throws SAXException {
+        // this.contentHandler.startPrefixMapping("", sethTransformer.my_uri);
+        HTMLRetrieval retrieval = (HTMLRetrieval) retrievals.elementAt(index);
+        try {
+            retrieval.execute();
+        } catch (Exception e) {
+               System.out.println("error " + e.toString());
+            getLogger().error(e.toString());
+            throw new SAXException(e);
+        }
+
+        this.contentHandler.endPrefixMapping("");
+    }
+
+    protected static void throwIllegalStateException(String message) {
+        throw new IllegalStateException(my_name + ": " + message);
+    }
+
+    /** Move into elements */
+    protected void startExecuteRetrieval(Attributes attributes) {
+        HTMLRetrieval retrieval;
+        switch (current_state) {
+            case sethTransformer.STATE_OUTSIDE :
+                current_state = sethTransformer.STATE_INSIDE_EXECUTE_RETRIEVAL;
+                current_retrieval_index = retrievals.size();
+                retrieval = new HTMLRetrieval(this);
+                retrievals.addElement(retrieval);
+                getCurrentRetrieval().toDo = sethTransformer.STATE_INSIDE_EXECUTE_RETRIEVAL;
+                getCurrentRetrieval().retrieval_index = current_retrieval_index;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a start execute-retrieval element");
+        }
+    }
+
+    protected void endExecuteRetrieval() throws SAXException {
+        switch (current_state) {
+            case STATE_INSIDE_EXECUTE_RETRIEVAL :
+                executeRetrieval(current_retrieval_index);
+                retrievals.remove(current_retrieval_index);
+                --current_retrieval_index;
+                if (current_retrieval_index > -1) {
+                    current_state = getCurrentRetrieval().toDo;
+                } else {
+                    retrievals.removeAllElements();
+                    current_state = sethTransformer.STATE_OUTSIDE;
+                }
+                break;
+            default :
+                throwIllegalStateException("Not expecting a end execute-retrieval element");
+        }
+    }
+
+    protected void startNvpElement(Attributes attributes) {
+       String thisName = attributes.getValue("name");
+
+       if (thisName != null) 
+               getCurrentRetrieval().nvpName = thisName;
+       else
+                throwIllegalStateException("value without name");
+
+       String checkJsonSpace = attributes.getValue("jsspace");
+       if (checkJsonSpace != null)
+               getCurrentRetrieval().jsspace = checkJsonSpace;
+        switch (current_state) {
+            case STATE_INSIDE_EXECUTE_RETRIEVAL :
+                current_value.setLength(0);
+                current_state = sethTransformer.STATE_INSIDE_NVP_ELEMENT;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a start nvp element");
+        }
+    }
+
+    protected void endNvpElement() {
+        switch (current_state) {
+            case sethTransformer.STATE_INSIDE_NVP_ELEMENT :
+               String parmVal = current_value.toString().trim();
+               //examples of extra encoding options
+               /*
+               try {
+                       parmVal = URIUtil.encodeQuery(parmVal);
+               } catch (URIException uriEx) {
+                       System.out.println("prob: " + uriEx.toString());
+                       parmVal = current_value.toString().trim();
+               } */
+               /*
+               try {
+                       parmVal = URLEncoder.encode(parmVal,"UTF-8");
+               } catch (UnsupportedEncodingException uriEx) {
+                       System.out.println("prob: " + uriEx.toString());
+                       parmVal = current_value.toString().trim();
+               }
+               */
+
+               //we can't always rely on uri encodings for whitespaces
+               if (getCurrentRetrieval().jsspace != null)
+                       parmVal = parmVal.replaceAll(" ","\\\\u0020");
+
+               NameValuePair thisNVP = new NameValuePair(
+                                               getCurrentRetrieval().nvpName,
+                                               parmVal);
+                getCurrentRetrieval().nvps.addElement(thisNVP);
+                current_state = getCurrentRetrieval().toDo; 
+               break; 
+           default : 
+               throwIllegalStateException("Not expecting a end nvp element");
+        }
+    }
+
+    protected void startCookieElement(Attributes attributes) {
+       String checkDomain = attributes.getValue("domain");
+       if (checkDomain != null)
+               getCurrentRetrieval().thisDomain = checkDomain;
+
+       if (checkDomain == null) {
+               try {
+                        InetAddress localaddr = InetAddress.getLocalHost();
+                        String thisHost = localaddr.getHostAddress().toString();
+                       int firstPart = thisHost.indexOf(".");
+                       if (firstPart != -1)
+                               getCurrentRetrieval().thisDomain = 
+                                       thisHost.substring(firstPart);
+               } catch (UnknownHostException uhe) {
+                                getCurrentRetrieval().thisDomain = "*";
+                        
+               }
+       }
+       getCurrentRetrieval().thisName = attributes.getValue("name");
+       getCurrentRetrieval().thisPath = attributes.getValue("path");
+       String checkDate = attributes.getValue("date");
+       if (checkDate != null) {
+               DateFormat theFormat = new 
+                       SimpleDateFormat("EEE MMM d HH:mm:ss z yyyy");
+               try {
+                       getCurrentRetrieval().thisDate = 
+                       theFormat.parse(checkDate);
+               } catch (Exception e) {
+                throwIllegalStateException("Problem with cookie date");
+               }
+       }
+       String checkAge = attributes.getValue("age");
+       if (checkAge != null)
+               getCurrentRetrieval().thisAge = Integer.parseInt(checkAge);
+       String checkSecure = attributes.getValue("secure");
+       if (checkSecure != null) {
+               if (checkSecure.trim().toUpperCase().equals("TRUE"))
+               getCurrentRetrieval().isSecure = true;
+       }
+        switch (current_state) {
+            case STATE_INSIDE_EXECUTE_RETRIEVAL :
+                current_value.setLength(0);
+                current_state = sethTransformer.STATE_INSIDE_COOKIE_ELEMENT;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a start cookie element");
+        }
+    }
+
+    protected void endCookieElement() {
+        switch (current_state) {
+            case sethTransformer.STATE_INSIDE_COOKIE_ELEMENT :
+               String thisValue = current_value.toString().trim();
+               Cookie thisCookie;
+                       System.out.println("-> domain: " +
+                               getCurrentRetrieval().thisDomain + "\n name: " +
+                               getCurrentRetrieval().thisName + "\n value: " +
+                               thisValue + "\n path: " +
+                               getCurrentRetrieval().thisPath + "\n date: " + 
+                               getCurrentRetrieval().thisDate +"\n secure: " +
+                               getCurrentRetrieval().isSecure);
+
+               if (getCurrentRetrieval().thisPath != null &&
+                       getCurrentRetrieval().thisDate != null)
+               {
+               System.out.println("1");
+               thisCookie = new Cookie(getCurrentRetrieval().thisDomain, 
+                       getCurrentRetrieval().thisName, 
+                       thisValue,
+                       getCurrentRetrieval().thisPath,
+                       getCurrentRetrieval().thisDate,
+                       getCurrentRetrieval().isSecure);
+               } else if (getCurrentRetrieval().thisPath != null &&
+                       getCurrentRetrieval().thisAge >= 0)
+               {
+               System.out.println("2");
+               thisCookie = new Cookie(getCurrentRetrieval().thisDomain, 
+                       getCurrentRetrieval().thisName, 
+                       thisValue,
+                       getCurrentRetrieval().thisPath,
+                       getCurrentRetrieval().thisAge,
+                       getCurrentRetrieval().isSecure);
+               } else {
+               System.out.println("3");
+               thisCookie = new Cookie(getCurrentRetrieval().thisDomain, 
+                       getCurrentRetrieval().thisName, 
+                       thisValue);
+               }
+                getCurrentRetrieval().sethcookies.addElement(thisCookie);
+                current_state = getCurrentRetrieval().toDo;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a end cookie element");
+        }
+    }
+
+    protected void startMethodElement(Attributes attributes) {
+        switch (current_state) {
+            case STATE_INSIDE_EXECUTE_RETRIEVAL :
+                current_value.setLength(0);
+                current_state = sethTransformer.STATE_INSIDE_METHOD_ELEMENT;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a start method element");
+        }
+    }
+
+    protected void endMethodElement() {
+        switch (current_state) {
+            case sethTransformer.STATE_INSIDE_METHOD_ELEMENT :
+                getCurrentRetrieval().method = current_value.toString().trim().toUpperCase();
+                current_state = getCurrentRetrieval().toDo;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a end method element");
+        }
+    }
+
+    protected void startUrlElement(Attributes attributes) {
+        switch (current_state) {
+            case STATE_INSIDE_EXECUTE_RETRIEVAL :
+                current_value.setLength(0);
+                current_state = sethTransformer.STATE_INSIDE_URL_ELEMENT;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a start url element");
+        }
+    }
+
+    protected void endUrlElement() {
+        switch (current_state) {
+            case sethTransformer.STATE_INSIDE_URL_ELEMENT :
+                getCurrentRetrieval().url = current_value.toString();
+                current_state = getCurrentRetrieval().toDo;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a end url element");
+        }
+    }
+
+    protected void startUsernameElement(Attributes attributes) {
+        switch (current_state) {
+            case STATE_INSIDE_EXECUTE_RETRIEVAL :
+                current_value.setLength(0);
+                current_state = sethTransformer.STATE_INSIDE_USERNAME_ELEMENT;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a start username element");
+        }
+    }
+
+    protected void endUsernameElement() {
+        switch (current_state) {
+            case sethTransformer.STATE_INSIDE_USERNAME_ELEMENT :
+                getCurrentRetrieval().username = current_value.toString();
+                current_state = getCurrentRetrieval().toDo;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a end username element");
+        }
+    }
+
+    protected void startPasswordElement(Attributes attributes) {
+        switch (current_state) {
+            case STATE_INSIDE_EXECUTE_RETRIEVAL :
+                current_value.setLength(0);
+                current_state = sethTransformer.STATE_INSIDE_PASSWORD_ELEMENT;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a start password element");
+        }
+    }
+
+    protected void endPasswordElement() {
+        switch (current_state) {
+            case sethTransformer.STATE_INSIDE_PASSWORD_ELEMENT :
+                getCurrentRetrieval().password = current_value.toString();
+                current_state = getCurrentRetrieval().toDo;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a end password element");
+        }
+    }
+
+    protected void startLimitElement(Attributes attributes) {
+        switch (current_state) {
+            case STATE_INSIDE_EXECUTE_RETRIEVAL :
+                current_value.setLength(0);
+                current_state = sethTransformer.STATE_INSIDE_LIMIT_ELEMENT;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a start limit element");
+        }
+    }
+
+    protected void endLimitElement() {
+        switch (current_state) {
+            case sethTransformer.STATE_INSIDE_LIMIT_ELEMENT :
+                getCurrentRetrieval().limit = current_value.toString().trim().toUpperCase();
+                current_state = getCurrentRetrieval().toDo;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a end limit element");
+        }
+    }
+    protected void startUserAgentElement(Attributes attributes) {
+        switch (current_state) {
+            case STATE_INSIDE_EXECUTE_RETRIEVAL :
+                current_value.setLength(0);
+                current_state = sethTransformer.STATE_INSIDE_USERAGENT_ELEMENT;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a start useragent element");
+        }
+    }
+
+    protected void endUserAgentElement() {
+        switch (current_state) {
+            case sethTransformer.STATE_INSIDE_USERAGENT_ELEMENT :
+                getCurrentRetrieval().useragent = current_value.toString().trim();
+                current_state = getCurrentRetrieval().toDo;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a end useragent element");
+        }
+    }
+
+    protected void startTimeoutElement(Attributes attributes) {
+        switch (current_state) {
+            case STATE_INSIDE_EXECUTE_RETRIEVAL :
+                current_value.setLength(0);
+                current_state = sethTransformer.STATE_INSIDE_TIMEOUT_ELEMENT;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a start timeout element");
+        }
+    }
+
+    protected void endTimeoutElement() {
+        switch (current_state) {
+            case sethTransformer.STATE_INSIDE_TIMEOUT_ELEMENT :
+                getCurrentRetrieval().timeout = Integer.parseInt(current_value.toString());
+                current_state = getCurrentRetrieval().toDo;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a end timeout element");
+        }
+    }
+
+    protected void startRedirectLimitElement(Attributes attributes) {
+        switch (current_state) {
+            case STATE_INSIDE_EXECUTE_RETRIEVAL :
+                current_value.setLength(0);
+                current_state = sethTransformer.STATE_INSIDE_REDIRECT_LIMIT_ELEMENT;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a start redirect_limit element");
+        }
+    }
+
+    protected void endRedirectLimitElement() {
+        switch (current_state) {
+            case sethTransformer.STATE_INSIDE_REDIRECT_LIMIT_ELEMENT :
+                getCurrentRetrieval().redirect_limit = Integer.parseInt(current_value.toString());
+                current_state = getCurrentRetrieval().toDo;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a end redirect_limit element");
+        }
+    }
+
+    protected void startRegExpElement(Attributes attributes) {
+        switch (current_state) {
+            case STATE_INSIDE_EXECUTE_RETRIEVAL :
+                current_value.setLength(0);
+                current_state = sethTransformer.STATE_INSIDE_REGEXP_ELEMENT;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a start regexp element");
+        }
+    }
+
+    protected void endRegExpElement() {
+        switch (current_state) {
+            case sethTransformer.STATE_INSIDE_REGEXP_ELEMENT :
+                getCurrentRetrieval().regexp = current_value.toString();
+                current_state = getCurrentRetrieval().toDo;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a end regexp element");
+        }
+    }
+    protected void startRedirectElement(Attributes attributes) {
+        switch (current_state) {
+            case STATE_INSIDE_EXECUTE_RETRIEVAL :
+                current_value.setLength(0);
+                current_state = sethTransformer.STATE_INSIDE_REDIRECT_ELEMENT;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a start redirect element");
+        }
+    }
+
+    protected void endRedirectElement() {
+        switch (current_state) {
+            case sethTransformer.STATE_INSIDE_REDIRECT_ELEMENT :
+                if (current_value.toString().toUpperCase().equals("FALSE")) {
+                    getCurrentRetrieval().redirect = false;
+                }
+                current_state = getCurrentRetrieval().toDo;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a end redirect element");
+        }
+    }
+
+    protected void startDebugElement(Attributes attributes) {
+        switch (current_state) {
+            case STATE_INSIDE_EXECUTE_RETRIEVAL :
+                current_value.setLength(0);
+                current_state = sethTransformer.STATE_INSIDE_DEBUG_ELEMENT;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a start debug element");
+        }
+    }
+
+    protected void endDebugElement() {
+        switch (current_state) {
+            case sethTransformer.STATE_INSIDE_DEBUG_ELEMENT :
+                if (current_value.toString().toUpperCase().equals("TRUE")) {
+                    getCurrentRetrieval().debug = true;
+                }
+                current_state = getCurrentRetrieval().toDo;
+                break;
+            default :
+                throwIllegalStateException("Not expecting a end debug element");
+        }
+    }
+
+    protected HTMLRetrieval getCurrentRetrieval() {
+        return (HTMLRetrieval) retrievals.elementAt(current_retrieval_index);
+    }
+
+    protected HTMLRetrieval getRetrieval(int i) {
+        return (HTMLRetrieval) retrievals.elementAt(i);
+    }
+
+    /** END my very own methods */
+
+    /** BEGIN SAX ContentHandler handlers */
+
+    public void setDocumentLocator(Locator locator) {
+        if (getLogger().isDebugEnabled()) {
+            getLogger().debug("PUBLIC ID: " + locator.getPublicId());
+            getLogger().debug("SYSTEM ID: " + locator.getSystemId());
+        }
+        if (super.contentHandler != null)
+            super.contentHandler.setDocumentLocator(locator);
+    }
+
+    public void startElement(String uri, String name, String raw, Attributes attributes) throws SAXException {
+        if (!uri.equals(my_uri)) {
+            super.startElement(uri, name, raw, attributes);
+            return;
+        }
+        getLogger().debug("RECEIVED START ELEMENT " + name + "(" + uri + ")");
+
+       if (name.equals(sethTransformer.MAGIC_EXECUTE_RETRIEVAL)) {
+            startExecuteRetrieval(attributes);
+        } else if (name.equals(sethTransformer.MAGIC_NVP_ELEMENT)) {
+            startNvpElement(attributes);
+        } else if (name.equals(sethTransformer.MAGIC_COOKIE_ELEMENT)) {
+            startCookieElement(attributes);
+        } else if (name.equals(sethTransformer.MAGIC_METHOD_ELEMENT)) {
+            startMethodElement(attributes);
+        } else if (name.equals(sethTransformer.MAGIC_URL_ELEMENT)) {
+            startUrlElement(attributes);
+        } else if (name.equals(sethTransformer.MAGIC_USERNAME_ELEMENT)) {
+            startUsernameElement(attributes);
+        } else if (name.equals(sethTransformer.MAGIC_PASSWORD_ELEMENT)) {
+            startPasswordElement(attributes);
+        } else if (name.equals(sethTransformer.MAGIC_LIMIT_ELEMENT)) {
+            startLimitElement(attributes);
+        } else if (name.equals(sethTransformer.MAGIC_USERAGENT_ELEMENT)) {
+            startUserAgentElement(attributes);
+        } else if (name.equals(sethTransformer.MAGIC_TIMEOUT_ELEMENT)) {
+            startTimeoutElement(attributes);
+        } else if (name.equals(sethTransformer.MAGIC_REDIRECT_LIMIT_ELEMENT)) {
+            startRedirectLimitElement(attributes);
+        } else if (name.equals(sethTransformer.MAGIC_REGEXP_ELEMENT)) {
+            startRegExpElement(attributes);
+        } else if (name.equals(sethTransformer.MAGIC_REDIRECT_ELEMENT)) {
+            startRedirectElement(attributes);
+        } else if (name.equals(sethTransformer.MAGIC_DEBUG_ELEMENT)) {
+            startDebugElement(attributes);
+        }
+    }
+
+    public void endElement(String uri, String name, String raw) throws SAXException {
+        if (!uri.equals(my_uri)) {
+            super.endElement(uri, name, raw);
+            return;
+        }
+        getLogger().debug("RECEIVED END ELEMENT " + name + "(" + uri + ")");
+
+        if (name.equals(sethTransformer.MAGIC_EXECUTE_RETRIEVAL)) {
+            endExecuteRetrieval();
+       } else if (name.equals(sethTransformer.MAGIC_NVP_ELEMENT)) {
+            endNvpElement();
+       } else if (name.equals(sethTransformer.MAGIC_COOKIE_ELEMENT)) {
+            endCookieElement();
+       } else if (name.equals(sethTransformer.MAGIC_METHOD_ELEMENT)) {
+            endMethodElement();
+       } else if (name.equals(sethTransformer.MAGIC_URL_ELEMENT)) {
+            endUrlElement();
+       } else if (name.equals(sethTransformer.MAGIC_USERNAME_ELEMENT)) {
+            endUsernameElement();
+       } else if (name.equals(sethTransformer.MAGIC_PASSWORD_ELEMENT)) {
+            endPasswordElement();
+       } else if (name.equals(sethTransformer.MAGIC_LIMIT_ELEMENT)) {
+            endLimitElement();
+       } else if (name.equals(sethTransformer.MAGIC_USERAGENT_ELEMENT)) {
+            endUserAgentElement();
+       } else if (name.equals(sethTransformer.MAGIC_TIMEOUT_ELEMENT)) {
+            endTimeoutElement();
+       } else if (name.equals(sethTransformer.MAGIC_REDIRECT_LIMIT_ELEMENT)) {
+            endRedirectLimitElement();
+       } else if (name.equals(sethTransformer.MAGIC_REGEXP_ELEMENT)) {
+            endRegExpElement();
+        } else if (name.equals(sethTransformer.MAGIC_REDIRECT_ELEMENT)) {
+            endRedirectElement();
+        } else if (name.equals(sethTransformer.MAGIC_DEBUG_ELEMENT)) {
+            endDebugElement();
+       }
+    }
+
+    public void characters(char ary[], int start, int length) throws SAXException {
+        if (current_state != sethTransformer.STATE_INSIDE_NVP_ELEMENT
+               && current_state != sethTransformer.STATE_INSIDE_COOKIE_ELEMENT
+               && current_state != sethTransformer.STATE_INSIDE_METHOD_ELEMENT
+               && current_state != sethTransformer.STATE_INSIDE_URL_ELEMENT
+               && current_state != sethTransformer.STATE_INSIDE_USERNAME_ELEMENT
+               && current_state != sethTransformer.STATE_INSIDE_PASSWORD_ELEMENT
+               && current_state != sethTransformer.STATE_INSIDE_LIMIT_ELEMENT
+               && current_state != sethTransformer.STATE_INSIDE_USERAGENT_ELEMENT
+               && current_state != sethTransformer.STATE_INSIDE_TIMEOUT_ELEMENT
+               && current_state != sethTransformer.STATE_INSIDE_REDIRECT_LIMIT_ELEMENT
+               && current_state != sethTransformer.STATE_INSIDE_REGEXP_ELEMENT
+               && current_state != sethTransformer.STATE_INSIDE_REDIRECT_ELEMENT
+               && current_state != sethTransformer.STATE_INSIDE_DEBUG_ELEMENT) 
+       {
+            super.characters(ary, start, length);
+        }
+        getLogger().debug("RECEIVED CHARACTERS: " + new String(ary, start, length));
+        current_value.append(ary, start, length);
+    }
+
+    private void attribute(AttributesImpl attr, String name, String value) {
+        attr.addAttribute("", name, name, "CDATA", value);
+    }
+
+    private void start(String name, AttributesImpl attr) throws SAXException {
+        super.contentHandler.startElement("", name, name, attr);
+        attr.clear();
+    }
+
+    private void end(String name) throws SAXException {
+        super.contentHandler.endElement("", name, name);
+    }
+
+    private void data(String data) throws SAXException {
+        if (data != null)
+            super.contentHandler.characters(data.toCharArray(), 0, data.length());
+    }
+
+    protected static String getStringValue(Object object) {
+        if (object instanceof byte[]) {
+            return new String((byte[]) object);
+        } else if (object instanceof char[]) {
+            return new String((char[]) object);
+        } else if (object != null) {
+            return object.toString();
+        } else {
+            return "";
+        }
+    }
+
+    public final Logger getTheLogger() {
+        return getLogger();
+    }
+
+    class HTMLRetrieval {
+
+        /** Index for retrievals list */
+        protected int retrieval_index;
+
+        /** The current state of the event */
+        protected int current_state;
+
+        protected sethTransformer transformer;
+
+       protected String url = "http://127.0.0.1";
+
+       protected String username = null;
+
+       protected String password = null;
+
+       protected String limit = null;
+
+       protected String useragent = null;
+
+       protected int timeout = 0;
+
+       protected int redirect_limit = 5;
+
+       protected String regexp = null;
+
+       protected RE sethRE;
+
+       protected String method = "GET";
+
+       protected String cookieType = "NAME";
+
+       protected Vector nvps = new Vector();
+
+       protected Vector sethcookies = new Vector();
+
+       protected int toDo;
+
+       //NVP values
+       protected String nvpName = null;
+       protected String jsspace = null;
+
+       //Cookie values
+       protected String thisDomain = null;
+       protected String thisName = null;
+       protected String thisPath = null;
+       protected Date thisDate = null;
+       protected int thisAge = -1;
+       protected boolean isSecure = false;
+
+       protected int sequence = 1;
+
+       protected StringBuffer textBucket = new StringBuffer();
+               
+       protected AttributesImpl attr = new AttributesImpl();
+
+       protected HttpClient _httpClient;
+
+        protected HttpMethod _httpMethod;
+
+       protected boolean redirect = true;
+
+       protected int limitTagBlock = 0;
+
+       protected boolean debug = false;
+
+       //work through elements
+        protected HTMLRetrieval(sethTransformer transformer) {
+               this.transformer = transformer;
+
+               if (null != transformer.
+                       default_properties.
+                       getProperty(sethTransformer.MAGIC_NVP_ELEMENT)) 
+               {
+                       nvps.addElement(transformer.
+                               default_properties.
+                               getProperty(sethTransformer.
+                               MAGIC_NVP_ELEMENT));
+               }
+
+               if (null != transformer.
+                       default_properties.
+                       getProperty(sethTransformer.MAGIC_COOKIE_ELEMENT)) 
+               {
+                       sethcookies.addElement(transformer.
+                               default_properties.
+                               getProperty(sethTransformer.
+                               MAGIC_COOKIE_ELEMENT));
+               }
+
+               if (null != transformer.
+                       default_properties.
+                       getProperty(sethTransformer.MAGIC_METHOD_ELEMENT)) 
+               {
+                       method = transformer.
+                               default_properties.
+                               getProperty(sethTransformer.
+                               MAGIC_METHOD_ELEMENT);
+               }
+
+               if (null != transformer.
+                       default_properties.
+                       getProperty(sethTransformer.MAGIC_URL_ELEMENT)) 
+               {
+                       url = transformer.
+                               default_properties.
+                               getProperty(sethTransformer.
+                               MAGIC_URL_ELEMENT);
+               }
+
+               if (null != transformer.
+                       default_properties.
+                       getProperty(sethTransformer.MAGIC_USERNAME_ELEMENT)) 
+               {
+                       username = transformer.
+                               default_properties.
+                               getProperty(sethTransformer.
+                               MAGIC_USERNAME_ELEMENT);
+               }
+
+               if (null != transformer.
+                       default_properties.
+                       getProperty(sethTransformer.MAGIC_PASSWORD_ELEMENT)) 
+               {
+                       password = transformer.
+                               default_properties.
+                               getProperty(sethTransformer.
+                               MAGIC_PASSWORD_ELEMENT);
+               }
+
+               if (null != transformer.
+                       default_properties.
+                       getProperty(sethTransformer.MAGIC_LIMIT_ELEMENT)) 
+               {
+                       limit = transformer.
+                               default_properties.
+                               getProperty(sethTransformer.
+                               MAGIC_LIMIT_ELEMENT);
+               }
+
+               if (null != transformer.
+                       default_properties.
+                       getProperty(sethTransformer.MAGIC_USERAGENT_ELEMENT)) 
+               {
+                       useragent = transformer.
+                               default_properties.
+                               getProperty(sethTransformer.
+                               MAGIC_USERAGENT_ELEMENT);
+               }
+
+               if (null != transformer.
+                       default_properties.
+                       getProperty(sethTransformer.MAGIC_TIMEOUT_ELEMENT)) 
+               {
+                       timeout = Integer.parseInt(transformer.
+                               default_properties.
+                               getProperty(sethTransformer.
+                               MAGIC_TIMEOUT_ELEMENT));
+               }
+
+               if (null != transformer.
+                       default_properties.
+                       getProperty(sethTransformer.MAGIC_REDIRECT_LIMIT_ELEMENT)) 
+               {
+                       redirect_limit = Integer.parseInt(transformer.
+                               default_properties.
+                               getProperty(sethTransformer.
+                               MAGIC_REDIRECT_LIMIT_ELEMENT));
+               }
+
+               if (null != transformer.
+                       default_properties.
+                       getProperty(sethTransformer.MAGIC_REGEXP_ELEMENT)) 
+               {
+                       regexp = transformer.
+                               default_properties.
+                               getProperty(sethTransformer.
+                               MAGIC_REGEXP_ELEMENT);
+               }
+
+               if (null != transformer.
+                       default_properties.
+                       getProperty(sethTransformer.MAGIC_REDIRECT_ELEMENT)) 
+               {
+                       redirect = transformer.
+                               default_properties.
+                               getProperty(sethTransformer.
+                               MAGIC_REDIRECT_ELEMENT).equals("TRUE") ? true : false;
+               }
+
+               if (null != transformer.
+                       default_properties.
+                       getProperty(sethTransformer.MAGIC_DEBUG_ELEMENT)) 
+               {
+                       debug = transformer.
+                               default_properties.
+                               getProperty(sethTransformer.
+                               MAGIC_DEBUG_ELEMENT).equals("TRUE") ? true : false;
+               }
+
+
+       } //HTMLRetrieval
+
+       // set up DOM and execute http request
+        protected void execute() throws Exception {
+               int ret;
+
+               //start with regexp
+               if (regexp != null) {
+                       try {
+                               sethRE = new RE(regexp);
+                       } catch (RESyntaxException reex) {
+                               transformer.getTheLogger().debug("[sethTransformer] " +
+                                       "compiling regular expression  problem " + 
+                                       reex.toString());
+                               regexp = null;
+                       }
+               }
+
+               if (debug) 
+                       debugPrint();
+               try {
+                       // Setup an instance of Tidy.
+                       Tidy tidy = new Tidy();
+                       tidy.setXmlOut(true);
+                       tidy.setXHTML(true);
+                       tidy.setIndentAttributes(true);
+
+                       tidy.setShowWarnings(getLogger().isWarnEnabled());
+
+                       tidy.setQuiet(!getLogger().isInfoEnabled());
+                       StringWriter stringWriter = new StringWriter();
+                       PrintWriter errorWriter = new PrintWriter(stringWriter);
+
+                       tidy.setErrout(errorWriter); 
+
+
+                       HttpMethod _httpMethod = workOutHttpMethod(url, username, password);
+                       URL thisUrl = new URL(url);
+                        HttpURLConnection _httpURLConnection = new HttpURLConnection(_httpMethod, thisUrl);
+                       System.out.println("lm: " + _httpURLConnection.getLastModified());
+                       Date last_modified = new Date(_httpURLConnection.getLastModified());
+
+                       org.w3c.dom.Document doc = tidy.parseDOM(new
+                               BufferedInputStream(_httpMethod.getResponseBodyAsStream()), null);
+
+                       XMLUtils.stripDuplicateAttributes(doc, null);
+
+                       Element docRoot = doc.getDocumentElement();
+
+                       Cookie[] cookies = _httpClient.getState().getCookies();
+
+                       Header[] responseHeaders = _httpMethod.getResponseHeaders();
+
+                       Header[] requestHeaders = _httpMethod.getRequestHeaders();
+
+                       //_httpClient.endSession();
+                       transformer.start(RESULTS_ELEMENT, attr);
+
+                       transformer.start(URL_ELEMENT, attr);
+                       transformer.data(url);
+                       transformer.end(URL_ELEMENT);
+
+                       transformer.start(RESPONSE_ELEMENT, attr);
+                       for (int i=0; i<responseHeaders.length;i++) {
+                               transformer.start("response",nvpAttributes(responseHeaders[i].getName()));
+                               System.out.println("res " + responseHeaders[i].getValue());
+                               transformer.data(responseHeaders[i].getValue());
+                               transformer.end("response");
+                       }
+                       //special date
+                       transformer.start("response",nvpAttributes("last_modified_check"));
+                       transformer.data(last_modified.toString());
+                       transformer.end("response");
+                       transformer.end(RESPONSE_ELEMENT);
+
+                       transformer.start(REQUEST_ELEMENT, attr);
+                       for (int i=0; i<requestHeaders.length;i++) {
+                               transformer.start("request",nvpAttributes(requestHeaders[i].getName()));
+                               System.out.println("req " + requestHeaders[i].getValue());
+                               transformer.data(requestHeaders[i].getValue());
+                               transformer.end("request");
+                       }
+                       transformer.end(REQUEST_ELEMENT);
+
+                       transformer.start(COOKIES_ELEMENT, attr);
+                       for (int i = 0; i < cookies.length; i++) {
+                               transformer.start("cookie",cookieAttributes(cookies[i]));
+                               transformer.data(cookies[i].getValue());
+                               transformer.end("cookie");
+                       }
+                       transformer.end(COOKIES_ELEMENT);
+
+                       transformer.start(CONTENTS_ELEMENT,attr);
+                       traverse(doc);
+                       transformer.end(CONTENTS_ELEMENT);
+
+                       transformer.end(RESULTS_ELEMENT);
+
+                       errorWriter.flush();
+                       errorWriter.close();
+
+                       if(getLogger().isWarnEnabled()){
+                                       getLogger().warn(stringWriter.toString());
+                       }
+               } catch (Exception e){
+                       getLogger().error("problem: ", e);
+                       throw new ProcessingException("Exception in sethTransformer.execute",e);
+               }
+        } //execute
+  
+       protected AttributesImpl nvpAttributes(String theName) 
+       throws IOException, SAXException
+       {
+               AttributesImpl nvpAtts = new AttributesImpl();
+               nvpAtts.addAttribute( null,
+                       "name","name",
+                       "CDATA",theName);
+
+               return nvpAtts;
+       }
+
+       protected AttributesImpl cookieAttributes(Cookie theCookie) 
+       throws IOException, SAXException
+       {
+               AttributesImpl cookieAtts = new AttributesImpl();
+               cookieAtts.addAttribute( null,
+                       "name","name",
+                       "CDATA",theCookie.getName());
+               if (theCookie.getDomain() != null)
+                       cookieAtts.addAttribute( null,
+                               "domain","domain",
+                               "CDATA",theCookie.getDomain());
+               if (theCookie.getPath() != null)
+                       cookieAtts.addAttribute( null,
+                               "path","path",
+                               "CDATA",theCookie.getPath());
+               if (theCookie.getExpiryDate() != null)
+                       cookieAtts.addAttribute( null,
+                               "date","date",
+                               "CDATA",theCookie.getExpiryDate().toString());
+               if (theCookie.getSecure() == true)
+                       cookieAtts.addAttribute( null,
+                               "secure","secure",
+                               "CDATA","TRUE");
+
+               return cookieAtts;
+       }
+
+       protected HttpMethod workOutHttpMethod(String url, String username, String password) {
+               int result = 0;
+               String redirectLocation = "";
+               try {
+                       Header locationHeader = null;
+                       URL u = new URL(url);
+
+                       //custom ssl to handle self-signed certificates
+                       Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
+                       Protocol.registerProtocol("https", easyhttps);
+
+                       _httpClient = new HttpClient();
+
+                       HttpState state = new HttpState();
+
+                       if (useragent != null) {
+                               System.getProperties().
+                                       setProperty("httpclient.useragent", 
+                                       useragent);
+                       }
+
+
+                       //should open this up for generator control
+                       state.setCookiePolicy(CookiePolicy.COMPATIBILITY);
+
+                       //how to add your own cookie
+                       //Cookie mycookie = new Cookie("privcom.gc.ca", "mycookie", "stuff", "/", null, false);
+                       //state.addCookie(mycookie);
+
+                       for (int i=0; i<sethcookies.size(); i++) {
+                               Cookie theCookie = (Cookie) sethcookies.elementAt(i);
+                               state.addCookie(theCookie);
+                       }
+
+                       _httpClient.setState(state);
+
+                       // HTTP-Method
+                       if(method.equals("POST")) {
+                               _httpMethod = new PostMethod(u.getPath());              
+                               System.out.println("posting ");
+                               //((PostMethod) _httpMethod).setUseDisk(false);           
+
+                               for (int i=0; i<nvps.size(); i++) {
+                                       NameValuePair formNVP = (NameValuePair) nvps.
+                                               elementAt(i);
+                                       //System.out.println("adding " + formNVP);
+                                       ((PostMethod) _httpMethod).
+                                               addParameter(formNVP);
+                               }
+                       } else {
+                               _httpMethod = new GetMethod(u.getPath());
+                               //((GetMethod) _httpMethod).setUseDisk(false);
+                               if (nvps.size() > 0) {
+                                       String qs = ((HttpMethod) _httpMethod).getQueryString();
+                                       NameValuePair nvpa[] = new NameValuePair[nvps.size()];
+                                       ((HttpMethod) _httpMethod).setQueryString((NameValuePair []) 
+                                               nvps.toArray(nvpa));
+                                       if (qs != null) {
+                                               ((HttpMethod) _httpMethod).
+                                                       setQueryString(qs + "&" + 
+                                                       ((HttpMethod) _httpMethod).
+                                                       getQueryString());
+                                       }
+                               }
+                       }
+                       System.out.println("0");
+
+                       if (timeout > 0)
+                               _httpClient.setTimeout(timeout * 1000);
+
+                       
+                        if (method.equals("GET"))
+                               ((HttpMethod) _httpMethod).setFollowRedirects(redirect);
+                       /* setFollowRedirects won't work for a post, need somethng like this
+                        if (method.equals("POST")) {
+                                URI redirectLocation = new URI(
+                                        ((HttpMethod) _httpMethod).getURI(),
+                                ((HttpMethod) _httpMethod).getResponseHeader("location").
+                                        getValue()
+                        );
+                       */
+
+                       System.out.println("1");
+
+                       // HTTPSession
+                       //_httpClient.startSession(u);
+                       HostConfiguration hostConfig = _httpClient.getHostConfiguration();
+                       System.out.println("3");
+                       hostConfig.setHost(u.getHost(),u.getPort(),u.getProtocol());
+
+                       /* - would we ever set these?
+                       for(int i = 0; i < this.header.size(); i++) {
+                               ((HttpMethod) _httpMethod).setRequestHeader( 
+                                       (Header) this.header.elementAt(i));
+                       }
+                       */
+
+                       System.out.println("4");
+                       // value for "accept-encoding" must be empty
+                       ((HttpMethod) _httpMethod).
+                               setRequestHeader("accept-encoding", "");
+
+                       /*
+                       ((HttpMethod) _httpMethod).
+                       setRequestHeader(
+                               "Content-Type", 
+                               "text/plain; charset=utf-8");
+                       */
+
+
+                       System.out.println("username is " +
+                               username + " and " + password);
+                       if (username != null && password != null) {
+                               System.out.println("host is " + u.getHost());
+                               /*
+                               Credentials defaultcreds = new UsernamePasswordCredentials(username, password);
+                               _httpClient.getState().setCredentials(null, u.getHost(), defaultcreds);
+                               _httpClient.getState().setAuthenticationPreemptive(true);
+                               */
+
+                               List authPrefs =  new ArrayList(2);
+                               authPrefs.add(AuthPolicy.DIGEST );
+                               authPrefs.add(AuthPolicy.BASIC);
+                               _httpClient.getParams().setParameter (AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);
+                               _httpClient.getParams().setAuthenticationPreemptive(true);
+                               Credentials defaultcreds = new UsernamePasswordCredentials(username, password); 
+                               //_httpClient.getState().setCredentials(new AuthScope( u.getHost(), 443, AuthScope.ANY_REALM), defaultcreds);
+                               _httpClient.getState().setCredentials(null, u.getHost(), defaultcreds);
+                       }
+
+                       try {
+                       System.out.println("here goes");
+                       result = _httpClient.executeMethod(_httpMethod);                                
+                       System.out.println("the result - " + result);
+                       } catch (Exception ex) {
+                       System.out.println("oh oh");
+                       System.out.println(ex.toString());
+                       }
+                       int num_redirects = 0;
+
+                       while (result == HttpStatus.SC_MOVED_TEMPORARILY &&
+                               num_redirects++ < redirect_limit) {
+                               //will need to make this a parameter at some point
+                               locationHeader = 
+                                       ((HttpMethod) _httpMethod).
+                                               getResponseHeader("location");
+                               if (locationHeader != null) {
+                                       redirectLocation = 
+                                               locationHeader.getValue();
+                                       System.out.println("suggesting " +
+                                               redirectLocation);
+                                       //I am assuming a redirect is always a GET
+                                       //If not, we would need something like this
+/*
+                                       if (method.equals("GET")) {
+                                               _httpMethod = new GetMethod(redirectLocation);
+                                       } else {
+                                               _httpMethod = new PostMethod(
+                                                       redirectLocation);
+                                       }
+*/
+                                       _httpMethod = new GetMethod(redirectLocation);
+                                       System.out.println("result is now - " + result);
+                                       result = _httpClient.executeMethod(_httpMethod);                                
+                               }
+                       }
+
+                       Cookie[] cookies = _httpClient.getState().getCookies();
+                       if (username != null && password != null)
+                               _httpMethod.setDoAuthentication( true );
+
+                       return _httpMethod;
+               } catch (Exception e){
+                       getLogger().error("problem: ", e);
+               }
+
+               return null;
+       }
+
+       //  Traverse DOM Tree.  Print out Element Names
+       protected void traverse (Node node)
+       throws IOException, SAXException {
+               String name = "";
+               String value = "";
+               int numChildren = 0;
+
+               int type = node.getNodeType();
+               NodeList children = node.getChildNodes();
+               if (children != null)
+                       numChildren = children.getLength();
+
+               transformer.getTheLogger().debug("[sethTransformer] node type: " + type);
+               if (type == Node.ELEMENT_NODE) {
+                       name =
+                               node.getNodeName().trim();
+                       if (!checkLimitTags(name))
+                               transformer.start(name, copyAttributes(node));
+               }
+               if (type == Node.TEXT_NODE) {
+                       value =
+                               node.getNodeValue().trim();
+                       if (textBucket.length() > 0)
+                               textBucket.append(" ");
+                       textBucket.append(value);
+               }
+               if (children != null) {
+                       for (int i=0; i< numChildren; i++) 
+                               traverse (children.item(i));  
+               }
+               if (type == Node.ELEMENT_NODE) {
+                       if (regexp != null && textBucket.length() > 0) {
+                       try {
+                               String newText = 
+                                       textBucket.toString();
+                               
+                               if (sethRE.match(newText)) {
+                                       transformer.getTheLogger().debug("[sethTransformer] regexp: " + regexp +
+                                               " matches on " + newText);
+                                       /* RE matches ok, but doesn't extract properly, may not need */ 
+                                       /*
+                                               System.out.println("1> " + sethRE.getParenStart(0));
+                                               System.out.println("2> " + sethRE.getParenStart(1));
+                                               System.out.println("3> " + sethRE.getParenEnd(0));
+                                               System.out.println("4> " + sethRE.getParenEnd(1));
+                                               System.out.println("5> " + sethRE.getParen(0));
+                                               System.out.println("6> " + sethRE.getParen(1));
+                                       */
+
+                                       transformer.start(REGEXP_ELEMENT,attr);
+                                       transformer.data(newText);
+                                       transformer.end(REGEXP_ELEMENT);
+                                       textBucket.setLength(0);
+                               }
+                       } catch (Exception reex) {
+                               System.out.println("matching regular expression  problem " + reex.toString());
+                               regexp = null;
+                       }
+                       }
+                       if (textBucket.length() > 0) {
+                               if (!checkLimitTags(name))
+                                       transformer.data(textBucket.toString());
+                               textBucket.setLength(0);
+                       }
+                       if (!checkLimitTags(name))
+                               transformer.end(name);
+               }
+       }
+
+       protected boolean checkLimitTags(String currentTag) {
+               if (limit != null) {
+                       String thisLimit = "," + limit + ",";
+                       int limitNum = thisLimit.indexOf("," + currentTag.trim().toUpperCase() + ",");
+                       if (limitNum == -1 )
+                               return true;
+               }
+
+               return false;
+       }
+/*
+       protected boolean checkLimitTags(String currentTag,boolean atEnd,int numKids) {
+               if (limit != null) {
+                       String thisLimit = "," + limit + ",";
+                       int limitNum = thisLimit.indexOf("," + currentTag.trim().toUpperCase() + ",");
+                       System.out.println("working with " + currentTag);
+                       if (limitTagBlock > 0 && limitNum != -1 && atEnd) {
+                               System.out.println("stopping block for " + currentTag); 
+                               limitTagBlock--; 
+                               System.out.println("value is now " + limitTagBlock); 
+                       } else {
+                               if (limitNum == -1 && limitTagBlock <= 0) {
+                                       System.out.println("stop printing for " + currentTag);
+                                       return true;
+                               } else {
+                                       if (limitNum != -1 && numKids > 0) {
+                                               System.out.println("set block to true for  " + currentTag);
+                                               limitTagBlock++;
+                                               System.out.println("value is now " + limitTagBlock); 
+                                       }
+                               }
+                       }
+               }
+
+               return false;
+       }
+*/
+               
+
+       protected AttributesImpl copyAttributes(Node currentNode) 
+               throws IOException, SAXException
+       {
+               AttributesImpl currentAtts = new AttributesImpl();
+               NamedNodeMap map = currentNode.getAttributes();
+               currentAtts.clear();
+                   
+               for (int i = map.getLength() - 1; i >= 0; i--) {
+                       Attr att = (Attr) map.item(i);
+                       /*
+                       currentAtts.addAttribute( att.getNamespaceURI(),
+                                                 att.getLocalName(), att.getName(),
+                                                 "CDATA", att.getValue());
+                       */
+                       currentAtts.addAttribute(null,att.getName(), att.getName(),
+                                                 "CDATA", att.getValue());
+               }
+       
+               return currentAtts;
+       }
+
+       //show every element if working in DEBUG mode
+        protected void debugPrint() {
+            transformer.getTheLogger().debug("[sethTransformer] retrieval_index: " + retrieval_index);
+            transformer.getTheLogger().debug("[sethTransformer] # of nvps: " + nvps.size());
+            transformer.getTheLogger().debug("[sethTransformer] # of cookies: " + sethcookies.size());
+            transformer.getTheLogger().debug("[sethTransformer] url: " + url);
+            transformer.getTheLogger().debug("[sethTransformer] limit: " + limit);
+            transformer.getTheLogger().debug("[sethTransformer] redirect_limit: " + redirect_limit);
+            transformer.getTheLogger().debug("[sethTransformer] useragent: " + useragent);
+            transformer.getTheLogger().debug("[sethTransformer] timeout: " + timeout);
+            transformer.getTheLogger().debug("[sethTransformer] redirect: " + redirect);
+            transformer.getTheLogger().debug("[sethTransformer] regexp: " + regexp);
+        }
+
+    }
+}